CMake官方文档:
https://cmake.org/cmake/help/v3.17/guide/tutorial/index.html#adding-system-introspection-step-5
CMake的优点
高效 、强大 、开发团队的首选
一、基础
1、按照官网教程准备计算平方根的代码,这里命名为calculatesqrt.cpp
2、编写相应的CMakeLists.txt文件
3、创建build目录
其中源代码可以参考官方github,具体如下
需要在CMakeLists.txt文件中指定如下几项,cmake版本、工程名、构建目标app的源文件
cmake_minimum_required(VERSION 3.10)
# set the project name
project(CalculateSqrt)
# add the executable
add_executable(CalculateSqrt hello.cxx)
现有目录结构如下图所示(忽略.http://h.in文件,后面会讲到)
为构建可执行文件需要执行如下命令
执行后在build目录中多了一个可执行文件CalculateSqrt
二、为项目添加版本号和可配置的头文件
虽然可以在源码中指定具体的版本,但是通过CMakeLists.txt来指定项目的版本号则更加的灵活
在CMakelists.txt中首先指定project的版本号,然后添加可配置的同文件,指定C++版本为c++11
cmake_minimum_required(VERSION 3.10)
# 设定工程名和版本号
project(CalculateSqrt VERSION 1.0)
# configure_file的作用将一份文件拷贝到另一个位置并修改它的内容,使得在代码中使用CMake中定义的变量
# configure_file官方文档:https://cmake.org/cmake/help/latest/command/configure_file.html
configure_file(CalculateSqrtConfig.h.in CalculateSqrtConfig.h)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# add the executable
add_executable(CalculateSqrt calculate.cpp)
# 指定项目编译的时候需要include的文件路径,PROJECT_BINARY_DIR变量为编译发生的目录,也就是make执行的目录,PROJECT_SOURCE_DIR为工程所在的目录
# target_include_directories官方文档:https://cmake.org/cmake/help/v3.3/command/target_include_directories.html
target_include_directories(CalculateSqrt PUBLIC
"${PROJECT_BINARY_DIR}"
)
在源代码的同级目录创建http://CalculateSqrtConfig.h.in文件并指定如下内容
// the configured options and settings for CalculateSqrt,@@引用的变量可以通过CMakeLists.txt来设置
#define CalculateSqrt_VERSION_MAJOR @CalculateSqrt_VERSION_MAJOR@
#define CalculateSqrt_VERSION_MINOR @CalculateSqrt_VERSION_MINOR@
同时需要在源代码中引入(#include)配置生成的头文件,即CalculateSqrtConfig.h
具体源代码如下
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <math.h>
#include "CalculateSqrtConfig.h"
int main(int argc, char* argv[]){
if(argc<2){
std::cout << argv[0] << " Version " << CalculateSqrt_VERSION_MAJOR << "."
<< CalculateSqrt_VERSION_MINOR << std::endl;
fprintf(stdout, "Uage: %s numbern", argv[0]);
return 1;
}
double inputValue = atof(argv[1]);
double outputValue = sqrt(inputValue);
fprintf(stdout, "The square root of %g is %gn",inputValue, outputValue);
return 0;
}
三、为工程添加链接库lib
在本例中我们为工程添加一个lib,这个lib会包含我们自己实现的平方根计算函数,我们将自己定义的平方根计算函数放置在MathFunction目录下,同时在该目录下需要添加一个新的CMakelists.txt文件,具体内容如下
# 使用特定的源码为项目增加lib
add_library(MathFunctions mysqrt.cpp)
为了在源码中使用我们自己定义的平方根函数,需要在上层的CMakeLists.txt中做相应的修改
cmake_minimum_required(VERSION 3.10)
# set the project name
project(CalculateSqrt VERSION 1.0)
configure_file(CalculateSqrtConfig.h.in CalculateSqrtConfig.h)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# add the MathFunctions library,Add a subdirectory to the build,将新加的子目录用于build
add_subdirectory(MathFunctions)
# add the executable
add_executable(CalculateSqrt calculate.cpp)
# 该指令的作用为将目标文件与库文件进行链接
# target_link_libraries官方文档:https://cmake.org/cmake/help/latest/command/target_link_libraries.html
target_link_libraries(CalculateSqrt PUBLIC MathFunctions)
target_include_directories(CalculateSqrt PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_SOURCE_DIR}/MathFunctions"
)
接下来我们尝试将自己定义的lib更改为可选的,该功能在本例中不是必要的,但是在大型的项目中却是一个比较常见的功能,具体操作如下。首先就是在上层的CMakeLists.txt中增加一个option,然后将lib和include路径增加到EXTRA_LIBS和EXTRA_INCLUDE两个变量中,具体上层的CMakeLists.txt修改为如下
cmake_minimum_required(VERSION 3.10)
# set the project name
project(CalculateSqrt VERSION 1.0)
option(USE_MYMATH "Use tutorial provided math implementation" ON)
configure_file(CalculateSqrtConfig.h.in CalculateSqrtConfig.h)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# add the MathFunctions library,Add a subdirectory to the build
#add_subdirectory(MathFunctions)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
endif()
# add the executable
add_executable(CalculateSqrt calculate.cpp)
target_link_libraries(CalculateSqrt PUBLIC ${EXTRA_LIBS})
target_include_directories(CalculateSqrt PUBLIC
"${PROJECT_BINARY_DIR}"
"${EXTRA_INCLUDES}"
)
其次需要在可配置的头文件中添加cmakelists.txt中定义的变量USE_MYMATH
// the configured options and settings for CalculateSqrt
#define CalculateSqrt_VERSION_MAJOR @CalculateSqrt_VERSION_MAJOR@
#define CalculateSqrt_VERSION_MINOR @CalculateSqrt_VERSION_MINOR@
#cmakedefine USE_MYMATH
最后我们在源码中include相应的头文件即可
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <math.h>
#include "CalculateSqrtConfig.h"
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
int main(int argc, char* argv[]){
if(argc<2){
std::cout << argv[0] << " Version " << CalculateSqrt_VERSION_MAJOR << "."
<< CalculateSqrt_VERSION_MINOR << std::endl;
fprintf(stdout, "Uage: %s numbern", argv[0]);
return 1;
}
double inputValue = atof(argv[1]);
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
fprintf(stdout, "The square root of %g is %gn",inputValue, outputValue);
return 0;
}
四、为lib增加使用需求
根据不同使用场景,可以对如下命令指定相应的使用需求
- target_compile_definitions()
- target_compile_options()
- target_include_directories()
- target_link_libraries()
以上文例子为例,在代码中想要调用MathFunctions中的函数,就需要#include对应的代码路径,然而MathFunctions本身不需要#include,所以这里采用INTERFACE来满足该需求,将MathFunctions中的CMakeLists.txt更改为
add_library(MathFunctions mysqrt.cpp)
target_include_directories(MathFunctions INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
同时我们可以将上层目录中的CMakeLists.txt中的EXTRA_INCLUDE变量去掉,同时将其从target_include_directiontarget_include_directories中删除
cmake_minimum_required(VERSION 3.10)
# set the project name
project(CalculateSqrt VERSION 1.0)
option(USE_MYMATH "Use tutorial provided math implementation" ON)
configure_file(CalculateSqrtConfig.h.in CalculateSqrtConfig.h)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
# add the MathFunctions library,Add a subdirectory to the build
#add_subdirectory(MathFunctions)
if(USE_MYMATH)
add_subdirectory(MathFunctions)
list(APPEND EXTRA_LIBS MathFunctions)
endif()
# add the executable
add_executable(CalculateSqrt calculate.cpp)
target_link_libraries(CalculateSqrt PUBLIC ${EXTRA_LIBS})
target_include_directories(CalculateSqrt PUBLIC
"${PROJECT_BINARY_DIR}"
)
五、安装和测试
接下来我们会添加install规则和testing到工程,install规则非常简单,对于MathFunctions库来说,我们在MathFunctions/CMakeLists.txt中添加如下两行来实现安装库和头文件
install(TARGETS MathFunctions DESTINATION lib)
install(FILES MathFunctions.h DESTINATION include)
对于应用来说,我们在上层的CMakeLists.txt中添加如下两行来实现安装目标文件和可配置头文件
install(TARGETS CalculateSqrt DESTINATION bin)
install(FILES "${PROJECT_BINARY_DIR}/CalculateSqrtConfig.h"
DESTINATION include
)
这样我们在执行cmake..&&make install之后,指定的库、头文件和目标文件就安装到指定的目录中了,具体如下