gcc如何决定隐式包含哪些库?

gcc如何决定隐式包含哪些库?

问题描述:

参考this questiongcc如何决定隐式包含哪些库?

对于一个小型微型嵌入式项目,我发现我的编译代码大小比预期的大得多。原来,这是因为我包含了使用assert()的代码。在包含的代码中使用assert是合适的,但导致我的编译代码大小几乎翻了一番。

问题不在于if/when应该使用assert,而是编译器/链接器如何决定包含断言的所有必要开销。

我从其他职位原题:

这将是有益的,如果有人能向我解释如何gcc的决定,包括库函数时断言被称为?我看到assert.h声明了一个外部函数__assert_func。链接器如何知道从库中引用它,而不是仅仅说“对__asert_func的未定义引用”?

配置工具链时,作者默认决定应链接哪些库。

通常这是包括运行时启动/初始化代码和一个名为libc库,其中包括C标准的实现,以及任何其他代码的作者认为相关的(如libc中也可以实现了POSIX,任何定制电路板的特定功能等。 )并且对于嵌入式目标,连接到为目标实现RTOS的库也并不少见。

您可以使用-nodefaultlibs标志gcc在链接阶段省略这些默认库。

在assert()的情况下,它是一个标准C宏/函数,通常在libc中实现。如果assert()失败,assert()可能会打印到stdout,所以使用assert()可以引入实现FILE *处理/缓冲,printf等的所有stdio工具,所有这些工作都是在libc中实现的。

如果您为链接阶段运行gcc -v,您可以默认查看gcc链接到的库。

+0

这几乎是它所做的。在stdio和printf等语言中被拉扯...为了一些天真的原因,我假设链接器需要被告知所有库链接到,包括libc ... –

gcc(或g++)命令只是一个驱动程序。它运行其他程序,包括编译器本身(用于C代码的cc1,用于C++代码的cc1plus)以及汇编器和链接器。

运行的程序由spec file决定(并且有一个隐含的程序,请参阅-dumpspecsdeveloper option)。顺便说一句,运行gcc-v选项显示涉及的实际程序。

assert宏定义(见文件/usr/include/assert.h)做一些检查在<assert.h>只有NDEBUG不是一个定义的预处理器符号。在我的Linux/Glibc系统上,它可以调用C标准库中的__assert_failed内部函数。引用assert(3)文档:

如果宏NDEBUG此刻正在<assert.h>定义的最后 包括,宏观assert()不会产生代码,所以并 什么都没有。

一些项目正在编译与-DNDEBUG他们的代码在生产模式。

您应该阅读文档的Invoking GCC一章。

也许你想​​避免任何额外的库,即使是标准的库?

在你的嵌入式系统上,链接是静态的。静态链接的工作方式如下。

静态库是对象文件的存档。链接器分别考虑每个对象。

生成的可执行文件中包含在静态库中找到的引用函数或变量,以及包含引用符号的整个对象文件。不包含引用符号的对象文件不会被拉入。

这不是特定于gcc的任何方式。自从时间的黎明以来,连接器就以这种方式工作。