How to Create Packages with CMake
Asked Answered
F

1

9
.
+-- 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".

Fick answered 11/4, 2019 at 14:44 Comment(1)
export the package in MyPack and then -DCMAKE_PREFIX_PATH=../../MyPackAguascalientes
R
14

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( 
  TARGETS lib1
  EXPORT MyPackTargets
  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
  )

in Lib2/CMakeLists.txt:

add_library(lib2 "")
add_library(MyPack::lib2 ALIAS lib2)
[...]
include(GNUInstallDirs)
install( 
  TARGETS 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/

Ryals answered 12/4, 2019 at 8:10 Comment(5)
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?Fick
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 folderRyals
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!Fick
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)Ryals
I believe it's "TARGETS" and not "TARGET" apart from that typo, the solution works amazing. Thank you!Silvereye

© 2022 - 2024 — McMap. All rights reserved.