有没有简单的方法让gcc省略掉crtbegin.o/crtend.o?

13
除了使用-nostdlib并自己链接crt1.o -lc -lgcc之外,是否有更简单的方法可以防止gcc链接crtbegin[S].ocrtend[S].o?这些文件不是很大,但我正在尝试制作小型二进制文件,并希望删除无用的C ++支持代码,因为对于C程序而言不需要它们。(大概是,gcc即使对于C程序也链接它们,以防您在C++库中使用全局对象变量。我会免除每个人对该如何在C ++模块中生成安全的一次性初始化调用,而不是在main之前初始化全局对象的怒吼......)

我不反对修改gcc specs文件,使C++支持文件的链接取决于某个条件,但我不确定如何做到这一点。也许已经有一个好的方法了吗?


我相信它们也适用于__attribute__ ((constructor))(以及destructor)函数。(虽然我并不是一个C++专家,但据说为了符合标准,在调用main()之前必须先执行全局构造函数。) - caf
@caf:我曾经认为C++标准规定构造函数在程序调用和对象第一次使用之间的某个不确定时间被调用(当然,除了一个对象引用另一个对象并因此调用“第一次使用”之外,顺序也是不确定的)。你有相反的参考资料吗? - R.. GitHub STOP HELPING ICE
也许是一个“吃蛋的老师”,但你尝试过使用gcc进行编译,然后直接使用系统链接器(可能是ld)进行实际的链接步骤,以便更好地控制链接吗? - CB Bailey
@Charles:我知道我可以这样做,但是那样我就必须自己去找标准库文件和库路径。这比使用“gcc -nostdlib”略微麻烦一些。 - R.. GitHub STOP HELPING ICE
我目前正在使用specs文件进行黑客攻击以跳过链接那些文件;在shell中编写了一个gcc包装器,如下:exec /usr/bin/gcc --specs /usr/lib/gcc/specs-no-c++ "$@"。对我来说,这是最简单的方法。 - Low power
2个回答

8
gcc -wrapper sh,-c,'z= ; for i ; do [ "$z" ] || set -- ; z=1 ;
    case "$i" in *crtbegin*.o|*crtend*.o) ;; *) set -- "$@" "$i" ;; esac ;
    done ; exec "$0" "$@"'

1
有人可以解释一下上面的脚本正在发生什么吗? - 4aRk Kn1gh7
@4aRkKn1gh7:-wrapper选项让gcc调用外部命令,通过包装程序运行。包装程序是一个shell脚本,在调用请求的命令之前删除与*crtbegin*.o*crtend*.o匹配的任何参数。它只是在命令行上内联编写,而不是将脚本保存到文件中。 - R.. GitHub STOP HELPING ICE

4
我认为您需要使用 -nostartfiles 选项。无论是嵌入式设备还是其他,这都是我需要的。

2
这是一个不错的开始(无恶意),但它也省略了包含“_start”入口点的crt1.o - R.. GitHub STOP HELPING ICE
@R..:我相信你可以在链接脚本中设置ENTRYPOINT。 - leppie
是的,我知道我可以这样做,但那比找到crt1.o路径并使用gcc命令行链接要糟糕得多。基本上,我正在寻找最接近可移植方式的方法来让gcc不链接不必要的东西,而答案似乎是没有。 - R.. GitHub STOP HELPING ICE
2
crt1.o 不是 C++ 支持的垃圾。它是 C 代码的正常入口点,从内核给程序提供的初始状态中提取 argcargv 和指向环境的指针,并使用它来调用 exit(main(argc, argv)); - R.. GitHub STOP HELPING ICE
2
顺便提一下,gcc -print-file-name=crt1.o 命令会给出 crt1.o 的路径名,你可以在传递 -nostartfiles 参数后重新添加它。 - R.. GitHub STOP HELPING ICE
显示剩余2条评论

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