编译一个独立的静态可执行文件

43

我正在尝试编译一个不使用动态加载器的可执行文件(ELF文件)。我构建了一个交叉编译器,将来自Linux的MIPS编译为我所制作的模拟器所用。在编译我的hello.cpp文件(hello world程序)时,我使用了-static-libgcc标志进行断言。然而,显然这还不够。因为我的可执行文件中仍然有一个段包含动态加载器的名称/路径。我需要使用哪些标志来生成包含运行所需一切的可执行文件?我需要重建我的交叉编译器吗?

2个回答

123

使用以下标志进行链接

-static -static-libgcc -static-libstdc++

使用这三个标志针对所有依赖项的静态版本进行链接(假设使用gcc)。请注意,在某些情况下,您不一定需要全部三个标志,但它们也不会“伤害”您。因此,请打开所有三个标志。

检查是否有效

  1. 确保确实没有动态链接

ldd yourexecutable

应该返回“not a dynamic executable”或等效内容。

  • 确保没有未解决的符号

  • nm yourexecutable | grep " U "
    
    列表应为空或仅包含一些特殊的内核空间符号,例如
    U __tls_get_addr
    
  • 最后,请检查您是否可以执行可执行文件


  • 26
    尝试使用-static标志?

    有没有一个很好的资源描述每个gcc标志的精确结果?我不确定是否真正禁用了动态加载。当我使用-static时,我的elf文件的.interp部分仍然有动态加载器名称。 - Dan Snyder
    1
    我明白了,那么无论如何 --disable-shared 都不会影响我的可执行文件?如果使用静态链接(只是为了确认我理解正确),那么我的可执行文件将会更大,因为运行二进制文件所需的所有内容都已经加载到 elf 文件中了?然后我只需要将程序计数器设置为入口位置,其他一切都应该能正常工作? - Dan Snyder
    尝试在可执行文件上运行“file”命令。它应该会告诉你你有哪种类型的可执行文件。 - sigjuice
    -static标志应该可以工作(我刚试过);确保您不会因为链接脚本或其他原因而意外地使用.so文件链接您的程序,您可以使用"ldd"命令进行检查。 - Tomaka17
    不知道 ldd 执行程序;但是我认为如果使用 -static 标志并且内部库没有静态版本,GCC 至少会发出警告。 - Tomaka17
    显示剩余13条评论

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接