CMake C / C ++宏生成[重复]

Posted

技术标签:

【中文标题】CMake C / C ++宏生成[重复]【英文标题】:CMake C/C++ macro generating [duplicate] 【发布时间】:2017-10-29 13:56:46 【问题描述】:

我在记录和调试我的程序期间使用__FILE__。当我使用它时,我会得到完整的源文件路径。所以,我想编写自己的宏,类似于宏__FILE__

我寻找了一个解决方案,但我一无所获。 那么,是否存在实现用户宏的 CMake 方式,会生成类似于__FILE__ 宏的数据?

【问题讨论】:

那为什么不直接使用__FILE__呢? 我猜您可以创建一个自定义命令,循环遍历目标的所有源文件,并在根据文件路径提取$SOURCE_FILE_NAME 变量后添加编译器标志-DFILE=$SOURCE_FILE_NAME 这是一个黄金 XY 问题。只需在记录之前处理 __FILE__ 的值 :) 它不必那样做。它所需要做的就是从__FILE__ 中删除路径,只留下文件名。您当然可以编写删除路径的 c 或 c++ 函数。 我在***.com/questions/8487986/file-macro-shows-full-path 为我的平台找到了解决方案 【参考方案1】:

只需从__FILE__ 中删除路径即可。

可能的解决方案:

#include <libgen.h>
#include <stdio.h>

#define LOG(message) \
do  \
    char* filename = basename(__FILE__); \
    printf("In %s: %s", filename, message); \
 while(false);

必须通过检查日志级别来扩展示例。并且应该使用可变数量的参数而不是固定消息。

注意:这是针对 Unix 的。假设您的操作系统提供了类似的功能。

【讨论】:

没关系,但我想在编译时计算源路径【参考方案2】:

正如我已经在评论中提到的,您可以创建一个 CMake 函数,该函数循环遍历给定目标的所有源文件,并将宏定义添加到该源文件的编译标志中。

function(add_filepath_macro target) 
    get_target_property(SOURCE_FILES $target SOURCES)

    foreach (FILE_PATH IN LISTS SOURCE_FILES)
        file(RELATIVE_PATH RELATIVE_FILE_PATH $PROJECT_SOURCE_DIR $CMAKE_CURRENT_SOURCE_DIR/$FILE_PATH)
        set_property(SOURCE $FILE_PATH APPEND PROPERTY COMPILE_DEFINITIONS FILEPATH="$RELATIVE_FILE_PATH")
    endforeach()
endfunction()

这现在在作为您传递给它的目标的一部分的每个 TU 中定义宏 FILEPATH

但有一个警告:与常规的 __FILE__ 宏相比,您不能在头文件中使用 FILEPATH 宏,因为在不同的翻译单元中包含一个这样的头会立即导致违反 ODR,因此行为未定义。

演示

让我们通过一个非常小的示例来看看它是如何工作的。从以下项目结构开始:

.
├── cmake
│   └── add_filepath_macro.cmake
├── CMakeLists.txt
├── lib
│   ├── a.cpp
│   ├── a.h
│   └── CMakeLists.txt
└── main.cpp

cmake/add_filepath_macro.cmake 文件只包含上面显示的代码。

我们有库文件

// lib/a.h
#pragma once
char const* foo();

// lib/a.cpp
#include "a.h"
char const* foo() 
    return FILEPATH;

与对应的CMakeLists.txt

# lib/CMakeLists.txt

add_library(liba
    a.cpp
)

target_include_directories(liba PUBLIC $CMAKE_CURRENT_SOURCE_DIR)
add_filepath_macro(liba)

以及一个小的演示可执行文件

// main.cpp
#include <iostream>

#include "a.h"

int main() 
    std::cout << foo() << '\n' << FILEPATH << '\n';

最后是项目CMakeLists.txt

# CMakeLists.txt

# not tested with older version, but I guess it should work with anything > 3.0
cmake_minimum_required(VERSION 3.9) 

project(cmake_filepath_macro_demo LANGUAGE CXX)

include(cmake/add_filepath_macro.cmake)
add_subdirectory(lib)

add_executable(demo
    main.cpp
)

add_filepath_macro(demo)

运行生成的可执行文件然后产生以下输出

$ ./demo 
lib/a.cpp
main.cpp

【讨论】:

以上是关于CMake C / C ++宏生成[重复]的主要内容,如果未能解决你的问题,请参考以下文章

C多行宏:do/while(0) vs scope block [重复]

C包括警卫[重复]

C ++中的宏指令和预处理器指令有啥区别[重复]

C语言 define 防止头文件重复包含

C中宏中需要括号[重复]

如何在 Vim 中重复任何命令,例如 emacs 中的“C-x z”?