让gcc在调试信息中放置相对文件名

时间:2012-03-07 18:35:37

标签: debugging gcc cmake debug-symbols

我正在编译的项目使用CMake,loves absolute pathnames

当我在启用调试信息的情况下进行编译时,gcc会将这些长名称放入.debug_str部分,这对调试很不利。我希望在那里有一个简短的相对项目根路径名。

是否有一些选项可以告诉gcc在发出调试数据之前去掉路径名的某些部分?或者,也许有一些工具可以在已编译的二进制文件上执行此操作?

我尝试过使用SET(CMAKE_USE_RELATIVE_PATHS ON)(devs似乎是frowned upon)选项,但由于我使用的是源外构建版本,因此路径名仍然不是我的形式我希望他们成为。即他们是./../src/mod_foo/foo.c而不是mod_foo/foo.c

3 个答案:

答案 0 :(得分:14)

您可以使用 -fdebug-prefix-map 标志重新映射调试信息路径。例如,要使用相对于构建位置的路径,请使用: -fdebug-prefix-map = / full / build / path =。

答案 1 :(得分:6)

您可以设置CMake目标的RULE_LAUNCH_COMPILE属性,让CMake调用shell脚本,该脚本在调用gcc之前将源文件路径转换为项目相对路径。使用CMake函数configure_file生成一个shell脚本,该脚本可以了解项目的PROJECT_SOURCE_DIRPROJECT_BINARY_DIR

在最外面的CMakeLists.txt添加以下代码:

configure_file(
    "${PROJECT_SOURCE_DIR}/gcc_debug_fix.sh.in"
    "${PROJECT_BINARY_DIR}/gcc_debug_fix.sh"
    @ONLY)

add_executable (MyExecutable ...)

set_target_properties(MyExecutable PROPERTIES 
    RULE_LAUNCH_COMPILE "${PROJECT_BINARY_DIR}/gcc_debug_fix.sh")

以下模板shell脚本gcc_debug_fix.sh.in需要转到CMake项目的根目录:

#!/bin/sh

PROJECT_BINARY_DIR="@PROJECT_BINARY_DIR@"
PROJECT_SOURCE_DIR="@PROJECT_SOURCE_DIR@"

# shell script invoked with the following arguments
# $(CXX) $(CXX_DEFINES) $(CXX_FLAGS) -o OBJECT_FILE -c SOURCE_FILE

# extract parameters
SOURCE_FILE="${@: -1:1}"
OBJECT_FILE="${@: -3:1}"
COMPILER_AND_FLAGS=${@:1:$#-4}

# make source file path relative to project source dir
SOURCE_FILE_RELATIVE="${SOURCE_FILE:${#PROJECT_SOURCE_DIR} + 1}"

# make object file path absolute
OBJECT_FILE_ABSOLUTE="$PROJECT_BINARY_DIR/$OBJECT_FILE"

cd "$PROJECT_SOURCE_DIR"

# invoke compiler
exec $COMPILER_AND_FLAGS -c "${SOURCE_FILE_RELATIVE}" -o "${OBJECT_FILE_ABSOLUTE}"

shell脚本使用变量PROJECT_BINARY_DIRPROJECT_SOURCE_DIR中的信息将源文件的路径转换为相对于项目根目录的路径和目标文件到绝对路径的路径。因为gcc现在传递了项目相对路径,.debug_str也应该使用该路径。

以下警告适用:

  • 务必将可执行位设置为gcc_debug_fix.sh.in
  • 要使用的脚本CMAKE_USE_RELATIVE_PATHS必须再次设置为OFF
  • 该脚本假设有关命令行上文件路径的位置。如果CMake使用不同的规则来调用编译器,则这可能不起作用。更强大的解决方案是扫描-o-c标志的脚本参数。

答案 2 :(得分:1)

如果我真的无法修复make文件/工具来正确执行此操作,我会为gcc编写一个包装器脚本,用于识别绝对路径名并转换为相对路径名。

在bash中可能看起来像这样:

#!/bin/bash

out=()
for arg; do
  out=("${out[@]}" $(echo "$arg" | sed 's:/my/absolute/directory/:../:'))
done

exec gcc "${out[@]}"

如果你的源目录有子目录,那么你需要仔细处理它们,但上面的内容应该适用于平面源目录。我没有对它进行过测试,如果我的引用错误,我也不会感到惊讶,但如果你的路径名有空格,那只会是一个问题。它也不会处理像{{{}这样的参数。 1}},但你可以解决这个问题。