002-【CMake】动态生成代码

写代码时不免需要使用到一些常量或是宏,一些常量或宏在每次编译时可能需要取不同的值。比如用宏来充当编译开关,现编写一个网络教学系统,系统包括两个终端--【教师端】和【学生端】。两个终端大部分代码是相同的只有少部分功能不同,这时通常会选择使用编译开关来控制源代码的编译结果。如下:

#include "Windows.h" //虽然CMake是跨平台的,本文只演示Windows下使用CMake,因此引入了Windows.h
#include "stdio.h"

int main()
{
#ifdef TEACHER
  printf("Howdy CMake. I am a teacher");
#elif
  printf("Howdy CMake. I am a student");
#endif
  system("pause");
  return 0;  
}

上面的代码中用【TEACHER】这个编译开关控制编译结果是【教师端】还是学生端【学生端】。使用编译开关通常有两种做法:一、在头文件中定义【TEACHER】然后引用这个头文件。二、在编译选项中定义【TEACHER】,比如g++编译器的【-D】选项。

CMake给我们提供了另一种方式

我们可以在【CMakeLists.txt】中定义变量,然后在源代码中引用这些变量,达到动态生成原代码的目的。实质上就是把变量的值赋值到引用它的地方。

因此我们要做两件事。一、在【CMakeLists.txt】定义变量。二、在源代码中引用变量

定义变量

CMake定义变量使用【set】命令。【set】命令的第一个值是变量名,第二个值是变量的值。现在我们在【CMakeLists.txt】定义变量【YPTE】用于定义【TEACHER】

#cmake_minimum_required 指明需要使用的CMake软件的最低版本,我下载的是3.14因此就写3.14了
cmake_minimum_required (VERSION 3.14)

#project指明项目名称,对应Visual Studio解决方案和项目的名称
project (HelloCMake)

#定义TYPE变量
set (TYPE "#define TEACHER")

#add_executable 指明生成可执行文件的名称(HelloCMake),和生成可执行文件依赖的源文件(HelloCMake.cpp)
add_executable(HelloCMake HelloCMake.cpp)

引用变量

编写输入文件

说是引用变量,实质上并不是在源代码中直接引用。而是需要先编写一个CMake的输入文件,然后在这个输入文件中引用变量。CMake会读输入文件,然后将文件中的变量替换掉,最后生成一个输出文件。这个输出文件才是我们需要的源代码。

首先编写输入文件。编译一个输入文件名称为SystemDef.h.in。放到与CMakeLists.txt同目录下。内容如下:

@TYPE@

用【@】包裹表示此处引用CMake变量

修改CMakeLists.txt

定义完变量和编写完输入文件后我们需要告诉CMake生成输出文件。使用命令【configure_file】,该命令有两个参数,参数1为输入文件,参数2为输出文件。就改后的CMakeLists.txt如下

#cmake_minimum_required 指明需要使用的CMake软件的最低版本,我下载的是3.14因此就写3.14了
cmake_minimum_required (VERSION 3.14)

#project指明项目名称,对应Visual Studio解决方案和项目的名称
project (HelloCMake)

#定义TYPE变量
set (TYPE "#define TEACHER")

#让CMake动态生产SystemDef.h
configure_file("${PROJECT_SOURCE_DIR}/SystemDef.h.in" "${PROJECT_BINARY_DIR}/SystemDef.h")

#将SystemDef.h的目录加入到工程
include_directories("${PROJECT_BINARY_DIR}")

#add_executable 指明生成可执行文件的名称(HelloCMake),和生成可执行文件依赖的源文件(HelloCMake.cpp)
add_executable(HelloCMake HelloCMake.cpp)

其中 PROJECT_SOURCE_DIR 和 PROJECT_BINARY_DIR 是两个CMake内置变量。分别代表我们在GUI中选择的两个目录

include_directories命令用于在项目中添加头文件目录。可以理解为g++ 的-I指令

引用生成的头文件

经过以上步骤后在生成的VS项目的目录中产生了【SystemDef.h】他的内容为

#define TEACHER

看到这大家应该可以明白了,接下来就是正常引用头文件了。

#include "Windows.h" //虽然CMake是跨平台的,本文只演示Windows下使用CMake,因此引入了Windows.h
#include "stdio.h"
#include "SystemDef.h" //引用动态生成的SystemDef.h

int main()
{
#ifdef TEACHER
  printf("Howdy CMake. I am a teacher");
#else
  printf("Howdy CMake. I am a student");
#endif
  system("pause");
  return 0;  
}

执行结果

再将TYPE的值改成其他,比如STUDENT,再次生成一遍工程查看结果

本节定义编译开关,只是一个例子,说明如何动态生成文件。大家可以开动脑筋灵活运用此功能

猜你喜欢

转载自blog.csdn.net/patronwa/article/details/89840523
今日推荐