在 CMake 中使用来自 C/C++ 宏的值
Use value from C/C++ macro in CMake
将 C/C++ 宏的值放入 CMake 变量的最简单方法是什么?
假设我用 header foo.h
检查库 libfoo
。我知道 foo.h
包含宏 #define FOO_VERSION_MAJOR <version>
,其中版本是整数或字符串值。要提取找到的库的主要版本,我想使用此宏中的值。
作为奖励,如果找不到宏,这可能表明版本比引入版本宏的特定版本更早。
我会用 file(READ ...)
阅读 header,然后 string(REGEX ...)
来提取所需的定义。
示例代码:
file(READ "foo.h" header)
string(REGEX MATCH "#define FOO_MAJOR_VERSION [0-9]+" macrodef "${header}")
string(REGEX MATCH "[0-9]+" FooMajorVersion "${macrodef}")
使用try_compile
和正确的编译指示可以在编译时输出预处理器宏的值。 CMake 可以解析输出以获得所需的值。
CMake 片段:
try_compile(result "${CMAKE_BINARY_DIR}"
SOURCES "${CMAKE_SOURCE_DIR}/foo-version.cpp"
OUTPUT_VARIABLE fooversion)
string(REGEX MATCH ": [0-9]+" fooversionshort "${fooversion}")
string(REGEX MATCH "[0-9]+" FooMajorVersion "${fooversionshort}")
foo-version.cpp:
#include "foo.h"
/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#pragma message(VALUE(FOO_MAJOR_VERSION))
int main()
{
return 0;
}
好:
- 来自变量的实际值,可能会计算出来。
差:
- 只有一些较新的编译器支持宏的输出。
- 对于未经测试的编译器,输出解析可能会中断,因为格式会随着编译器版本的不同而变化。
- 那种复杂的代码,冗长的代码,难以阅读。
可以使用C 预处理器提取宏展开。
我使用这种方法提取特定的 typedef,而无需知道定义在文件层次结构中的确切位置。
假设我们在 foo.h
的某处定义了这个宏
#define FOO_VERSION_MAJOR 666
您需要使用此内容创建帮助文件helper.c
#include "foo.h"
int __READ_FOO_MAJOR__ = FOO_VERSION_MAJOR ;
请注意,我使用了一个特定的模式 __READ_FOO_MAJOR__
,稍后我将使用它作为 grep
命令的模式
从 CMakeLists.txt
开始,您必须像这样调用 C(C++ 等)预处理器并过滤其输出
cmake_minimum_required(VERSION 3.0)
execute_process(
COMMAND bash "-c" "${CMAKE_C_COMPILER} -E ${CMAKE_CURRENT_SOURCE_DIR}/helper.cpp | grep __READ_FOO_MAJOR__ | awk '{ print }'"
OUTPUT_VARIABLE FOO_VERSION_MAJOR )
message("From CMake: FOO_VERSION_MAJOR=${FOO_VERSION_MAJOR}")
请注意,awk '{ print }'
提取所选行的第 4 个单词。
当运行宁cmake
我们得到这个结果
From CMake: FOO_VERSION_MAJOR=666
使用的短 shell 管道是用 Unix 系统 V 基本命令构建的,应该 运行 无处不在。
将 C/C++ 宏的值放入 CMake 变量的最简单方法是什么?
假设我用 header foo.h
检查库 libfoo
。我知道 foo.h
包含宏 #define FOO_VERSION_MAJOR <version>
,其中版本是整数或字符串值。要提取找到的库的主要版本,我想使用此宏中的值。
作为奖励,如果找不到宏,这可能表明版本比引入版本宏的特定版本更早。
我会用 file(READ ...)
阅读 header,然后 string(REGEX ...)
来提取所需的定义。
示例代码:
file(READ "foo.h" header)
string(REGEX MATCH "#define FOO_MAJOR_VERSION [0-9]+" macrodef "${header}")
string(REGEX MATCH "[0-9]+" FooMajorVersion "${macrodef}")
使用try_compile
和正确的编译指示可以在编译时输出预处理器宏的值。 CMake 可以解析输出以获得所需的值。
CMake 片段:
try_compile(result "${CMAKE_BINARY_DIR}"
SOURCES "${CMAKE_SOURCE_DIR}/foo-version.cpp"
OUTPUT_VARIABLE fooversion)
string(REGEX MATCH ": [0-9]+" fooversionshort "${fooversion}")
string(REGEX MATCH "[0-9]+" FooMajorVersion "${fooversionshort}")
foo-version.cpp:
#include "foo.h"
/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#pragma message(VALUE(FOO_MAJOR_VERSION))
int main()
{
return 0;
}
好:
- 来自变量的实际值,可能会计算出来。
差:
- 只有一些较新的编译器支持宏的输出。
- 对于未经测试的编译器,输出解析可能会中断,因为格式会随着编译器版本的不同而变化。
- 那种复杂的代码,冗长的代码,难以阅读。
可以使用C 预处理器提取宏展开。 我使用这种方法提取特定的 typedef,而无需知道定义在文件层次结构中的确切位置。
假设我们在 foo.h
#define FOO_VERSION_MAJOR 666
您需要使用此内容创建帮助文件helper.c
#include "foo.h"
int __READ_FOO_MAJOR__ = FOO_VERSION_MAJOR ;
请注意,我使用了一个特定的模式 __READ_FOO_MAJOR__
,稍后我将使用它作为 grep
命令的模式
从 CMakeLists.txt
开始,您必须像这样调用 C(C++ 等)预处理器并过滤其输出
cmake_minimum_required(VERSION 3.0)
execute_process(
COMMAND bash "-c" "${CMAKE_C_COMPILER} -E ${CMAKE_CURRENT_SOURCE_DIR}/helper.cpp | grep __READ_FOO_MAJOR__ | awk '{ print }'"
OUTPUT_VARIABLE FOO_VERSION_MAJOR )
message("From CMake: FOO_VERSION_MAJOR=${FOO_VERSION_MAJOR}")
请注意,awk '{ print }'
提取所选行的第 4 个单词。
当运行宁cmake
我们得到这个结果
From CMake: FOO_VERSION_MAJOR=666
使用的短 shell 管道是用 Unix 系统 V 基本命令构建的,应该 运行 无处不在。