目录
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