Jak powiedzieć CMake, aby utworzył łącze w bibliotece statycznej w katalogu źródłowym?

98

Mam mały projekt z plikiem Makefile, który próbuję przekonwertować na CMake, głównie po to, aby zdobyć doświadczenie z CMake. Na potrzeby tego przykładu projekt zawiera plik źródłowy (C ++, chociaż nie sądzę, aby język był szczególnie odpowiedni) i plik biblioteki statycznej, który skopiowałem z innego miejsca. Załóżmy, że kod źródłowy biblioteki jest niedostępny; Mam tylko plik .a i odpowiedni nagłówek.

Mój ręcznie robiony plik Makefile zawiera następującą zasadę budowy:

main: main.o libbingitup.a
    g++ -o main main.o libbingitup.a

co działa dobrze. Jak powiedzieć CMake, aby to odtworzył? Oczywiście nie dosłownie ten plik makefile, ale coś, co zawiera równoważne polecenie łączenia. Próbowałem oczywistych, ale naiwnych sposobów

add_executable(main main.cpp libbingitup.a)

lub

add_executable(main main.cpp)
target_link_libraries(main libbingitup.a)

jak również różne rzeczy z link_directories(.)lub add_library(bingitup STATIC IMPORTED)itp., ale jak dotąd nic nie skutkuje udanym powiązaniem. Co mam robić?


Szczegóły wersji: CMake 2.8.7 na Linuksie (Kubuntu 12.04) z GCC 4.6.3

David Z
źródło

Odpowiedzi:

123

CMake preferuje przekazywanie pełnej ścieżki do łączenia bibliotek, więc zakładając, że libbingitup.a jest włączony ${CMAKE_SOURCE_DIR}, wykonanie następujących czynności powinno zakończyć się sukcesem:

add_executable(main main.cpp)
target_link_libraries(main ${CMAKE_SOURCE_DIR}/libbingitup.a)
Fraser
źródło
2
Świetnie, to działa, dzięki! Wydaje się trochę hakerskie, że trzeba tu podać pełną ścieżkę, ale myślę, że to tylko sposób CMake ...
David Z,
4
Zgadzam się, że wydaje się to przesadą, ale wyraźne określenie pełnej ścieżki opłaca się, jeśli masz zainstalowanych wiele różnych wersji tej samej biblioteki.
Fraser
1
Niesamowite, jak zwykle! W moim przypadku rozwiązano problem bibliotek zależnych od innej zbudowanej biblioteki dynamicznej, która była zależna od biblioteki statycznej: biblioteki zależne również próbowały linkować do tej biblioteki statycznej.
Antonio
1
Skąd main wie o katalogach włączania?
ManuelSchneid3r
3
Musisz użyć target_include_directorieslub include_directories(ten pierwszy jest preferowany, ponieważ jest bardziej szczegółowy).
Fraser
32

Jeśli nie chcesz uwzględniać pełnej ścieżki, możesz to zrobić

add_executable(main main.cpp)
target_link_libraries(main bingitup)

bingitup to ta sama nazwa, którą nadasz celowi, jeśli utworzysz bibliotekę statyczną w projekcie CMake:

add_library(bingitup STATIC bingitup.cpp)

CMake automatycznie dodaje na libpoczątku i .ana końcu w Linuksie i .libna końcu w Windows.

Jeśli biblioteka jest zewnętrzna, możesz dodać ścieżkę do biblioteki za pomocą

link_directories(/path/to/libraries/)
Cris Luengo
źródło
1
A jeśli istnieją pliki .a i .so o tej samej nazwie, jak określisz, czy chcesz połączyć z .a lub .so w tym przypadku?
George
1
@George: Nie możesz. Jeśli masz oba typy, podaj pełną nazwę pliku, z którym chcesz utworzyć łącze.
Cris Luengo
21

Uważam, że to pomocne ...

http://www.cmake.org/pipermail/cmake/2011-June/045222.html

Z ich przykładu:

ADD_LIBRARY(boost_unit_test_framework STATIC IMPORTED)
SET_TARGET_PROPERTIES(boost_unit_test_framework PROPERTIES IMPORTED_LOCATION /usr/lib/libboost_unit_test_framework.a)
TARGET_LINK_LIBRARIES(mytarget A boost_unit_test_framework C)
stu
źródło
3
A co z INCLUDE_DIRECTORIES?
kyb
1
Działa to tylko wtedy, gdy biblioteka jest częścią kompilacji cmake, ale te zagraniczne to nie działa
eigenfield
pytanie brzmi: „projekt zawiera plik źródłowy (C ++, chociaż nie sądzę, aby język był szczególnie istotny) i plik biblioteki statycznej, który skopiowałem z innego miejsca”.
stu