Exporting an imported library

后端 未结 3 905
野的像风
野的像风 2021-02-07 21:31

I have projectA, into which I\'m importing a library with:

add_library(foo STATIC IMPORTED)
set_property(TARGET foo PROPERTY IMPORTED_LOCATION /path/to/foo.a)
         


        
3条回答
  •  面向向阳花
    2021-02-07 22:17

    I also can't find an ideal way to do this. But here is the workaround I'm using for now. It's extra work, and not DRY, but I think it achieves the right thing.

    Imagine lib B depends on third party lib A. A either has a find module defined, or we can implement a custom find module for it. Both are doable. Assume we've already written FindA.cmake and stored in in ${CMAKE_SOURCE_DIR}/cmake. Also, let's assume that when you run cmake to generate B's build system, you provide A_ROOT to help cmake locate A.

    Then in B's top-level CMakeLists.txt we need:

    # Use FindA.cmake, defined in the cmake/ directory.
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
    find_package(A REQUIRED)
    
    # ... (define the B target here)...
    
    # Copy the config file to the build dir
    configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY)
    
    # Copy A's find module (skip this step if FindA is not custom).
    configure_file(cmake/FindA.cmake cmake/FindA.cmake COPYONLY)
    
    # Create the target export.
    export(EXPORT BTargets
        FILE ${CMAKE_BINARY_DIR}/cmake/BTargets.cmake
        NAMESPACE B::
        )
    
    # Register B so cmake can find B's config file.
    export(PACKAGE B)
    

    Now in cmake/BConfig.cmake:

    # Get the exported find module onto the module path.
    # This step is unnecessary if the find module is part of cmake.
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
    
    # Store the root so that find_package will work.
    # You may have to store other variables here, too, but
    # the principle is just more of the same.
    set(A_ROOT @A_ROOT@) # **Could optionally cache this.
    find_package(A MODULE REQUIRED)
    
    # The usual one-liner for a config file.
    include("${CMAKE_CURRENT_LIST_DIR}/BTargets.cmake")
    

    Just to drive the solution home, let's look at a second example, Rocket this time using Boost, which already has a find module defined.

    CMakeLists.txt:

    option(Boost_USE_MULTITHREADED ON)
    option(Boost_USE_STATIC_LIBS OFF)
    find_package(Boost REQUIRED COMPONENTS filesystem program_options)
    
    add_library(Rocket rocket.cpp)
    target_link_libraries(Rocket
        PUBLIC Boost::filesystem
        PRIVATE Boost::program_options
        )
    
    configure_file(cmake/BConfig.cmake cmake/BConfig.cmake @ONLY)
    
    export(EXPORT RocketTargets 
        FILE ${CMAKE_BINARY_DIR}/RocketTargets.cmake
        NAMESPACE Rocket::
        )
    export(PACKAGE Rocket)
    

    Then cmake/RocketConfig.cmake would have:

    set(BOOST_ROOT @BOOST_ROOT@ CACHE PATH "In case boost was relocated.")
    set(Boost_USE_MULTITHREADED @Boost_USE_MULTITHREADED@)
    set(Boost_USE_STATIC LIBS @Boost_USE_STATIC_LIBS@)
    find_package(Boost REQUIRED COMPONENTS filesystem program_options)
    
    include("${CMAKE_CURRENT_LIST_DIR}/RocketTargets.cmake")
    

    So yeah. It seems like too much typing. It seems like cmake should be able to generate all of that code from an export statement in CMakeLists.txt. But this strategy seems to achieve the goal.

    Also, I haven't tested yet, but I suspect that, if your transitive dependency uses a CONFIG instead of a MODULE for find_package, it should be very easy just to add to CMAKE_PREFIX_PATH in your config file as well.

提交回复
热议问题