十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
纸上学来终觉浅,觉知此时要躬行。学习一项技术最好的武器就是去实践和复盘。接触cmake有一年多了,但是真正学会cmake也是在用cmake编译项目的过程中,逐渐掌握了这门技术。本文想带着读者从一个小的点开始逐渐完善,最后做出一个涵盖绝大部分功能和满足日常需求的cmake demo工程。作者将在github中新建一个新的仓库,然后逐渐向上提交代码。最后作者会开源本项目的github网址,读者可以自行根据commit版本提示找到每一部分的源码。
二.增量开发打造一个cmake demo 2.1 github 版本管理的使用在这里我要安利一下,前些天写的这篇github教程。涵盖从进课题组开始,完成项目所需要的所有日常指令。有需要的朋友可以参考一下。
四个指令玩转git
sudo apt install cmake# ubuntu16.04 默认 3.0.5
最基本的项目是将一个源代码文件生成可执行文件。对于这么简单的项目,只需要一个三行的 CMakeLists.txt 文件即可,这是本篇教程的起点。在 目录中创建一个 CMakeLists.txt 文件,如下所示:
cmake_minimum_required(VERSION 3.0)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial tutorial.cpp)
cmake_minimum_required 指定使用 CMake 的最低版本号,project 指定项目名称,add_executable 用来生成可执行文件,需要指定生成可执行文件的名称和相关源文件。
注意,此示例在 CMakeLists.txt 文件中使用小写命令。CMake 支持大写、小写和混合大小写命令。tutorial.cpp 文件在commit first目录中,可用于计算数字的平方根。
// tutorial.cpp
#include#include#include#includeint 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;
}
mkdir build
cd build
cmake ..
cmake --build .
可执行文件Tutorial就在build目录下。
zzy@zzy-virtual-machine:~/LearnCmake/build$ ./Tutorial 5
The square root of 5 is 2.23607
2.3 优化 CMakeLists.txt 文件之前CMakeList.txt如下:
cmake_minimum_required(VERSION 3.0)
# set the project name
project(Tutorial)
# add the executable
add_executable(Tutorial tutorial.cpp)
指定了项目名后,后面可能会有多个地方用到这个项目名,如果更改了这个名字,就要改多个地方,比较麻烦,那么可以使用 == PROJECT_NAME== 来表示项目名。
add_executable(${PROJECT_NAME} tutorial.cpp)
生成可执行文件需要指定相关的源文件,如果有多个,那么就用空格隔开,比如:
add_executable(${PROJECT_NAME} test1.cpp test2.cpp test3.cpp)
我们也可以用一个变量来表示这多个源文件:
set(SRC_LIST test1.cpp test2.cpp test3.cpp )
add_executable(${PROJECT_NAME} ${SRC_LIST})
set 命令指定SRC_LIST变量来表示多个源文件,用 ${var_name} 获取变量的值。
于是原来的 CMakeLists.txt 文件就可以变成如下所示:
cmake_minimum_required(VERSION 3.0)
# set the project name
project(Tutorial)
SET(SRC_LIST tutorial.cpp)
# add the executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
这样可配置性就增强了很多,有利于后续项目扩展。
我们可以在 CMakeLists.txt 为可执行文件和项目提供一个版本号。首先,修改 CMakeLists.txt 文件,使用 project 命令设置项目名称和版本号。
cmake_minimum_required(VERSION 3.0)
# set the project name and version
project(Tutorial VERSION 1.0)
configure_file(TutorialConfig.h.in TutorialConfig.h)//配置头文件将版本号传递给源代码
由于 TutorialConfig.h 文件会被自动写入 build 目录,因此必须将该目录添加到搜索头文件的路径列表中。将以下行添加到 CMakeLists.txt 文件的末尾:
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
)
安装刚才的方式用cmake … 构建项目的过程中会在build目录中生成TutorialConfig.h
#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 0
下一步在 tutorial.cpp 包含头文件 TutorialConfig.h,最后通过以下代码打印出可执行文件的名称和版本号。
if (argc< 2) { // report version
std::cout<< argv[0]<< " Version "<< Tutorial_VERSION_MAJOR<< "."
<< Tutorial_VERSION_MINOR<< std::endl;
std::cout<< "Usage: "<< argv[0]<< " number"<< std::endl;
return 1;
}
接下来将tutorial.cpp 源码中的 atof 替换为 std::stod,这是 C++11 的特性。
const double inputValue = std::stod(argv[1]);
在 CMake 中支持特定 C++标准的最简单方法是使用 CMAKE_CXX_STANDARD 标准变量。在 CMakeLists.txt 中设置CMAKE_CXX_STANDARD为11,CMAKE_CXX_STANDARD_REQUIRED设置为True。确保在 add_executable 命令之前添加CMAKE_CXX_STANDARD_REQUIRED命令。
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
此时完整的CMakeList.txt
cmake_minimum_required(VERSION 3.0)
# set the project name
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
configure_file(TutorialConfig.h.in TutorialConfig.h)
SET(SRC_LIST tutorial.cpp)
# add the executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
)
根据刚才的方法编译运行
zzy@zzy-virtual-machine:~/LearnCmake/build$ ./Tutorial 5
The square root of 5 is 2.23607
zzy@zzy-virtual-machine:~/LearnCmake/build$ ./Tutorial
./Tutorial Version 1.0
Usage: ./Tutorial number
代码保存在github commit second版本中
Author: zzy<825830916@qq.com>Date: Sun Dec 4 20:03:34 2022 +0800
commit second
commit f5d7e8288b3956fa78028dec6fbb3d0268cfbbb0
Author: zzy<825830916@qq.com>Date: Sun Dec 4 19:37:38 2022 +0800
commit first
2.4 添加库现在我们将向项目中添加一个库,这个库包含计算数字平方根的实现,可执行文件使用这个库,而不是编译器提供的标准平方根函数。
我们把库放在名为 MathFunctions 的子目录中。此目录包含头文件 MathFunctions.h 和源文件 mysqrt.cpp。源文件有一个名为 mysqrt 的函数,它提供了与编译器的 sqrt 函数类似的功能,MathFunctions.h 则是该函数的声明。
在 MathFunctions 目录下创建一个 CMakeLists.txt 文件,并添加以下一行:
add_library(MathFunctions mysqrt.cpp)
为了使用== MathFunctions== 这个库,我们将在顶级 CMakeLists.txt 文件中添加一个add_subdirectory(MathFunctions)命令指定库所在子目录,该子目录下应包含 CMakeLists.txt 文件和代码文件。
可执行文件要使用库文件,需要能够找到库文件和对应的头文件,可以分别通过target_link_libraries和target_include_directories来指定。
使用target_link_libraries将新的库文件添加到可执行文件中,使用target_include_directories将 MathFunctions 添加为头文件目录,添加到 Tutorial 目标上,以便 mysqrt.h 可以被找到。
然后在测试文件中把函数名设置为mysqrt。
const double outputValue = mysqrt(inputValue);
完整的CMakeList.txt
cmake_minimum_required(VERSION 3.0)
# set the project name
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
configure_file(TutorialConfig.h.in TutorialConfig.h)
SET(SRC_LIST tutorial.cpp)
add_subdirectory(MathFunctions)
# add the executable
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} PUBLIC MathFunctions)
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}/MathFunctions
)
安装刚才的方式编译运行,可以得到。
zzy@zzy-virtual-machine:~/LearnCmake/build$ ./Tutorial 5
Computing sqrt of 5 to be 3
Computing sqrt of 5 to be 2.33333
Computing sqrt of 5 to be 2.2381
Computing sqrt of 5 to be 2.23607
Computing sqrt of 5 to be 2.23607
Computing sqrt of 5 to be 2.23607
Computing sqrt of 5 to be 2.23607
Computing sqrt of 5 to be 2.23607
Computing sqrt of 5 to be 2.23607
Computing sqrt of 5 to be 2.23607
The square root of 5 is 2.23607
代码在github仓库提交版本 commit third中
2.5 将库设置为可选选项现在将 MathFunctions 库设为可选的,虽然对于本教程来说,功能已经完成了,但对于较大的项目来说,这种情况很常见。
第一步是向顶级 CMakeLists.txt 文件添加一个选项。
option(USE_MYMATH "Use tutorial provided math implementation" ON)
option表示提供用户可以选择的选项。命令格式为:option( "description [initial value])。
==USE_MYMATH ==这个选项缺省值为 ON,用户可以更改这个值。此设置将存储在缓存中,以便用户不需要在每次构建项目时设置该值。
下一个更改是使 MathFunctions 库的构建和链接成为条件。于是创建一个 if 语句,该语句检查选项USE_MYMATH的值。
在 if 块中,有 add_subdirectory 命令和 list 命令,APPEND表示将元素MathFunctions追加到列表EXTRA_LIBS中,将元素 ${PROJECT_SOURCE_DIR}/MathFunctions 追加到列表EXTRA_INCLUDES中。EXTRA_LIBS 存储 MathFunctions 库,EXTRA_INCLUDES 存储 MathFunctions 头文件。
变量EXTRA_LIBS用来保存需要链接到可执行程序的可选库,变量EXTRA_INCLUDES用来保存可选的头文件搜索路径。这是处理可选组件的经典方法,我将在下一步介绍现代方法。
接下来对源代码的进行修改。首先,在 tutorial.cpp 中包含 MathFunctions.h 头文件,
然后,还在 tutorial.cpp 中,使用 USE_MYMATH 选择使用哪个平方根函数:
#ifdef USE_MYMATH
#include "MathFunctions.h"
#endif
#ifdef USE_MYMATH
const double outputValue = mysqrt(inputValue);
#else
const double outputValue = sqrt(inputValue);
#endif
因为源代码使用了 USE_MYMATH 宏,可以用下面的行添加到 tutorialconfig.h.in 文档中:
// TutorialConfig.h.in
#cmakedefine USE_MYMATH
完整的CMakeLists如下:
cmake_minimum_required(VERSION 3.0)
# set the project name
project(Tutorial VERSION 1.0)
# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
configure_file(TutorialConfig.h.in TutorialConfig.h)
SET(SRC_LIST tutorial.cpp)
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(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} PUBLIC ${EXTRA_LIBS})
target_include_directories(${PROJECT_NAME} PUBLIC
${PROJECT_BINARY_DIR}
${EXTRA_INCLUDES}
)
option(USE_MYMATH "Use tutorial provided math implementation" ON)
测试:
zzy@zzy-virtual-machine:~/LearnCmake/build$ cmake .. -USE_MYMATH=OFF
zzy@zzy-virtual-machine:~/LearnCmake/build$ ./Tutorial 5
The square root of 5 is 2.23607
代码在commit four版本中
commit 31e20019090c3fc6b0edc4e1bb96a56d818b63ee
Author: zzy<825830916@qq.com>Date: Sun Dec 4 20:27:57 2022 +0800
commit four
commit a48dbcd622b99708dd4fac0af6e82a769737b7bf
Author: zzy<825830916@qq.com>Date: Sun Dec 4 20:16:35 2022 +0800
third commit
commit 14a1b053935e4d2d2036044470b3efcd86600010
Author: zzy<825830916@qq.com>Date: Sun Dec 4 20:03:34 2022 +0800
commit second
commit f5d7e8288b3956fa78028dec6fbb3d0268cfbbb0
Author: zzy<825830916@qq.com>Date: Sun Dec 4 19:37:38 2022 +0800
commit first
三.结语到这里整个教程就结束了,教程源码在https://github.com/tongjiaxuan666/CmakeLearn
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧