CMake C / C ++宏生成

时间:2017-10-29 13:56:47

标签: c++ c cmake

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

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

2 个答案:

答案 0 :(得分:2)

只需从__FILE__删除路径。

可能的解决方案:

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

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

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

注意:这适用于Unix。假设您的操作系统提供了类似的功能。

答案 1 :(得分:1)

正如我在评论中已提到的,您可以创建一个循环遍历给定目标的所有源文件的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