CMake链接到外部库
如何让CMake将可执行文件链接到不在同一个CMake项目中构build的外部共享库?
只是做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
失败。
首先设置库searchpath:
LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)
然后就这样做
TARGET_LINK_LIBRARIES(GLBall mylib)
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/ )
然后链接,如果这个库是由您的项目build立的:
TARGET_LINK_LIBRARIES(GLBall mylib)
这样的方法会给你更多的灵活性:查看add_library()命令以及与导入的库相关的许多目标属性 。
我不知道这是否会解决您的问题与“更新版本的库”。
我假设你想链接到一个名为foo的库,它的文件名通常是链接foo.dll
或libfoo.so
。
1.find图书馆
你必须find图书馆。 这是一个好主意,即使你知道你的图书馆的path。 如果图书馆消失或得到一个新的名字,CMake会报错。 这有助于及早发现错误,并向用户(可能自己)明确是什么原因造成问题。
查找foo库并将path存储在FOO_LIB
find_library(FOO_LIB foo)
CMake会自己弄清楚实际的文件名是如何的。 它检查通常的位置,例如/usr/lib
, /usr/lib64
和PATH
中的PATH
。
你已经知道你的图书馆的位置。 当你调用CMake的时候将它添加到CMAKE_PREFIX_PATH
,那么CMake也会在传递的path中查找你的库。
有时您需要添加提示或path后缀,请参阅文档以获取详细信息: https : //cmake.org/cmake/help/latest/command/find_library.html
2.链接库从1.你有完整的库名在FOO_LIB
。 你可以使用这个将库链接到你的目标mylib
中
target_link_libraries(mylib "${FOO_LIB}")
你可能想要在图书馆前加上PRIVATE
, PUBLIC
或INTERFACE
,参见 文档: https : //cmake.org/cmake/help/latest/command/target_link_libraries.html
3.添加包含 (这一步可能不是强制性的)。
如果您还想包含头文件,请使用类似于find_library
并search头文件。 然后添加包含与target_include_directories
相似的target_include_directories
的include目录。
文档: https : //cmake.org/cmake/help/latest/command/find_path.html和https://cmake.org/cmake/help/latest/command/target_include_directories.html
如果可用于外部软件,则可以通过find_package
replacefind_library
和find_package
。
如果你正在使用Appstore,还需要另外一个select,它需要“权利”,因此需要链接到Apple-Framework。
对于权利的工作(如GameCenter),你需要有一个“链接二进制文件库”–buildstep,然后链接到“GameKit.framework”。 CMake将“低级”的库注入命令行,因此Xcode并不真正了解它,因此在Capabilities屏幕中将不会启用GameKit。
一种使用CMake的方法,有一个“与二进制链接”-buildstep是用CMake生成xcodeproj,然后用'sed'来search和replace,并以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版本,(硬编码)唯一编号可能并不是唯一的,而且其他人的解决scheme通常更好 – 所以除非您需要支持Appstore +权利(和自动构build),不要这样做。
这是一个CMake错误,请参阅http://cmake.org/Bug/view.php?id=14185和http://gitlab.kitware.com/cmake/cmake/issues/14185