CMake
CMake
Build the Smallest Project
Create directory structure as follows:
- Tutorial/
- build/
- CMakeLists.txt
- tutorial.cpp
The files content as follows:
# CMakeLists.txt
# Specify the minimum version of CMake.
cmake_minimum_required(VERSION 3.15)
# Specify the project name.
project(Tutorial)
# It's used to generate the executables
add_executable(Tutorial tutorial.cpp)
// tutorial.cpp
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
if (argc < 2) {
std::cout << "Usage: " << argv[0] << " number" << std::endl;
return 1;
}
// convert input to double
const double inputValue = atof(argv[1]);
// calculate square root
const double outputValue = sqrt(inputValue);
std::cout << "The square root of " << inputValue
<< " is " << outputValue
<< std::endl;
return 0;
}
Enter the directory build, and execute the command cmake -G"MinGW Makefiles" ... This will generate a file called Makefile.
Execute the command cmake --build ., which calls the compiler to compile and link the project.
--build specifies the directory where the compiled files are stored, including the executable files.
The executable file Tutorial.exe are generated in the directory build, and you can execute it.
Optimize the CMakeLists.txt
Use PROJECT_NAME to replace project name in CMakeLists.txt:
cmake_minimum_required(VERSION 3.15)
project(Tutorial)
add_executable(${PROJECT_NAME} tutorial.cpp)
We can also use a variable to represent multiple source files.
set(SRC_LIST a.cpp b.cpp c.cpp)
add_executable(${PROJECT_NAME} ${SRC_LIST})
Set the Project Version
Modify the content of CMakeLists.txt
project(Tutorial VERSION 1.0.2)
Configure the header File
Create a new file named TutorialConfig.h.in in the project root directory, and the content is as follows:
#define Tutorial_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @PROJECT_VERSION_MINOR@
#define Tutorial_VERSION_PATCH @PROJECT_VERSION_PATCH@
Add the content to CMakeList.txt as follows:
configure_file(TutorialConfig.h.in TutorialConfig.h)
TutorialConfig.h will be generated in the directory build. It depends on TutorialConfig.h.in. Therefore, it's necessary to add build to the search path list. Add the following content to the end of CMakelists.txt
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
)
PROJECT_BINARY_DIR represents the binary path of the current project. Now it's the directory build.
Add the header TutorialConfig.h to the file tutorial.cpp, then the Macro defined in TutorialConfig.h.in can be used in tutorial.cpp, including Tutorial_VERSION_MAJOR, Tutorial_VERSION_MINOR and Tutorial_VERSION_PATCH.
Add the Compile Timestamp
Add the following content to CMakeLists.txt:
string(TIMESTAMP COMPILE_TIME %Y%m%d-%H%M%S)
Add the following content to TutorialEConfig.h.in:
#define TIMESTAMP @COMPILE_TIME@
Specify the C++ Standard
Replace atof with std::stod in the file tutorial.cpp.
Add the following content before the command add_executable to CMakeLists.txt:
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
Add the Library
Now we add a library which achieve the function of square root, and use it to replace the function provided by STL.
Create the directory named MathFunctions in the project root directory. It includes 3 files named CMakeLists.txt, MathFunctions.h and mysqrt.cpp, and the content of CMakeLists.txt is as follows:
# MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)
MathFunctions.h and mysqrt.cpp include a function named mysqrt, which achieves the function of square root.
To use the library MathFunctions, we need to add the following content to top level CMakeLists.txt:
add_subdirectory(MathFunctions)
What's more, in order to use MathFunctions, tutorial.cpp needs to find the library files and the corresponding header file. We can use target_link_libraries and target_include_directories to specify. Add and modify the content in the top level CMakeLists.txt as follows:
target_link_libraries(${PROJECT_NAME} PUBLIC MathFunctions)
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/MathFunctions
)
Add the header MathFunctions.h, then we can use mysqrt function.
Make the Library Optional
Now we'll make the library MathFunctions optional.
At first, add an option to the top level CMakeLists.txt as follows:
option(USE_MYMATH "Use tutorial provided math implementation" ON)
option represents providing options that users can choose from, and its command format is option(<variable> "description" [initial value]).
The default value of USE_MYMATH is ON, which can be changed by the user.
The next change is to make the building and linking of the MathFunctions library conditional. Modify the content of the top level CMakeLists.txt as follows:
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES ${PROJECT_SOURCE_DIR}/MathFunctions)
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC ${EXTRA_LIBS})
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
${EXTRA_INCLUDES}
)
Then modify the source code of tutoral.cpp as follows:
...
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
...
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
...
Because of the using of the marco USE_MYMATH in the source code, we can add the following content to TutorialConfig.h.in:
#cmakedefine USE_MYMATH
This project calls the mysqrt function by default, we can specify USE_MYMATH to use the sqrt function of STL:
# Enter the directory build.
$ cmake -G"MinGW Makefiles" ..
$ cmake -DUSE_MYMATH=OFF ..
$ cmake --build .
Add the Requirements for the Use of the Library
Now we use a more modern method to include the header file of the MathFunctions library.
Add the below content to the CMakeLists.txt file in the directory MathFunctions:
target_include_directories(MathFunctions
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
)
Modify the top level CMakeLists.txt as follows:
...
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
)
...
Original Link
[1]:CMake 良心教程,教你从入门到入魂
[2]:CMake Tutorial

浙公网安备 33010602011771号