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

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

Related

CMake copy dll transitively

Basically I want CMake to copy dependency's dll to the same directory of the executable. Suppose I have the following directory structure:
my-project/
CMakeLists.txt
lib/
CMakeLists.txt
... # Some source files
app/
CMakeLists.txt
... # Some source files
The library lib depends on some third party dll, say foo.dll. The executable in app, say app.exe, depends on lib.
I've written a FindFOO.cmake to make the third party library foo.dll an imported target named foo.
Now when I compile app, in order to run the executable, foo.dll is required to be in the same directory as app.exe. How can this be achieved automatically with cmake? And what if I want to use CPack to package the application into an installer?
CMAKE_RUNTIME_OUTPUT_DIRECTORY is your friend.
If this variable is created before creating some target, if the target is RUNTIME, it will define where the output of the target will be placed.
In your case, it can be used to force foo.dll and app.exe to be in the same folder. Your root CMakeLists.txt should look like this:
cmake_minimum_required(VERSION 3.15)
project(foo_and_app)
# app.exe and foo.dll will be in bin subfolder of build dir
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
add_subdirectory(lib)
add_subdirectory(app)
#not connected to placement, but only to package creation
include(CPack)
It should be noted that this variable is used to initialize the properties of the targets added, meaning that everything may also be achieved by directly manipulating appropriate target properties.
Regarding packaging, what you ask is possible, regardless of the placement of runtime targets, by using install cmake statement. In lib/CMakeLists.txt you should add something like this:
# suppose that the target named `foo`,
# i.e. it is added by add_library(foo SHARED .....)
install(TARGETS foo
RUNTIME DESTINATION bin
)
same should be done for app/CMakeLists.txt:
# suppose that the target named `app`,
# i.e. it is added by add_executable(app .....)
install(TARGETS app
RUNTIME DESTINATION bin
)
If you have these install statements, the final destination will be bin folder within the chosen install folder.
In the end, here are the links for CMake documentation describing:
CMAKE_RUNTIME_OUTPUT_DIRECTORY variable
RUNTIME cmake targets
install(TARGETS ...)

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 subdirectories install

I would like to set up a new project using CMake.
My working dir is the following :
CMakeLists.txt
include
- file1.h
src
- file1.cpp
- CMakeLists.txt
tests
- test1.cpp
- CMakeLists.txt
The main CMakeList.txt is the following:
cmake_minimum_required(VERSION 2.8)
project(bench CXX)
include_directories(include)
subdirs(src tests)
The src CMakeList.txt is :
add_library(foo SHARED file1.cpp)
install(TARGETS foo DESTINATION lib)
And the tests CMakeList.txt is:
add_executable(test1 test1.cpp)
target_link_libraries(test1 foo)
install(TARGETS test1 DESTINATION bin)
I would expect the files to be located in
<build_dir>/bin/test1
<build_dir>/lib/libfoo.so
But instead they are organized like this :
<build_dir>/src/test1
<build_dir>/tests/libfoo.so
What am I doing wrong ?
Thanks in advance,
You are giving instructions for the install step/build target, which is independent from the build tree under <binary_dir>.
Set CMAKE_INSTALL_PREFIX to a folder of your choice and run make install (assuming make build system here) after your build. The you will find CMAKE_INSTALL_PREFIX/lib/libfoo.so and CMAKE_INSTALL_PREFIX/bin/test1 as you told cmake. The DESTINATION path is always relative to CMAKE_INSTALL_PREFIX (unless you specify an absolute path, of course).
The compiled libs and binaries within the build tree (i.e. <build_dir>) will always reflect the source tree structure with respect to location; this cannot be changed and is not the intended way of use.
Generally there are three different "things": Source/Build/Install trees. The build tree mirrors the source tree structure and contains cmake-generated extra files and objects. The install "tree" is a setting of your choice, where CMAKE_INSTALL_PREFIX is the root directory under which libraries, archives and binaries are placed. You can control the behaviour completely (what you already intend to do!), although there are reasonable default settings.

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)