Cmake Subdirectory

The following information is biased. But in a good way, I think. I'm going to tell you how to structure the directories in your project. This is based on convention, but will help you:

  1. Cmake Subdirectory Target
  2. Cmake Subdirectory Option
  3. Cmake Subdirectory Dependency
  4. Cmake Subdirectory Source Files
  1. I'm trying to build a C project using CMake. Therefore I'd like to create a library from a subdirectory. My project structure looks like the following: project core CMakeLists.txt point.h point.cpp CMakeLists.txt build main.cpp My outer CMakeLists.txt.
  2. Cmakeminimumrequired(VERSION 3.0.2) project(rosmotor) addcompileoptions(-std=c11) findpackage(catkin REQUIRED COMPONENTS canmsgs roscpp socketcaninterface ) catkinpackage( # INCLUDEDIRS include # LIBRARIES rosmotor # CATKINDEPENDS canmsgs roscpp socketcaninterface # DEPENDS systemlib ) addsubdirectory(lib/motor/) include.

CMakeLists.txt loaded by addsubdirectory command creates a node in a source tree: # Top-level CMakeLists.txt cmakeminimumrequired(VERSION 2.8) project(foo NONE) message('Top level CMakeLists.txt') addsubdirectory(foo) addsubdirectory(boo) # foo/CMakeLists.txt message('Processing foo/CMakeList.txt'). The CMAKESTRIP variable will contain the platform's strip utility, which removes symbols information from generated binaries. Sub/dir/test New in version 3.7: Runs the test step in the subdirectory, if any.

  • Easily read other projects following the same patterns,
  • Avoid a pattern that causes conflicts,
  • Keep from muddling and complicating your build.

First, this is what your files should look like when you start if your project is creatively called project, with a library called lib, and a executable called app:

The names are not absolute; you'll see contention about test/ vs. tests/, and the application folder may be called something else (or not exist for a library-only project). You'll also sometime see a python folder for python bindings, or a cmake folder for helper CMake files, like Find<library>.cmake files. But the basics are there.

Notice a few things already apparent; the CMakeLists.txt files are split up over all source directories, and are not in the include directories. This is because you should be able to copy the contents of the include directory to /usr/include or similar directly (except for configuration headers, which I go over in another chapter), and not have any extra files or cause any conflicts. That's also why there is a directory for your project inside the include directory. Use add_subdirectory to add a subdirectory containing a CMakeLists.txt.

You often want a cmake folder, with all of your helper modules. This is where your Find*.cmake files go. An set of some common helpers is at github.com/CLIUtils/cmake. To add this folder to your CMake path:

Your extern folder should contain git submodules almost exclusively. That way, you can control the version of the dependencies explicitly, but still upgrade easily. See the Testing chapter for an example of adding a submodule.

You should have something like /build* in your .gitignore, so that users can make build directories in the source directory and use those to build. A few packages prohibit this, but it's much better than doing a true out-of-source build and having to type something different for each package you build.

Cmake Subdirectory Target

Cmake

If you want to avoid the build directory being in a valid source directory, add this near the top of your CMakeLists:

Cmake Subdirectory

See the extended code example here.

Cmake Subdirectory Option

Subdirectory

Cmake Subdirectory Dependency

This tutorial shows how to export a CMake library to a package and import it from a different project using the find_package() command. This works faster as referencing the library project’s directory using the add_subdirectory() command, as the exporting mechanism allows precisely selecting which targets to export. We will use Visual Studio to create a basic library project for Raspberry Pi with a cross-compiler, export it to a package and import it from another project.

Cmake Subdirectory Source Files

  1. Follow this tutorial to create a basic CMake library for Raspberry Pi and import it manually via add_subdirectory().
  2. Now we will change the library project to be exported to a package. Add the following lines to the CMakeLists.txt file that defines the library:
    2
    target_include_directories(CMakeLibraryDemo PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/public>

    This syntax tells CMake to use a directory inside the source tree when building the package and use the directory under the installation directory (where we installed PublicHeader.h using INSTALL FILES command) while handling exporting.
  3. Now the build should succeed:
  4. You can generate the package by right-clicking on libCMakeLibraryDemo.so in Solution Explorer and selecting “Install Target(s)”:
  5. CMake will create the c:/Packages/DemoLibraryClient directory and install the necessary files there:
  6. Open the installation directory with Explorer and check its contents:It should normally contain the library (.so file), the Find<Package name>.cmake file and the public directory with the public header (created via the INSTALL FILES command).
  7. Now we will create another CMake project that will import the package. Use the VisualGDB Linux Project Wizard to do that:
  8. Insert the following line in the CMakeLists.txt file of the new project:

    If you try building it now, CMake will complain that FindCMakeLibraryDemo.cmake file must be located in CMAKE_MODULE_PATH:
  9. You can fix this by adding “c:PackagesDemoLibraryClient” to the “Extra module directories” field on the CMake Project Settings page of VisualGDB Project Properties for your project:
  10. Now CMake will find the package and build the project, however running it will result in an error: the libCMakeLibraryDemo.so file will not be found:
  11. This happens because the libraries imported from packages are assumed to be already installed on the target in a directory where the application can find them. If you have previously tested tested out the library as a part of this tutorial, it should be already deployed to /tmp/MyLibraryDemo. Simply add this directory to SOLIB_SEARCH_PATH and executable will be able to locate it:
  12. If you want to debug the library sources while debugging your application, add the “set solib-search-path <directory with the .so file on the Windows machine> to the gdb startup commands (when importing the project via add_subdirectory() and adding a reference, VisualGDB would do this automatically):
  13. Now the library will get loaded and the breakpoints inside its functions will work as well: