summary:
CMake is a more advanced compilation and configuration tool than make. It can generate corresponding Makefile or vcproj projects according to different platforms and compilers. By writing cmakelists Txt, you can control the generated Makefile to control the compilation process.
We often use the Makefile automatically generated by CMake to build projects, generate target files and install files. This paper mainly introduces several common engineering structures and the writing method of the corresponding CMakeList file.
case1:
In the introductory example, all files are in the same folder.
Source code from: https://github.com/yanxicheung/CMakeNote/tree/main/CMakeDemo/case1
Directory structure:
. ├── CMakeLists.txt ├── main.cpp ├── MathFunctions.cpp └── MathFunctions.h
CMakeLists:
# CMake minimum version number requirements cmake_minimum_required (VERSION 2.8) # Project information project (Demo2) # Find all source files in the directory # And save the name to DIR_SRCS variable aux_source_directory(. DIR_SRCS) # Specify build target add_executable(Demo ${DIR_SRCS})
case2:
Multiple directories and multiple files, using an example of CMakeLists.
Source code from: https://github.com/yanxicheung/CMakeNote/tree/main/CMakeDemo/case2/quantity
Directory structure:
. ├── CMakeLists.txt ├── include │ ├── Amount.h │ └── Length.h ├── source │ └── Length.cpp └── test ├── LengthTest.cpp └── main.cpp
CMakeLists:
# Set project name project(quantity) cmake_minimum_required(VERSION 2.8) # Used to set environment variables set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") # Set header file include path include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) # Traversal file file(GLOB_RECURSE all_files source/*.cpp source/*.cc source/*.c test/*.cpp test/*.cc test/*.c) # Generate target executable add_executable(quantity-test ${all_files}) # Since the gtest framework is used, this library needs to be linked target_link_libraries(quantity-test gtest)
case3:
case3 is a multi-level directory using cmakelists Txt.
Source code from: https://github.com/yanxicheung/CMakeLists
Directory structure:
. ├── CMakeLists.txt // Top CMakeList ├── hello │ ├── CMakeLists.txt // Static libraries will be generated for top-level calls │ ├── include │ │ └── hello.h │ └── source │ └── hello.cpp ├── main.cpp └── world ├── CMakeLists.txt // Static libraries will be generated for top-level calls ├── include │ └── world.h └── source └── world.cpp
CMakeLists:
top floor:
cmake_minimum_required(VERSION 2.8) set(curr_dir ${CMAKE_CURRENT_SOURCE_DIR}) set(hello_dir ${curr_dir}/hello) set(world_dir ${curr_dir}/world) project(helloworld) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") # Add header file include directories include_directories( ${hello_dir}/include ${world_dir}/include ) # Add block directories add_subdirectory(hello) add_subdirectory(world) # Target add_executable(helloworld main.cpp) target_link_libraries(helloworld hello world)
Subdirectory hello:
set(curr_dir ${CMAKE_CURRENT_SOURCE_DIR}) include_directories( include ) aux_source_directory(${curr_dir}/source DIR_HELLO_SRCS) add_library(hello ${DIR_HELLO_SRCS}) // The default is STATIC library
Subdirectory world:
set(curr_dir ${CMAKE_CURRENT_SOURCE_DIR}) include_directories( include ) aux_source_directory(${curr_dir}/source DIR_WORLD_SRCS) add_library(world ${DIR_WORLD_SRCS}) // The default is STATIC library
case4:
In this example, we need to:
- Add compilation options for the project, so that the most appropriate compilation scheme can be selected according to the user's environment and needs: when enable_ When test is opened, a static library file libcub.exe is generated A and compile unit tests to generate executable files. Otherwise, only the static library file libcub a
- The static library file libcub A and header files are installed in the system directory.
Source code from: https://github.com/yanxicheung/cub
Directory structure:
. ├── build.sh ├── CMakeLists.txt // Top layer CMakeList ├── doc ├── include │ └── cub │ ├── algo │ ├── base │ ├── cub.h │ ├── dci │ ├── ... ├── README.md ├── src │ ├── CMakeLists.txt // Static libraries will be generated for top-level calls │ ├── log │ ├── mem │ └── sched └── test ├── CMakeLists.txt // The executable file of the unit test is generated ├── main.cpp ├── ...
CMakeLists:
top floor
cmake_minimum_required(VERSION 2.8) project("cub") if(UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof -g -std=c++14") endif() include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") add_subdirectory("src") if(ENABLE_TEST) add_subdirectory(test) endif() install(DIRECTORY include/cub DESTINATION include) #Install the header file into / usr/local/include
Static library libcub a
FILE(GLOB_RECURSE all_files *.cpp *.cc *.c++ *.c *.C) add_library(cub STATIC ${all_files} ../include/cub/network/ByteOrder.h ../test/TestByteOrder.cpp) install(TARGETS cub ARCHIVE DESTINATION lib) #Set libcub A install in / usr/local/lib # The installation part of the header file can also be written here: install (directory.. / include / cub destination include)
Unit test:
project(cub-test) include_directories(${MAGELLAN_INCLUDE_DIR}) #You can not write it. The top-level cmakelists have been included if(UNIX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") endif() FILE(GLOB_RECURSE all_files *.cpp *.cc *.c++ *.c *.C) add_executable(cub-test ${all_files}) target_link_libraries(cub-test cut cub)
Compile library files only:
cd cub mkdir build cd build cmake .. make
Install library files:
sudo make install
Generate unit test executable:
cd build cmake -DENABLE_TEST=1 .. #cmake -DENABLE_TEST=ON .. it's fine too make ./test/cub-test
case5:
This example is mainly used to demonstrate conditional compilation of source code.
Source code from: https://github.com/yanxicheung/CMakeNote/tree/main/CMakeDemo/case5
Directory structure:
. ├── CMakeLists.txt ├── main.cpp ├── MathFunctions.cpp └── MathFunctions.h
CMakeLists:
cmake_minimum_required (VERSION 2.8) project (Demo2) if(DEFINED USE_MYMATH) message("USE_MYMATH is defined") add_definitions(-DUSE_MYMATH) else() message("USE_MYMATH is not defined") endif() aux_source_directory(. DIR_SRCS) add_executable(Demo ${DIR_SRCS})
If you need to use your own implementation:
cmake -DUSE_MYMATH=ON .. make
reference:
- CMake introduction practice: https://www.hahack.com/codes/cmake/
- https://github.com/wzpan/cmake-demo
- CMake conditional compilation: https://www.cnblogs.com/binbinjx/p/5648957.html
- Conditional compilation of CMake and Cpp (I): https://www.dennisthink.com/2020/10/18/877/
- Conditional compilation of CMake and Cpp (II): https://www.dennisthink.com/2020/10/18/893/