My project uses the same core code, and i want to build the following structure
project
|
| - core_code
| - cmake
| - CMakeLists.txt
| - example1
| |
| |- example1.cc
| |- build
|
| - example2
| |
| |- example2.cc
| |- build
I would like cmake to create targets in the build subdirectories for each example. So after I run cmake
from projects
directory then build, the structure should look like this:
project
|
| - core
| - cmake
| - CMakeLists.txt
| - example1
| |
| |- example1.cc
| |- build
| |- Makefile
| |- example1
|
| - example2
| |
| |- example2.cc
| |- build
| |- Makefile
| |- example2
What should I do in project/CMakeLists.txt
?
If you structure your project as follows:
project
|
|- CMakeLists.txt
|- core
| |
| |- core.cc
| |- core.h
| |- CMakeLists.txt
|
|- example1
| |
| |- example1.cc
| |- CMakeLists.txt
|
|- example2
|
|- example2.cc
|- CMakeLists.txt
Your project/CMakeLists.txt
file just includes the other cmakelists files
project/CMakeLists.txt
:
cmake_minimum_required (VERSION 3.5)
project (project CXX C)
add_subdirectory(core)
add_subdirectory(example1)
add_subdirectory(example2)
Your core/CMakeLists.txt
file builds the core targets
project/core/CMakeLists.txt
:
add_library(core core.cc)
target_include_directories(core PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
Your exampleN/CMakeLists.txt
file builds the example targets
project/example1/CMakeLists.txt
:
add_executable(example1 example.cc)
target_link_libraries(example1 core)
When you generate the build files, cmake mimics your directory structure in the build directory, so running the following commands would result in the below directory structure:
$ cd project
$ mkdir build
$ cd build
$ cmake ..
The resulting directory structure would look as follows:
project
|
|- CMakeLists.txt
|- core
| |
| |- core.cc
| |- core.h
| |- CMakeLists.txt
|
|- example1
| |
| |- example1.cc
| |- CMakeLists.txt
|
|- example2
| |
| |- example2.cc
| |- CMakeLists.txt
|
|- build
|
|- Makefile
|- core
| |- Makefile
|
|- example1
| |- Makefile
| |- example1
|
|- example2
|- Makefile
|- example2
Now if you only want to build example2
for example, you can execute the following:
$ cd project/build/example2
$ make
The benefit of this is that it doesn't pollute your source tree with build files. If you want to blow away the build directory, you only need to delete one directory
$ rm -r project/build
Assuming you have additional CMakeLists.txt
somewhere, e.g. at cmake/example/CMakeLists.txt
with content like:
add_executable(${EXAMPLE_NAME} ${EXAMPLE_DIR}/${EXAMPLE_NAME}.cc)
you may call it from project/CMakeLists.txt
with:
# Build the first example in the 'example1/build' subdirectory
set(EXAMPLE_NAME example1)
set(EXAMPLE_DIR ${CMAKE_SOURCE_DIR}/example1)
add_subdirectory(cmake/example ${CMAKE_SOURCE_DIR}/example1/build)
# Build the second example in the 'example2/build' subdirectory
set(EXAMPLE_NAME example2)
set(EXAMPLE_DIR ${CMAKE_SOURCE_DIR}/example2)
add_subdirectory(cmake/example ${CMAKE_SOURCE_DIR}/example2/build)
Note, that CMake generates Makefile's only in the build directory, and the only way to change build directory is add_subdirectory()
call. So you cannot get Makefile
not in the top-level directory without additional CMakeLists.txt
. But you may use single additional CMakeLists.txt
for multiple build directories.
To be precise, you may use top-level CMakeLists.txt
for examples too, but you need to make it "reentrant", which seems ugly for me.