Ссылка CMake на внешнюю библиотеку

Как заставить CMake связать исполняемый файл с внешней общей библиотекой, которая не строится в рамках одного проекта CMake?

Просто выполнение target_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so) дает ошибку

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)

после того, как я скопировал библиотеку в двоичный каталог bin/res.

Я попытался использовать find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

Что не удается с помощью RESULT-NOTFOUND.

Ответ 1

Сначала найдите путь поиска библиотек:

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

А потом просто

TARGET_LINK_LIBRARIES(GLBall mylib)

Ответ 2

arrowdodger ответ правильный и предпочтительный во многих случаях. Я просто хотел бы добавить альтернативу его ответу:

Вы можете добавить "импортированную" цель библиотеки, а не ссылку-каталог. Что-то вроде:

# 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 )

И затем соедините, как будто эта библиотека была построена вашим проектом:

TARGET_LINK_LIBRARIES(GLBall mylib)

Такой подход даст вам немного большую гибкость. Посмотрите на команду add_library() и много свойств-мишеней, связанных с импортированными библиотеками.

Я не знаю, решит ли это вашу проблему с "обновленными версиями libs".

Ответ 3

Предполагаю, что вы хотите связать библиотеку с именем foo, ее имя файла обычно имеет ссылку foo.dll или libfoo.so.

1. Найти библиотеку
Вы должны найти библиотеку. Это хорошая идея, даже если вы знаете путь к своей библиотеке. CMake выйдет из строя, если библиотека исчезнет или получит новое имя. Это помогает выявить ошибки на раннем этапе и дать понять пользователю (может быть, самому), что вызывает проблему.
Чтобы найти библиотеку foo и сохранить путь в FOO_LIB, используйте

    find_library(FOO_LIB foo)

CMake выяснит, каким образом это имя файла. Он проверяет обычные места, такие как /usr/lib, /usr/lib64 и пути в PATH.

Вы уже знаете местоположение своей библиотеки. Добавьте его в CMAKE_PREFIX_PATH, когда вы вызываете CMake, тогда CMake также будет искать вашу библиотеку в пройденных путях.

Иногда вам нужно добавить подсказки или суффиксы пути, подробности см. в документации: https://cmake.org/cmake/help/latest/command/find_library.html

2. Свяжите библиотеку С 1. у вас есть полное имя библиотеки в FOO_LIB. Вы используете это, чтобы связать библиотеку с вашей целью mylib, как в

  target_link_libraries(mylib "${FOO_LIB}")

Возможно, вы захотите добавить PRIVATE, PUBLIC или INTERFACE перед библиотекой, cf. документация: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

3. Добавить включает (этот шаг может быть необязательным.)
Если вы также хотите включить заголовочные файлы, используйте find_path, аналогичный find_library, и найдите файл заголовка. Затем добавьте каталог include с target_include_directories, похожим на target_link_libraries.

Документация: https://cmake.org/cmake/help/latest/command/find_path.html а также https://cmake.org/cmake/help/latest/command/target_include_directories.html

Если доступно для внешнего программного обеспечения, вы можете заменить find_library и find_path на find_package.

Ответ 4

Еще одна альтернатива, в случае, если вы работаете с Appstore, нуждается в "правах" и, как таковая, должна быть связана с Apple-Framework.

В разделе "Права доступа к работе" (например, GameCenter) необходимо иметь "Link Binary with Libraries" -buildstep, а затем ссылку на "GameKit.framework". CMake "внедряет" библиотеки на "низкий уровень" в командную строку, поэтому Xcode действительно не знает об этом, и поэтому вы не сможете включить GameKit на экране Capabilities.

Один из способов использования CMake и "Link with Binaries" -buildstep - генерировать xcodeproj с помощью CMake, а затем использовать "sed" для "поиска и замены" и добавлять GameKit так, как XCode нравится..

script выглядит так (для 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

сохраните это в "gamecenter.sed", а затем примените его так (он изменит ваш xcodeproj!)

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

Возможно, вам придется изменить команды script в соответствии с вашими потребностями.

Предупреждение: он может сломаться с другой версией Xcode, поскольку формат проекта может измениться, уникальный номер (hardcoded) может быть не уникальным - и, как правило, решения других людей лучше - так что, если вам не нужна поддержка Appstore + Ent Rightsments (и автоматические сборки), не делайте этого.

Это ошибка CMake, см. http://cmake.org/Bug/view.php?id=14185 и http://gitlab.kitware.com/cmake/cmake/issues/14185