CMake链接到外部库

时间:2012-01-08 01:16:05

标签: cmake external

如何让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

5 个答案:

答案 0 :(得分:107)

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( )命令和many target-properties related to imported libraries

我不知道这是否能解决“更新版本的lib”的问题。

答案 1 :(得分:86)

首先设置库搜索路径:

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

然后就这样做

TARGET_LINK_LIBRARIES(GLBall mylib)

答案 2 :(得分:40)

我假设您要链接到名为 foo 的库,其文件名通常是链接/users/2/posts?num=78 foo.dll

<强> 1。找到图书馆
你必须找到图书馆。即使您知道图书馆的路径,这也是一个好主意。如果库消失或获得新名称,CMake将会出错。这有助于及早发现错误,并使用户(可能是您自己)明白导致问题的原因 要查找库 foo 并将路径存储在libfoo.so使用

FOO_LIB

CMake将自己弄清楚实际文件名是怎样的。它会检查 find_library(FOO_LIB foo) /usr/lib等常用地点以及/usr/lib64中的路径。

您已经知道图书馆的位置。当你调用CMake时将它添加到PATH,然后CMake也会在传递的路径中查找你的库。

有时您需要添加提示或路径后缀,有关详细信息,请参阅文档: https://cmake.org/cmake/help/latest/command/find_library.html

<强> 2。链接库 从1.您在CMAKE_PREFIX_PATH中拥有完整的库名称。您可以使用它将库链接到目标FOO_LIB,如

mylib

您可能希望在库前面添加 target_link_libraries(mylib "${FOO_LIB}") PRIVATEPUBLIC,参见文件: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

第3。添加包含 (此步骤可能不是强制性的。)
如果您还想要包含头文件,请使用与INTERFACE类似的find_path并搜索头文件。然后添加包含find_library的include目录,类似于target_include_directories

文档: https://cmake.org/cmake/help/latest/command/find_path.htmlhttps://cmake.org/cmake/help/latest/command/target_include_directories.html

如果可用于外部软件,则可以target_link_libraries替换find_libraryfind_path

答案 3 :(得分:3)

在您使用Appstore的情况下,还有一个替代方案需要“Entitlements”,因此需要与Apple-Framework链接。

要使权利工作(例如GameCenter),您需要拥有“与图书馆链接二进制文件”-buildstep,然后与“GameKit.framework”链接。 CMake将“低级别”的库“注入”到命令行中,因此Xcode不会真正知道它,因此你将启用GameKit功能界面。

使用CMake和“使用二进制链接”-buildstep的一种方法是使用CMake生成xcodeproj,然后使用'sed'来'搜索&amp;替换'并以XCode喜欢的方式添加GameKit ......

脚本如下所示(对于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

您可能需要更改脚本命令以满足您的需要。

警告:由于项目格式可能会发生变化,因此可能会破坏不同的Xcode版本,(硬编码)唯一编号可能并非真正独一无二 - 通常其他人的解决方案更好 - 所以除非您需要支持Appstore + Entitlements(和自动构建)不要这样做。

这是一个CMake错误,请参阅http://cmake.org/Bug/view.php?id=14185http://gitlab.kitware.com/cmake/cmake/issues/14185

答案 4 :(得分:1)

假设您有一个可执行文件,例如:

add_executable(GLBall GLBall.cpp)

如果外部库有标题,请给出其包含文件夹的路径:

target_include_directories(GLBall PUBLIC "/path/to/include")

添加库目录路径:

target_link_directories(GLBall PUBLIC "/path/to/lib/directory")

最后链接库名

target_link_libraries(GLBall mylib)

注意去掉了库文件的前缀和扩展名:

libmylib.a ➜ mylib
mylib.so ➜ mylib