问题描述
我最近在编译以下 C++ 程序时发现了一些奇怪的东西:
int main() { return 0; }
在 Linux 上使用 g++
。具体来说,我使用以下两个命令对程序(位于 /a/directory
)进行了两次编译:
-
g++ -g -o main main.cc
和 -
g++ -g -o /a/directory/main /a/directory/main.cc
。
对于我输入的每个程序 gdb main
,输入 break main
并运行程序。当 gdb 遇到断点时,我得到以下结果:
- 断点 1、
main ()
处的main.cc:1
和 - 断点 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