如何影响可执行文件或库的源目录?

问题描述

我最近在编译以下 C++ 程序时发现了一些奇怪的东西:

int main() { return 0; }

在 Linux 上使用 g++。具体来说,我使用以下两个命令对程序(位于 /a/directory )进行了两次编译:

  1. g++ -g -o main main.cc
  2. g++ -g -o /a/directory/main /a/directory/main.cc

对于我输入的每个程序 gdb main,输入 break main 并运行程序。当 gdb 遇到断点时,我得到以下结果:

  1. 断点 1、main () 处的 main.cc:1
  2. 断点 1,位于 main ()/a/directory/main.cc:1

简单地说,g++ 在使用调试符号编译时在二进制文件中嵌入了对源目录的引用。此外,该目录是传递给编译器的(字面的,未规范化的)目录(这是通过使用 strings 检查二进制文件来确认的)。

显然,cmake 构建执行 g++ 时目录是绝对的,至少在构建源外时是如此。相反,我遇到了一个 autotools 托管项目,其中源目录是本地目录。

实际上有valid reasons避免使用绝对构建目录,所以我想知道以下内容

我可以使用一些编译器选项影响放入库/可执行文件的源目录吗?使用 cmake 时如何为整个项目完成此操作(例如设置相对于项目根目录的目录)?

其次,我想知道Linux上是否有关于源目录的约定。理想情况下,可以安装源和工具,例如 gdb 会使用源 $PATH 之类的东西来获取实际位置。

解决方法

CMake 在编译时总是使用绝对路径,原因描述为 here

但是,您可以使用 GCC 选项 -fdebug-prefix-map 来更改嵌入在二进制文件中的调试路径。其文档位于 here

我试过了:

g++ -g -o `pwd`/main `pwd`/main.cc -fdebug-prefix-map=`pwd`=.

gdb 输出为:Breakpoint 1 at 0x1129: file ./main.cc,line 1.

对于整个项目,传递 -fdebug-prefix-map=<absolute path of source root>=<source root relative to build path> 可能会起作用。例如,如果源位于 /a/directory/ 下并且构建目录为 /a/directory/build/,那么您将传递 -fdebug-prefix-map=/a/directory/=..

编辑:之前有人回答过:Make gcc put relative filenames in debug information