使用GCC与CMake编译静态库时,能否让__FILE__宏输出相对路径?
解决CMake+GCC下__FILE__宏输出相对项目根路径的问题
完全可以实现,给你两个靠谱的方案,结合CMake和GCC的特性就能搞定:
方案一:用GCC的-fmacro-prefix-map参数直接替换路径
GCC从4.8版本开始支持-fmacro-prefix-map=OLD=NEW参数,它会把宏(比如__FILE__)里的OLD路径前缀替换成NEW。结合CMake的项目根目录变量,就能把绝对路径转成相对路径。
在根目录的CMakeLists.txt里添加以下代码:
# 获取项目根目录的绝对路径 get_filename_component(PROJECT_ROOT_ABS "${PROJECT_SOURCE_DIR}" ABSOLUTE) # 给所有目标添加编译选项,将项目根绝对路径替换为"."(对应相对项目根的路径) add_compile_options(-fmacro-prefix-map=${PROJECT_ROOT_ABS}=.)
如果项目包含多个子目录的静态库,只要根CMakeLists.txt配置了这个选项,所有子目标都会自动继承。这样__FILE__输出的就是相对于项目根的路径,比如原本的/home/user/myproj/src/libA/file.c会变成./src/libA/file.c。
方案二:自定义宏替换__FILE__(适合灵活控制场景)
如果你不想修改全局编译选项,或者需要自定义路径格式,可以自己封装宏,通过CMake给每个源文件传递相对路径,再在代码中替换__FILE__。
步骤1:在CMake中为每个源文件定义相对路径宏
在子目录的CMakeLists.txt(或根目录统一处理)中遍历源文件,计算其相对项目根的路径,再通过编译定义传递:
foreach(src_file ${SOURCES}) # 计算当前源文件相对于项目根的路径 file(RELATIVE_PATH rel_path "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${src_file}") # 为当前源文件添加编译定义,将__REL_FILE__设为相对路径字符串 set_source_files_properties(${src_file} PROPERTIES COMPILE_DEFINITIONS "__REL_FILE__=\"${rel_path}\"") endforeach()
步骤2:在源码中替换__FILE__为自定义宏
把代码里的__FILE__替换成__REL_FILE__,比如:
// 原代码 printf("Error in %s:%d\n", __FILE__, __LINE__); // 修改后 printf("Error in %s:%d\n", __REL_FILE__, __LINE__);
这个方案的优势是可以完全控制路径格式,比如是否添加前缀、调整分隔符等。
注意事项
- 方案一要求GCC版本≥4.8,若使用老版本GCC,建议升级或改用方案二。
- 方案二需要修改源码中的
__FILE__引用,若不想改动源码,优先选择方案一。 - 两种方案都不会改变CMake生成的编译命令(依然用绝对路径),但
__FILE__的输出会变成相对路径,不影响其他机器调试。
内容的提问来源于stack exchange,提问作者Krzysztof Cieniawski
相关产品推荐
相关产品推荐

