8

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
amir
  • 420
  • 4
  • 12
  • 1
    Something [like this CMake tutorial on how to make a ProjectConfig.cmake file](https://cmake.org/Wiki/CMake/Tutorials/How_to_create_a_ProjectConfig.cmake_file)? – DevSolar Nov 01 '15 at 13:36
  • 2
    DevSolar, I had read that article. To be honest I found it a bit too complex for my liking. I was hoping for a simpler method. Also, if I am right, I would have to run "make install" for it to work, although that would make sense. – amir Nov 01 '15 at 14:22
  • 1
    The same article points to [another article](https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html#creating-packages) as a newer solution. I will try this and see what happens. – amir Nov 01 '15 at 15:47
  • 1
    Just a hint: a more compact description can be found in a blog post by daniperez: [Use CMake-enabled libraries in your CMake project (III)](https://coderwall.com/p/qej45g/use-cmake-enabled-libraries-in-your-cmake-project-iii). – Florian Nov 02 '15 at 08:39
  • @Florian this was the one that finally worked, and this was the one that I wanted. I'll have to fix the question to correctly reflect what I wanted. Also if you write a solution I'll flag it as the answer, if not I'll do it myself in a few days. Thanks. – amir Nov 06 '15 at 09:53
  • @amir Glad to hear it help. I added an answer with my minimal code version. – Florian Nov 06 '15 at 14:44

1 Answers1

4

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

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Florian
  • 39,996
  • 9
  • 133
  • 149
  • @ruslo Thanks for the feedback. I'll check and update my answer(s) accordingly. – Florian Mar 30 '16 at 07:53
  • 1
    This seems like a great start, but I am having trouble modifying it to correctly pass on transitive library dependencies. The library I am trying to export depends itself on another library (and its header files), and I cannot get this stuff added to the correct link/include information for my package. Any ideas how this should work? – Ben Farmer Oct 19 '18 at 10:09