CMake link do zewnętrznej biblioteki

Jak zmusić CMake do połączenia pliku wykonywalnego z zewnętrzną biblioteką współdzieloną, która nie jest zbudowana w ramach tego samego projektu CMake?

Samo robienie target_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so) daje błąd

make[2]: *** No rule to make target `res/mylib.so', needed by `GLBall'.  Stop.
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2
make: *** [all] Error 2
(GLBall is the executable)

Po skopiowaniu biblioteki do katalogu binarnego bin/res.

Próbowałem użyć find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

, która nie powiodła się z RESULT-NOTFOUND.

Author: usr1234567, 2012-01-08

4 answers

Ustaw najpierw ścieżkę wyszukiwania bibliotek:

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

And then just do

TARGET_LINK_LIBRARIES(GLBall mylib)
 78
Author: arrowd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-08 08:59:16

Odpowiedź Arrowdodgera jest poprawna i preferowana przy wielu okazjach. Chciałbym po prostu dodać alternatywę dla jego odpowiedzi:

Możesz dodać" zaimportowany " cel biblioteki zamiast katalogu z linkami. Coś w stylu:

# Your-external "mylib", add GLOBAL if the imported library is located in directories above the current.
add_library( mylib SHARED IMPORTED )
# You can define two import-locations: one for debug and one for release.
set_target_properties( mylib PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/res/mylib.so )

A następnie Linkuj tak, jakby ta biblioteka została zbudowana przez twój projekt:

TARGET_LINK_LIBRARIES(GLBall mylib)

Takie podejście dałoby ci trochę więcej elastyczności: spójrz na polecenie add_library( ) i wiele właściwości docelowych związanych z importowanym biblioteki .

Nie wiem, czy to rozwiąże twój problem z "zaktualizowanymi wersjami libs".

 91
Author: André,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-07 16:21:50

Zakładam, że chcesz połączyć się z biblioteką o nazwie foo , jej nazwa pliku to zwykle coś link foo.dll lub libfoo.so.

1. Znajdź bibliotekę
Musisz znaleźć bibliotekę. To dobry pomysł, nawet jeśli znasz ścieżkę do swojej biblioteki. CMake spowoduje błąd, jeśli Biblioteka zniknie lub otrzyma nową nazwę. Pomaga to wcześnie wykryć błąd i wyjaśnić użytkownikowi (może samemu), co powoduje problem.
Aby znaleźć bibliotekę foo i zapisać ścieżkę w FOO_LIB użycie

    find_library(FOO_LIB foo)

CMake sam się zorientuje, jaka jest rzeczywista nazwa pliku. Sprawdza zwykłe miejsca jak /usr/lib, /usr/lib64 i ścieżek w PATH.

Znasz już lokalizację swojej biblioteki. Dodaj go do CMAKE_PREFIX_PATH po wywołaniu CMake, wtedy CMake będzie również szukał Twojej biblioteki w przekazywanych ścieżkach.

Czasami musisz dodać podpowiedzi lub przyrostki ścieżek, zobacz dokumentację szczegóły: https://cmake.org/cmake/help/latest/command/find_library.html

2. Połącz bibliotekę Od 1. pełna nazwa biblioteki znajduje się w FOO_LIB. Możesz użyć tego, aby połączyć bibliotekę z docelowym mylib jak w

  target_link_libraries(mylib "${FOO_LIB}")

Możesz dodać PRIVATE, PUBLIC, lub INTERFACE przed biblioteką, por. dokumentacja: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

3. Dodaj includes (ten krok może nie być obowiązkowe.)
Jeśli chcesz również dołączyć pliki nagłówkowe, użyj find_path podobnego do find_library i wyszukaj plik nagłówkowy. Następnie Dodaj katalog include z target_include_directories podobny do target_link_libraries.

Dokumentacja: https://cmake.org/cmake/help/latest/command/find_path.html oraz https://cmake.org/cmake/help/latest/command/target_include_directories.html

Jeśli jest dostępny dla zewnętrznego oprogramowania, możesz zastąpić find_library i find_path przez find_package.

 32
Author: usr1234567,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-30 12:23:56

Jeszcze jedna alternatywa, w przypadku, gdy pracujesz z Appstore, potrzebują "uprawnień" i jako takie muszą połączyć się z Apple-Framework.

Dla uprawnień do pracy (np. GameCenter) musisz mieć "Link Binary with Libraries"-buildstep, a następnie link z "GameKit.framework". CMake "wstrzykuje" biblioteki na "niskim poziomie" do wiersza poleceń, dlatego Xcode nie wie o tym naprawdę i jako taki będziesz Nie włączyć GameKit w Ekran możliwości.

Jednym ze sposobów użycia CMake i posiadania "łącza z binariami"-buildstep jest wygenerowanie xcodeproj za pomocą CMake, a następnie użycie ' sed ' do 'search & replace' i dodanie GameKit w sposób, w jaki Xcode go lubi...

Skrypt wygląda tak (dla Xcode 6.3.1).

s#\/\* Begin PBXBuildFile section \*\/#\/\* Begin PBXBuildFile section \*\/\
    26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks \*\/ = {isa = PBXBuildFile; fileRef = 26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/; };#g

s#\/\* Begin PBXFileReference section \*\/#\/\* Begin PBXFileReference section \*\/\
    26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System\/Library\/Frameworks\/GameKit.framework; sourceTree = SDKROOT; };#g

s#\/\* End PBXFileReference section \*\/#\/\* End PBXFileReference section \*\/\
\
\/\* Begin PBXFrameworksBuildPhase section \*\/\
    26B12A9F1C10543B00A9A2BA \/\* Frameworks \*\/ = {\
        isa = PBXFrameworksBuildPhase;\
        buildActionMask = 2147483647;\
        files = (\
            26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks xxx\*\/,\
        );\
        runOnlyForDeploymentPostprocessing = 0;\
    };\
\/\* End PBXFrameworksBuildPhase section \*\/\
#g

s#\/\* CMake PostBuild Rules \*\/,#\/\* CMake PostBuild Rules \*\/,\
            26B12A9F1C10543B00A9A2BA \/\* Frameworks xxx\*\/,#g
s#\/\* Products \*\/,#\/\* Products \*\/,\
            26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/,#g

Zapisz to do " gamecenter.sed", a następnie "zastosować" to tak ( zmienia XCODEPROJ! )

sed -i.pbxprojbak -f gamecenter.sed myproject.xcodeproj/project.pbxproj

Być może będziesz musiał zmienić skrypt-polecenia, aby dopasować się do Twoich potrzeb.

Warning: it ' s prawdopodobnie zerwać z różnych wersji Xcode jako format projektu może się zmienić, (hardcoded) unikalny numer może nie naprawdę przez unikalne - i ogólnie rozwiązania przez innych ludzi są lepsze - więc chyba że trzeba wspierać Appstore + uprawnienia ( i zautomatyzowanych kompilacji), nie rób tego.

To jest błąd CMake, zobacz http://cmake.org/Bug/view.php?id=14185 i http://gitlab.kitware.com/cmake/cmake/issues/14185

 3
Author: kalmiya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-15 19:34:32