Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a CMake library accessible by other CMake packages automatically

Tags:

cmake

I have one project that produces a library:

project (myCoolLibrary)
ADD_LIBRARY(my_cool_library SHARED ${mysources_SRC})

And another project that should be using this library:

find_package (myCoolLibrary REQUIRED)
INCLUDE_DIRECTORIES("${myCoolLibrary_INCLUDE_DIRS}" )
add_executable(myCoolExe ${my_sources_SRC} )
TARGET_LINK_LIBRARIES(myCoolExe ${myCoolLibrary_LIBRARIES} )

Is there a way that I can change the first file so that the second file works automatically? That by running CMake on the first file and then running make on the output, then running CMake on the second file, CMake is able to find the package?

An answer where I just give the address of where the first project is built to the second package is also acceptable.

like image 416
amir Avatar asked Nov 01 '15 12:11

amir


People also ask

How do I add a shared library to CMake?

which means that you should specify the sources of YOUR library as second argument to add_library() or add_executable() and not the library that is already compiled. You need your sources because generally you build something (a library or an executable) that requires linking to some library that already exist.

What does target link libraries do in CMake?

Specify libraries or flags to use when linking a given target and/or its dependents. Usage requirements from linked library targets will be propagated. Usage requirements of a target's dependencies affect compilation of its own sources.


1 Answers

Taking the code found in a blog post by @daniperez - Use CMake-enabled libraries in your CMake project (III) - I've come up with the following minimal solution:

myCoolLibrary/CMakeLists.txt

cmake_minimum_required(VERSION 3.3)

project(myCoolLibrary)

function(my_export_target _target _include_dir)
    file(
        WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
        "
            include(\"\$\{CMAKE_CURRENT_LIST_DIR\}/${_target}Targets.cmake\")
            set_property(
                TARGET ${_target}
                APPEND PROPERTY
                    INTERFACE_INCLUDE_DIRECTORIES \"${_include_dir}\"
            )
        "
    )

    export(TARGETS ${_target} FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake")

    # NOTE: The following call can pollute your PC's CMake package registry
    #       See comments/alternatives below
    export(PACKAGE ${_target})
endfunction(my_export_target)

...

add_library(${PROJECT_NAME} SHARED ${mysources_SRC})
my_export_target(${PROJECT_NAME} "${CMAKE_CURRENT_SOURCE_DIR}")

myCoolExe/CMakeLists.txt

cmake_minimum_required(VERSION 3.3)

project(myCoolExe)

find_package(myCoolLibrary REQUIRED)

...

add_executable(${PROJECT_NAME} ${my_sources_SRC})
target_link_libraries(${PROJECT_NAME} myCoolLibrary)

To make it reusable I have packed everything into my_export_target(). And I'm friend of self-propagating properties like INTERFACE_INCLUDE_DIRECTORIES.

As commented by @ruslo, using export(PACKAGE ...) can pollute your package registry. So alternatively you can:

  1. Write the target configuration files directly to some dedicated place specific for a certain toolchain

    See e.g. How to install your custom CMake-Find module and 0003659: FIND_PACKAGE command improvements.

  2. Set CMAKE_MODULE_PATH via the second project's CMake command line (injecting the search path(s) from the outside). If you are building the two projects anyway with a build script, then this is the most direct way to propagate the module search path(s).

Additional References

  • export()
  • CMake/Tutorials/Package Registry
  • Unable to find Eigen3 with CMake
  • How to instruct CMake to use the build architecture compiler
like image 59
Florian Avatar answered Oct 02 '22 00:10

Florian