前一章介绍了 cmake 的基本语法 以及如何构建一个最简单的工程。这里接着聊一聊使用 cmake 构建工程的常用操作:添加库
一、由源代码添加库
这一节中我们将向工程中添加一个库项目。
假设我们需要开发一个 mathlib
库, 并在其他项目中调用,可以像下面这样操作:
1. 在工程路径下建立子文件夹 mathlib
2. 在 ./mathlib
中添加项目源文件 mymath.h
, mymath.cxx
,并添加 CMakeLists.txt
:
前一章介绍了 cmake 的基本语法 以及如何构建一个最简单的工程。这里接着聊一聊使用 cmake 构建工程的常用操作:添加库
这一节中我们将向工程中添加一个库项目。
假设我们需要开发一个 mathlib
库, 并在其他项目中调用,可以像下面这样操作:
1. 在工程路径下建立子文件夹 mathlib
2. 在 ./mathlib
中添加项目源文件 mymath.h
, mymath.cxx
,并添加 CMakeLists.txt
:
cmake 文件包括 CMakeLists.txt
和以 .cmake
为后缀的文件。
程序源文件最外层的 CMakeLists.txt 文件是 cmake 的入口文件,这个文件可以定义了整个工程的构建规范。它也可以使用 add_subdirectory()
命令来包含一个子文件夹,每个使用该命令添加的子文件夹中也需要有一个 CMakeLists.txt 文件。
在 cmake 中, 变量都是以字符串的形式存在的。使用 set( )
包装变量, 使用 ${}
展开变量。${}
可以嵌套使用。 使用未包装的变量会导致空展开:
1 2 3 4 5 6 7 8 9 10 |
set(var_name_1 var1) message("var_name is ${var_name_1}") set(var_name_2 var2) set(${var_name_2} var) #same as set(var2 var) set(${${var_name_2}}_x foo) #same as set(var_x foo) message("var2 is ${var2}") message("var_name_2 is ${var_name_2}") message("var_x is ${var_x}") message("empty var is ${empty_var}") |
执行结果如下:
1 2 3 4 5 |
var_name is var1 var2 is var var_name_2 is var2 var_x is foo empty var is |
当我们在构建工程时,在不同的平台上使用不同的工具,如在Windows上使用 Visual Studio 工程, 在 Mac 上使用 Xcode 工程。
这些工程只限于特定的平台。当我们需要跨平台构建工程时,就需要使用 CMake
了,它是一个开源的 跨平台系统构建工具
。同一个 CMake 工程可以在不同的平台上转换为与平台适应的工具,极大的方便了跨平台工程构建。
新建一个空目录,在其中新建一个文本文件,命名为 CMakeLists.txt
,并输入以下内容:
1 |
message("Hello,This is my first cmake project") |
好了,你的第一个 cmake 工程就已经建好了。接下来,新建一个文件夹 build
, 并在该文件夹下运行命令:
1 |
cmake .. |
你可能会得到以下输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-- Building for: Visual Studio 15 2017 -- The C compiler identification is MSVC 19.15.26732.1 -- The CXX compiler identification is MSVC 19.15.26732.1 -- Check for working C compiler: ....../cl.exe -- Check for working C compiler: ....../cl.exe -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler: ....../cl.exe -- Check for working CXX compiler: ....../cl.exe -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done Hello,This is my first cmake project -- Configuring done -- Generating done -- Build files have been written to: ....../build |
再来看这个路径下,cmake 生成了一堆文件:
我们成功的使用 cmake 在 Windows 上构建了一个 vs 工程。 当然,如果你的操作系统是 MacOS, 或者 Linux, 结果后有所不同。
其实在 CMakeLists.txt 所以在路径下也能运行 cmake 命令。不过cmake没有提供专门的工具来清理生成的文件,为了方便管理,我们将其生成在 build 目录下。
这个 cmake 工程的作用仅仅是输出一了条消息,并没有什么意义。下面我们来让它更有意义一点:
为满足需求:
项目编译前需要预处理一些自定义命令,如生成代码文件,拷贝成果文件等。
解决该问题有两种方案:
vcxproj 可以自定义生成事件,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<ItemDefinitionGroup> <PreBuildEvent> <Command>copy $(ProjectDir)main.cpp $(ProjectDir)copyOfMain.cpp</Command> <Message>Making a copy of main.cpp </Message> </PreBuildEvent> <PreLinkEvent> <Command>copy $(ProjectDir)$(Configuration)\main.obj $(ProjectDir)$(Configuration)\copyOfMain.obj</Command> <Message>Making a copy of main.obj</Message> </PreLinkEvent> <PostBuildEvent> <Command>copy $(ProjectDir)$(Configuration)\$(TargetFileName) $(ProjectDir)$(Configuration)\copyOfMyproject.exe</Command> <Message>Making a copy of myproject.exe</Message> </PostBuildEvent> </ItemDefinitionGroup> |
本篇记录在使用 CMake 中遇到的一些问题及解决办法
参考资料: