使用gcc和libs/头进行编译的正确方法是什么?

使用gcc和libs/头进行编译的正确方法是什么?,gcc,compilation,linker,Gcc,Compilation,Linker,我的第一个示例不起作用,但我的第二个示例起作用。因此,我想问,链接时,什么是正确的编译方式?有关于正确链接的更多信息吗 非工作:gcc$(curl-config--libs--cflags)prog.c-o prog 工作:gcc prog.c$(curl config--libs--cflags)-o prog这是gcc语法。我希望您理解为什么第一个不起作用,第二个是: GCC语法 $gcc[options][source files][object files][o输出文件] 这是gcc语法

我的第一个示例不起作用,但我的第二个示例起作用。因此,我想问,链接时,什么是正确的编译方式?有关于正确链接的更多信息吗

非工作:
gcc$(curl-config--libs--cflags)prog.c-o prog


工作:
gcc prog.c$(curl config--libs--cflags)-o prog

这是gcc语法。我希望您理解为什么第一个不起作用,第二个是:

GCC语法

$gcc[options][source files][object files][o输出文件]


这是gcc语法。我希望您理解为什么第一个不起作用,第二个是:

GCC语法

$gcc[options][source files][object files][o输出文件]


C编译器——不管它是GCC还是其他编译器——都是一个复杂的生物。它实际上调用不同的流程来完成工作的不同部分。还有解析器,它可能(现在通常是这样)包括预处理器部分,然后是代码生成,通常是到汇编程序,然后是由汇编程序生成对象,最后是程序链接(通常是由一个名为
ld
的程序,用于加载程序)。具体组织可以不同;这里的关键点是,加载程序对由早期阶段创建的对象文件以及它被告知要使用的库进行操作

在编写链接可执行文件的调用时,可能也可能不将代码编译为对象文件。在您的示例中,您确实将
prog.c
编译为
prog.o
;通常,“链接”命令仅列出对象文件,而不列出任何源文件

使用C编译器添加的选项(可能还有对象文件)调用链接器,然后是对象文件和库,并按照您在命令行上列出的顺序链接相关选项,以及它自己添加的任何库

有两种类型的链接-静态和动态。通过静态链接,可执行文件包含运行时将使用的所有目标代码,但运行时动态加载的任何代码除外。链接器在遇到对象文件和库时处理它们。通常,第一个对象文件被称为
crt0.o
,由编译器提供;它包含对
main()
的引用。链接器通过记录它定义的符号和它引用的未定义的符号来处理对象文件

对于静态链接,它会在遇到库时扫描库;如果库提供了当前未定义的符号,它将从库中提取相关代码,并根据需要重新扫描以查找已引用但尚未定义的其他符号。如果唯一未定义的符号是
main()
,并且库不包含
main()
(这是正常的),则库将被有效跳过

对于动态链接(使用共享对象或动态链接库,也称为DLL),过去的情况是(在某些机器上),如果在链接行中提到库,则所有符号都会自动按定义处理,无论是否使用。最近,如果某个库在链接过程中扫描时不包含任何相关符号,编译器将忽略该库

您的工作示例在对象文件之后显示了正确的链接顺序-库。当然,在您的示例命令行中,您列出了一个源文件,但编译器将该命令转换为引用它刚从源文件创建的目标文件,并在命令行中按顺序列出库和其他链接器标志。如果您有一个旧式链接器,它记录了共享对象的使用情况,而不管它是否满足任何未定义的引用,“非工作”行也会链接OK。然而,它从来都不可靠;如果其中任何一个库是静态库,您通常会遇到问题

因此,规则很简单:

  • 链接程序时,在库之前列出对象文件

它总是工作的-旧的和新的链接器,静态和动态库。在某些平台上,用任何其他方法都可能失败。

C编译器——不管是GCC还是其他编译器——是一个复杂的生物。它实际上调用不同的流程来完成工作的不同部分。还有解析器,它可能(现在通常是这样)包括预处理器部分,然后是代码生成,通常是到汇编程序,然后是由汇编程序生成对象,最后是程序链接(通常是由一个名为
ld
的程序,用于加载程序)。具体组织可以不同;这里的关键点是,加载程序对由早期阶段创建的对象文件以及它被告知要使用的库进行操作

在编写链接可执行文件的调用时,可能也可能不将代码编译为对象文件。在您的示例中,您确实将
prog.c
编译为
prog.o
;通常,“链接”命令仅列出对象文件,而不列出任何源文件

使用C编译器添加的选项(可能还有对象文件)调用链接器,然后是对象文件和库,并按照您在命令行上列出的顺序链接相关选项,以及它自己添加的任何库

有两种类型的链接-静态和动态。通过静态链接,可执行文件包含运行时将使用的所有目标代码,但运行时动态加载的任何代码除外。链接器在遇到对象文件和库时处理它们。通常,第一个对象文件被称为
crt0.o
,由编译器提供;它包含对
main()
的引用。链接器通过记录它定义的符号和符号来处理对象文件