在CMake中使用C / C ++宏中的值

时间:2019-04-06 11:01:37

标签: cmake c-preprocessor

将C / C ++宏的值转换为CMake变量的最简单方法是什么?

鉴于我检查了标头为EchoRequest的图书馆Command。我知道libfoo包含宏foo.h,其中version是整数或字符串值。要提取找到的库的主要版本,我想使用此宏中的值。

作为奖励,如果未找到该宏,则可能表示该版本比引入该版本宏的特定版本要旧。

3 个答案:

答案 0 :(得分:2)

我将与file(READ ...)一起阅读标头,然后由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}")

答案 1 :(得分:2)

使用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;
}

好:

  • 来自变量的实际值,可以计算出来。

坏:

  • 仅某些较新的编译器支持宏的输出。
  • 对于未经测试的编译器,输出的解析可能会中断,因为格式会从编译器版本更改为编译器版本。
  • 种类繁多,难以理解的冗长代码。

答案 2 :(得分:1)

可以使用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 $4}'"
      OUTPUT_VARIABLE   FOO_VERSION_MAJOR )
message("From CMake: FOO_VERSION_MAJOR=${FOO_VERSION_MAJOR}")

请注意,awk '{ print $4}'提取所选行中的第四个单词。

运行cmake时,我们会得到结果

From CMake: FOO_VERSION_MAJOR=666

使用的简短Shel管道是使用Unix系统V基本命令构建的,应该在任何地方运行。