How to build and install dependencies from CMake - cmake

I am trying to create CMakeLists.txt, that can be able to build a number of other projects. My goal is to simplify building some libraries of particular project.
I have a directory called 'dependencies' with CMakeLists.txt, and there are some source code directories inside. Structure like this:
dependencies/
├── zlib (source code directory with it's own CMakeLists.txt)
├── libpng (source code directory with it's own CMakeLists.txt)
├── 3d lib (source code directory with it's own CMakeLists.txt, that uses zlib and libpng)
├── CMakeLists.txt
At this moment I have next content in the root CMakeLists.txt:
cmake_minimum_required (VERSION 3.15)
project(myProject)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../lib)
#### NEED TO ADD HERE ####
I want to do next things for all these subprojects (zlib, libpng and 3d lib):
Configure project with CMake;
Build this project in both: Debug and Release configurations;
Run install.
I need all these libraries to be installed to CMAKE_INSTALL_PREFIX, because '3d lib' will look for zlib and libpng in that directory. And by the time, when '3d lib's CMakeLists.txt will be processing, all previous libs has to be already installed, otherwise CMake fails finding zlib and libpng.
So is there a way to append my root CMakeLists.txt to do that? Of course, I can manually run CMake for all dependencies, but I think CMake are able to do all this stuff autonomously.

add_subdirectory was really the solution for this problem.
When I tried it for the first time I had some errors and thought that this was because some of these targets depend on others of them. But I was wrong, add_subdirectory is what I need.

Related

Using third-party libraries with CMake

I want anyone who cloned the repository can build it immediately, and don't need to install the dependencies.
Therefore, I found several ways:
Use git submodule and add_subdirectory.
Use find_package to find the built libraries and the headers.
The first one takes much time to build, so I think the second might be better. To make people be able to build the project instantly, I put the the files in the project, but it saied it doesn't know the linker language. What's this? And how to solve?
Direstories:
Project Root
lib
SDL2
(generated files when install)
include
(headers)
src
(sources)
CMakeLists.txt
CMakeLists.txt:
# ...
list(APPEND CMAKE_PREFIX_PATH lib)
find_package(SDL2)
# ...

Confusion on how CMake places binaries

I've recently began experimenting with CMake, and have written a simple Hello, World program in C++.
Here is my directory structure:
CMakeLists.txt
src/
CMakeLists.txt
main.cpp
build/
The top-level CMakeLists.txt reads as follows:
#Require at least CMake version 2.8
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
#set up the project name, version and language to compile in
project(HelloWorld)
#tell CMake that we have some source files located in the src directory
add_subdirectory(src)
And the CMakeLists.txt in /src reads:
add_executable(helloworld
main.cpp)
install(TARGETS helloworld
RUNTIME DESTINATION ../build)
Now, I would expect that these two scripts would cause the makefile to create the helloworld binary in the /build directory, but after running make, it creates the helloworld binary in /build/src.
If I move the add_executable and install function calls into the top-level CMakeLists.txt, then the helloworld binary is placed in /build, not /build/src.
So, as I understand, it places the build in the folder relative to where CMake was invoked. Why does it appear as though install is doing nothing, then?
Additionally, what if I have multiple complex subdirectories?
How should I write out my CMakeLists.txt while avoiding file(GLOB ...)?
For example;
CMakeLists.txt
/build
/src
/class_A
a.hpp
a.cpp
/class_B
b.hpp
b.cpp
/class_CB
cb.hpp
cb.cpp
/class_D
d.hpp
d.cpp
Would I just have a giant list of .cpp files, all with relative paths to each cpp file, and pass that list into the add_executable(executable ${SOURCE_FILES})? Or is there an easier way with using multiple CMakeLists.txt?
You misinterpret the install command. It is used to install your files, for example with make install.
When you configure your project, CMake will mimic the structure of your project. This means all folders are created in the same structure and the binaries appear in the according build directories.
Either place your targets in the main directory, which I would consider bad stile. Better live with build/src or give it a more meaningful name.

Building Documentation for Nested projects with CMake

I'm working on a project that contains other projects as libraries using git
submodules. These sub-projects are under active development as well, so the root
cmake file will run the sub-project cmake files as well.
Example Project Structure:
current_project/
src/
include/
docs/
libs/
sub_module_1/
src/
include/
docs/
sub_module_2/
src/
include/
docs/
sub_module_3/
src/
include/
docs/
src/
The actual building portion works fine. In some of the sub projects, the custom target docs is used to
generate the documentation. Since there are multiple docs targets defined for each
subproject, cmake complains. I don't have control over the sub-projects, and
therefore cannot simply edit the cmake files for those. Is there a way to, without
editing the sub-projects (as the changes will be overwritten when I do a git
update), either have cmake combine all the commands for each sub-project and run all
of them, or have it generate a prefix (probably the project name) for the docs
target for each project?
Edit: I see that CMake has projects as a defined term. I'm not referring to cmake projects. When I am saying project, I am referring to libraries and programs that, while related, are independent of each other.

CMake: include a directory into parent from within a subdirectory (aka library)

I have a small project with this structure:
myproject/
mylib/
include/
src/
myprog/
include/
src/
I added a CmakeLists.txt file into myproject and added the subdirectory mylib and myprog. The subdirectories got a CMakeLists, too. Now, when I run cmake, both modules are built correctly, unless I want to use mylib in myprogram. I've found solutions where the global CmakeLists defines an include_directories. But I would prefer to define this in mylib such that mylib/include is added to the project' include path. I would like a project of submodules where each submodule defines it's sources and includes and the project's CMakeLists only connects the modules together. How can I do that? Is that what I try to achieve recommanded? (cmake newbie)
You want target_include_directories. See http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html

CMake and dependencies

I have the following directory structure and library dependencies:
./lib-a
./lib-b (depending on lib-a)
Each directory contains a CMakeLists.txt file for generating its own library.
I am using an out-of-source building policy.
In order to say that lib-b depends on lib-a, I have put the command add_subdirectory(../lib-a lib-a) in ./lib-b/CMakeLists.txt, according to what is taught by the official CMake tutorial. This way I obtain that a subdirectory lib-a is created in ./lib-b/build dir.
This is not the behaviour I desire. What I would like to obtain is CMake making reference to lib-a in generating lib-b and, if lib-a has not been already generated, CMake should generate it inside ./lib-a/build by using the CMakeLists.txt of lib-a (in a behaviour similar to the one of the make tool when dealing with dependencies).
I would also like to add that I am not using a root CMakeLists.txt in my example, but what I would like to have is the lib-b/CMakeLists.txt declaring the dependency on lib-a, thus making lib-a to be compiled, if not already, by using its own lib-a/CMakeLists.txt.
Here is the dirs structure and their contents:
lib-a/
CMakeLists.txt (for compiling lib-a)
src/
test.cpp
include/
test.hpp
lib-b/
main.cpp
CMakeLists.txt (for compiling lib-b; here is the point where I would like to make reference to lib-a, that I need for the generation of lib-b)
lib-b/main.cpp contains also an include of test.hpp of lib-a, because it is using a function of lib-a. This should be taken into consideration in the specification of lib-b/CMakeLists.txt.
What should the content of the two lib-a/CMakeLists.txt and lib-b/CMakeLists.txt files be?
I think you misunderstand the tutorial. The thing that links the libraries together is target_link_library(lib_b lib_a). If the name of the dependency is a library that is part of the build, CMake will magically make the dependencies work. It has nothing to do with subdirectories. In fact, if I have the following directory structure:
./
./a.hpp
./a.cpp
./b.hpp
./b.cpp
./CMakeLists.txt
The following will set the dependencies just fine:
PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
PROJECT(lib_b)
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)
This will work across subdirectory projects as well:
./
./CMakeLists.txt
./lib_a/CMakeLists.txt
./lib_a/a.hpp
./lib_a/a.cpp
./lib_b/CMakeLists.txt
./lib_b/b.hpp
./lib_b/b.cpp
And the list files:
# ./CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
ADD_SUBDIRECTORY(lib_a)
ADD_SUBDIRECTORY(lib_b)
# ./lib_a/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(lib_a)
ADD_LIBRARY(lib_a a.hpp a.cpp)
# ./lib_b/CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(lib_b)
INCLUDE_DIRECTORIES(${lib_a_SOURCE_DIR})
ADD_LIBRARY(lib_b b.hpp b.cpp)
TARGET_LINK_LIBRARIES(lib_b lib_a)