CMake link to external library

后端 未结 4 2087
梦谈多话
梦谈多话 2020-11-21 04:53

How to get CMake to link an executable to an external shared library that is not build within the same CMake project?

Just doing target_link_libraries(GLBall $

相关标签:
4条回答
  • 2020-11-21 05:18

    I assume you want to link to a library called foo, its filename is usually something link foo.dll or libfoo.so.

    1. Find the library
    You have to find the library. This is a good idea, even if you know the path to your library. CMake will error out if the library vanished or got a new name. This helps to spot error early and to make it clear to the user (may yourself) what causes a problem.
    To find a library foo and store the path in FOO_LIB use

        find_library(FOO_LIB foo)
    

    CMake will figure out itself how the actual file name is. It checks the usual places like /usr/lib, /usr/lib64 and the paths in PATH.

    You already know the location of your library. Add it to the CMAKE_PREFIX_PATH when you call CMake, then CMake will look for your library in the passed paths, too.

    Sometimes you need to add hints or path suffixes, see the documentation for details: https://cmake.org/cmake/help/latest/command/find_library.html

    2. Link the library From 1. you have the full library name in FOO_LIB. You use this to link the library to your target GLBall as in

      target_link_libraries(GLBall PRIVATE "${FOO_LIB}")
    

    You should add PRIVATE, PUBLIC, or INTERFACE after the target, cf. the documentation: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

    If you don't add one of these visibility specifiers, it will either behave like PRIVATE or PUBLIC, depending on the CMake version and the policies set.

    3. Add includes (This step might be not mandatory.)
    If you also want to include header files, use find_path similar to find_library and search for a header file. Then add the include directory with target_include_directories similar to target_link_libraries.

    Documentation: https://cmake.org/cmake/help/latest/command/find_path.html and https://cmake.org/cmake/help/latest/command/target_include_directories.html

    If available for the external software, you can replace find_library and find_path by find_package.

    0 讨论(0)
  • 2020-11-21 05:21

    One more alternative, in the case you are working with the Appstore, need "Entitlements" and as such need to link with an Apple-Framework.

    For Entitlements to work (e.g. GameCenter) you need to have a "Link Binary with Libraries"-buildstep and then link with "GameKit.framework". CMake "injects" the libraries on a "low level" into the commandline, hence Xcode doesn't really know about it, and as such you will not get GameKit enabled in the Capabilities screen.

    One way to use CMake and have a "Link with Binaries"-buildstep is to generate the xcodeproj with CMake, and then use 'sed' to 'search & replace' and add the GameKit in the way XCode likes it...

    The script looks like this (for 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
    

    save this to "gamecenter.sed" and then "apply" it like this ( it changes your xcodeproj! )

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

    You might have to change the script-commands to fit your need.

    Warning: it's likely to break with different Xcode-version as the project-format could change, the (hardcoded) unique number might not really by unique - and generally the solutions by other people are better - so unless you need to Support the Appstore + Entitlements (and automated builds), don't do this.

    This is a CMake bug, see http://cmake.org/Bug/view.php?id=14185 and http://gitlab.kitware.com/cmake/cmake/issues/14185

    0 讨论(0)
  • 2020-11-21 05:23

    Set libraries search path first:

    LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)
    

    And then just do

    TARGET_LINK_LIBRARIES(GLBall mylib)
    
    0 讨论(0)
  • 2020-11-21 05:23

    arrowdodger's answer is correct and preferred on many occasions. I would simply like to add an alternative to his answer:

    You could add an "imported" library target, instead of a link-directory. Something like:

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

    And then link as if this library was built by your project:

    TARGET_LINK_LIBRARIES(GLBall mylib)
    

    Such an approach would give you a little more flexibility: Take a look at the add_library( ) command and the many target-properties related to imported libraries.

    I do not know if this will solve your problem with "updated versions of libs".

    0 讨论(0)
提交回复
热议问题