gcc如何决定隐式包含哪些库?
参考this question:gcc如何决定隐式包含哪些库?
对于一个小型微型嵌入式项目,我发现我的编译代码大小比预期的大得多。原来,这是因为我包含了使用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链接到的库。
gcc
(或g++
)命令只是一个驱动程序。它运行其他程序,包括编译器本身(用于C代码的cc1
,用于C++代码的cc1plus
)以及汇编器和链接器。
运行的程序由spec file决定(并且有一个隐含的程序,请参阅-dumpspecs
developer 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的任何方式。自从时间的黎明以来,连接器就以这种方式工作。
这几乎是它所做的。在stdio和printf等语言中被拉扯...为了一些天真的原因,我假设链接器需要被告知所有库链接到,包括libc ... –