Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Create Packages with CMake

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

like image 766
r.stagi Avatar asked Apr 11 '19 14:04

r.stagi


People also ask

Where are CMake packages stored?

CMake ships with its own set of built-in find_package scripts, and their location is in the default CMAKE_MODULE_PATH. The more normal use case for dependent projects that have been CMakeified would be to use CMake's external_project command and then include the Use[Project]. cmake file from the subproject.

How does CMake find package work?

CMake searches for a file called Find<package>. cmake in the CMAKE_MODULE_PATH followed by the CMake installation. If the file is found, it is read and processed by CMake. It is responsible for finding the package, checking the version, and producing any needed messages.

Is CMake used for C++?

CMake is an open-source, cross-platform tool that uses compiler and platform independent configuration files to generate native build tool files specific to your compiler and platform. The CMake Tools extension integrates Visual Studio Code and CMake to make it easy to configure, build, and debug your C++ project.


1 Answers

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

like image 187
Alkalyne Avatar answered Sep 23 '22 05:09

Alkalyne