我无法区分构建和编译。他们一样吗?链接究竟是如何工作的?.so 文件和 .o 文件到底包含什么以及我应该如何使用它们?这些我每天都会看到的所有文件,但我不知道它们到底包含什么。任何人都可以建议一些教程来清楚地说明这些过程吗?
Mat*_*Mat 12
术语“构建”通常用于表示从一组源代码文件和其他资源开始,到一组可执行文件、共享库(可能还有其他资源)结束的整个过程。
这可能涉及很多步骤,例如特殊的预处理器(moc
例如 Qt 代码)、代码生成器(flex
/yacc
或bison
例如)、编译、链接以及可能的后处理步骤(例如构建tar.gz
或rpm
分发文件)。
对于 C 和 C++(以及相关语言),编译是将源文件(例如.c
C 代码文件)转换为目标文件 ( .o
) 的过程。这些目标文件包含编译器为相应的源代码生成的机器代码,但不是最终产品——特别是,外部函数(和数据)引用没有被解析。从这个意义上说,它们是“不完整的”。
目标文件有时被组合成档案(.a
文件),也称为静态库。这几乎只是将它们组合在一起的一种便捷方式。
链接需要(通常是几个)目标文件(.o
或.a
)和共享库,组合目标文件,解析(主要)目标文件本身和共享库之间的引用,并生成您可以实际使用的可执行文件,或共享库(.so
)可以被其他程序或共享库使用。
共享库是其他可执行文件可以直接使用的代码/函数的存储库。针对共享库的动态链接与(静态)直接链接对象或存档文件之间的主要区别在于,无需重新构建使用它们的可执行文件即可更新共享库(尽管对此有很多限制)。
例如,如果在某个时候在 OpenSSL 共享库中发现错误,则可以在该代码中进行修复,并且可以生成和交付更新的共享库。动态链接到该共享库的程序不需要重新构建以获得错误修复。更新共享库会自动修复其所有用户。
如果他们改为与目标文件链接(或通常静态链接),他们将不得不重建(或至少重新链接)以获得修复。
一个实际的例子:假设你想用 C 编写一个程序 - 一个花哨的命令行计算器 - 具有命令行历史/编辑支持。您将编写计算器代码,但您将使用readline
库进行输入处理。
您可以将代码分成两部分:数学函数(将这些函数放在 中mathfuncs.c
)和处理输入/输出的“主要”计算器代码(例如在 中main.c
)。
您的构建将包括:
Compile mathfuncs.c ( gcc -o mathfuncs.o -c mathfuncs.c
,-c
代表“仅编译”)
mathfuncs.o
现在包含您编译的数学函数,但不是“可执行的”——它只是函数代码的存储库。
编译你的前端 ( gcc -o main.o -c main.c
)
main.o
同样只是一堆函数,不可运行
链接您的计算器可执行文件,链接readline
:
gcc -o supercalc main.o mathfuncs.o -lreadline
# ^ executable ^ dynamic link with libreadline.so
# ^ ^ two .o files statically linked in
Run Code Online (Sandbox Code Playgroud)
现在您有了一个可以运行的真正可执行文件 ( supercalc
),这取决于readline
库。
构建一个rpm
包含所有可执行文件和共享库(和头文件)的包。(这些.o
文件是临时构建产品而不是最终产品,通常不会发货。)
有了这个,如果在 中发现错误readline
,您将不必重建(和重新发送)您的可执行文件来获得修复 - 更新libreadline.so
就是所需的全部。但是,如果您在 中发现错误mathfuncs.c
,则需要重新编译并重新链接supercalc
(并发布新版本)。
归档时间: |
|
查看次数: |
874 次 |
最近记录: |