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

l3zydbqr  于 2022-11-11  发布在  C/C++
关注(0)|答案(3)|浏览(316)

将C/C++宏的值导入CMake变量的最简单方法是什么?
假设我检查一个库libfoo,其头文件为foo.h。我知道foo.h包含宏#define FOO_VERSION_MAJOR <version>,其中version是一个整数或字符串值。为了提取找到的库的主版本,我想使用此宏中的值。
另外,如果找不到宏,则可能表示版本早于引入版本宏的特定版本。

h79rfbju

h79rfbju1#

我将使用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}")
xkftehaa

xkftehaa2#

通过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;
}

好的:

  • 变量的实际值,可能是计算得出的。

不良:

  • 只有一些较新的编译器才支持宏输出。
  • 对于未测试的编译器,输出的分析可能会中断,因为格式会随着编译器版本的不同而变化。
  • 一种复杂的代码,冗长的代码,难以阅读。
llmtgqce

llmtgqce3#

宏扩展可以通过使用C预处理器来提取。我使用这个方法来提取特定的typedef,而不需要知道define在文件层次结构中的确切位置。
假设我们在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}'提取所选行上的第4个字。
当运行cmake时,我们得到以下结果

From CMake: FOO_VERSION_MAJOR=666

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

相关问题