How to Create Packages with CMake

10,394

Your drawing is a bit confusing because there is a CMakeLists.txt after Lib2 which belongs to no folder... Anyway : is MyPack

  • Lib1 and Lib2 ?
  • Lib1/Lib2/Subproj1/Subproj2 ?

in the 2nd case :

The top directory CMakeLists.txt gives you access to targets of Lib1 and Lib2 that you can use in SubProject1 and SubProject2 if you have something like this :

project(MyPack)
add_subdirectory(Lib1) # Building Lib1
add_subdirectory(Lib2) # Building Lib2
add_subdirectory(SubProject1) # you can use Lib1 & Lib2 targets here
add_subdirectory(SubProject2) # you can use Lib1 & Lib2 targets here

If it is the 1st case, MyPack is only Lib1 and Lib2 :

Using find_package(MyPack) means that you need to create a Config file and install() your project:

project(MyPack)
add_subdirectory(Lib1)
add_subdirectory(Lib2)

in Lib1/CMakeLists.txt :

add_library(lib1 "")
add_library(MyPack::lib1 ALIAS lib1)
[...]
include(GNUInstallDirs)
install( 
  TARGET lib1
  EXPORT MyPackTargets
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )

in Lib2/CMakeLists.txt :

add_library(lib2 "")
add_library(MyPack::lib2 ALIAS lib2)
[...]
include(GNUInstallDirs)
install( 
  TARGET lib2
  EXPORT MyPackTargets
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )

Now you have lib1 and lib2 in the export MyPackTargets. You have to install that export as well.

anywhere after above :

install(
  EXPORT MyPackTargets
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyPack
  NAMESPACE MyPack::
  FILE MyPackTargets.cmake # Not sure if this is still needed
  )

include(CMakePackageConfigHelpers)
configure_package_config_file( 
  "Config.cmake.in" 
  "MyPackConfig.cmake"
  INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyPack
  PATH_VARS
    CMAKE_INSTALL_LIBDIR
  )

write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/MyPackConfigVersion.cmake
  VERSION 1.0.0
  COMPATIBILITY SameMajorVersion
  )

### Install Config and ConfigVersion files
install(
  FILES "${CMAKE_CURRENT_BINARY_DIR}/MyPackConfig.cmake"
        "${CMAKE_CURRENT_BINARY_DIR}/MyPackConfigVersion.cmake"
  DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/MyPack"
  )

create a file Config.cmake.in with :

@PACKAGE_INIT@
include( "${CMAKE_CURRENT_LIST_DIR}/MyPackTargets.cmake" )

Now if you build and install your project MyPack, find_package(MyPack) from other project should find it and import the targets you've created.

Here is some documentation : https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html

https://blog.kitware.com/cmake-superbuilds-git-submodules/

Hope that helps

Share:
10,394

Related videos on Youtube

r.stagi
Author by

r.stagi

Updated on July 12, 2022

Comments

  • r.stagi
    r.stagi almost 2 years
    .
    +-- MyPack
    |   +-- Lib1
    |   |   +-- include
    |   |   |   +-- Lib1.h
    |   |   +-- src
    |   |   |   +-- Lib2.cpp
    |   |   +-- CMakeLists.txt
    |   +-- Lib2
    |   |   +-- include
    |   |   |   +-- Lib2.h
    |   |   +-- src
    |   |   |   +-- Lib2.cpp
    |   |   +-- CMakeLists.txt
    |   +-- CMakeLists.txt
    +-- SubProject1
    |   +-- CMakeLists.txt
    +-- SubProject2
    |   +-- CMakeLists.txt
    +-- CMakeLists.txt
    

    Hi all.

    I'm new to CMake and I'm trying to obtain something like the following. Considering the above directory tree of my C++ project:

    I have a directory (let's say "MyPack") that contains several subdirectories (Lib1, Lib2...) and each one represents a C++ Library that I wrote.

    How can I setup everything so I can write find_package(MyPack)in the other subprojects?

    Every subproject is a stand-alone project, and does not depend on other subprojects, but just on libraries in "MyPack".

  • r.stagi
    r.stagi about 5 years
    Thank you! I still can't make it work as I wish. First of all, the case is the first one as you understood. I put in lib1-2/CMakeLists.txt the code you suggested, exporting MyPackTargets. After that, I craeted the Config.cmake.in and the CMakeLists.txt in MyPack/, where I added the subdirectories of the two libs and I put the code you suggested (the one installing MyPackTargets). Finally, running "cmake ." in the project folder (outside MyPack), it finds the MyPack package, but it doesn't find MyPack/MyPackTargets.cmake, which is included by MyPack/MyPackConfig.cmake. Any further suggestion?
  • Alkalyne
    Alkalyne about 5 years
    It is a good sign that your project finds MyPack package config. Now it looks like the path in Config.cmake.in is not correct, you should try to adjust it to the location of MyPackTargets.cmake in the install folder
  • r.stagi
    r.stagi about 5 years
    The problem is that I can't find any MyPackTargets.cmake, anywhere. Btw, I solved putting add_subdirectory for all the libs (in the CMakeLists.txt of MyPack) and add_subdirectory(MyPack) inside the CMakeLists.txt of my project (which has inside "MyPack"). I had to remove the find_package directive and it works fine now. Maybe is not the best practice, but I could do what I wanted to. So thank you!
  • Alkalyne
    Alkalyne about 5 years
    You mostly did the 2nd solution I've explained earlier - because you have all the source code, you have access to the targets inside the build tree. For your original problem, MyPackTargets.cmake should be installed by install(Export). check that command if it is doing its job in the correct location (you can check install_manifest.txt to see where your file is installed)
  • Kjell Hedström
    Kjell Hedström over 3 years
    I believe it's "TARGETS" and not "TARGET" apart from that typo, the solution works amazing. Thank you!