谁能解释编译是如何工作的?
我似乎无法弄清楚编译是如何工作的..
更具体地说,这是一个例子..我正在尝试在MSVC++ 6中编写一些代码来加载Lua状态.
我已经:
设置库的其他目录并将文件包含到正确的目录中
使用extern"C"(因为Lua只是C,所以我听说)
包括正确的头文件
但是我仍然在MSVC++ 6中遇到一些关于未解析的外部符号的错误(对于我使用的Lua函数).
尽管我想知道如何解决这个问题并继续前进,但我认为如果我了解所涉及的基础过程对我来说会好得多,所以有人可能会为此写一个很好的解释吗?我想知道的是这个过程..它看起来像这样:
步骤1:
输入:源代码
过程:解析(可能在这里添加更多细节)
输出:这里输出的是什么..
第2步:
输入:无论从步骤1输出什么,加上可能还需要其他任何东西(库?DLL?.so?.lib?)
过程:无论输入做什么
输出:无论输出是什么
等等..
谢谢..
也许这将解释什么是符号,究竟什么是"链接",什么是"对象"代码或者其他什么.
谢谢..抱歉这样的菜鸟..
PS这不一定是语言特定的..但随意用你最舒服的语言表达它.. :)
编辑:所以无论如何,我能够解决错误,事实证明我必须手动将.lib文件添加到项目中; 只需在IDE设置或项目设置中指定库目录(.lib所在的位置)不起作用..
但是,下面的答案在一定程度上帮助我更好地理解了这个过程.非常感谢!如果有人还想写一篇详尽的指南,请做.. :)
编辑:仅供参考,我发现一篇作者(Mike Diehl)的两篇文章很好地解释了这一点.:) 检查编译过程:第1部分 检查编译过程:第2部分
从源代码到可执行文件通常是C和相关语言的两个阶段过程,尽管IDE可能将此作为单个过程呈现.
1 /您编写源代码并通过编译器运行它.此阶段的编译器需要您的源以及您要链接的其他内容的头文件(请参阅下文).
编译包括将源文件转换为目标文件.目标文件包含已编译的代码和足够的信息,以了解他们需要的其他内容,但不知道在哪里找到其他内容(例如,LUA库).
2 /下一阶段的链接是将所有目标文件与库相结合以创建可执行文件.我不会在这里讨论动态链接,因为这会使解释变得复杂而没什么好处.
您不仅需要指定链接器可以找到其他代码的目录,还需要指定包含该代码的实际库.你得到未解决的外部事实表明你没有这样做.
作为示例,请考虑以下简化的C代码(xx.c
)和命令.
#includeint x = bob_fn(7); cc -c -o xx.obj xx.c
这会将xx.c
文件编译为xx.obj
.在bob.h
包含了原型bob_fn()
,这样编译会成功.的-c
指示编译器生成目标文件,而不是可执行文件和-o xx.obj
将输出文件名.
但实际的代码为bob_fn()
不在头文件,但在/bob/libs/libbob.so
,所以链接,你需要的东西,如:
cc -o xx.exe xx.obj -L/bob/libs;/usr/lib -lbob
这xx.exe
是xx.obj
使用表单libbob.so
(在给定路径中搜索)创建的(lib和.so通常由链接器添加).在此示例中,-L
设置库的搜索路径.-l
如有必要,指定要包含在可执行文件中的库.链接器通常采用"bob"并在指定的搜索路径中查找第一个相关的库文件-L
.
库文件实际上是目标文件的集合(类似于zip文件如何包含多个其他文件,但不一定是压缩的) - 当找到未定义外部的第一个相关事件时,从库中复制目标文件并添加像你的xx.obj
文件一样可执行文件.这通常会持续到没有更多未解决的外部因素.该"相关的"图书馆是"鲍勃"文本的修改,它可能会寻找libbob.a
,libbob.dll
,libbob.so
,bob.a
,bob.dll
,bob.so
等.相关性由链接器本身决定,应记录在案.
它的工作原理取决于链接器,但基本上就是这样.
1 /所有目标文件都包含需要解析的未解析外部列表.链接器将所有这些对象放在一起并修复它们之间的链接(解析尽可能多的外部).
2 /然后,对于每个仍未解析的外部,链接器将梳理库文件,以查找可满足链接的目标文件.如果它找到它,它会将其拉入 - 这可能会导致进一步未解析的外部因素,因为拉入的对象可能有自己的需要满足的外部列表.
3 /重复步骤2,直到没有更多未解析的外部或无法从库列表中解析它们(这是您的开发所在的位置,因为您没有包含LUA库文件).
我之前提到的复杂性是动态链接.这是您与例程的存根(一种标记)而不是实际例程的链接,后者在加载时(运行可执行文件时)解析.诸如Windows公共控件之类的东西都在这些DLL中,因此它们可以在不必将对象重新链接到新的可执行文件的情况下进行更改.
第1步 - 编译器:
输入:源代码文件[s]
过程:解析源代码并转换为机器代码
输出:目标文件[s],由[s]组成:
此对象中定义的符号名称以及此对象文件"导出"的名称
与此对象文件中定义的每个符号关联的机器代码
未在此目标文件中定义但此目标文件中的软件所依赖的符号名称以及随后必须链接的符号名称,即此目标文件"导入"的名称
第2步 - 链接:
输入:
步骤1中的目标文件[s]
其他对象的库(例如来自O/S和其他软件)
处理:
对于要链接的每个对象
获取此对象导入的符号列表
在其他库中查找这些符号
将相应的库链接到目标文件
输出:单个可执行文件,包括来自所有对象的机器代码,以及导入(链接)到对象的库中的对象.