编译生成lib会进行连接吗
‘壹’ 关于整个编译过程和库文件的问题
问题1:
BD
D:通过目标文件归档程序(VC++中是lib.exe)和其它方式(例如由dll文件生成lib文件)得到的产物 。
问题2:
AB
问题3:
不一定。首先,一个完整的程序的全编译过程可以仅依赖于现有的库文件,且不在这个程序的编译过程生成库文件。其次,库文件的格式不一定是lib和dll文件。至于手动生成lib和dll,这个和使用的工具相关。例如VC++的命令行可以用编译程序cl.exe编译源文件为目标文件,用归档程序lib.exe连接obj和lib文件生成静态库,用链接程序link.exe链接目标文件和资源文件生成exe和dll。
====
[原创回答团]
‘贰’ C语言编译怎样连接lib文件,请讲解连接的原理,
广义的代码编译过程,实际上应该细分为:预处理,编译,汇编,链接。
预处理过程,负责头文件展开,宏替换,条件编译的选择,删除注释等工作。gcc –E表示进行预处理。
编译过程,负载将预处理生成的文件,经过词法分析,语法分析,语义分析及优化后生成汇编文件。gcc –S表示进行编译。
汇编,是将汇编代码转换为机器可执行指令的过程。通过使用gcc –C或者as命令完成。
链接,负载根据目标文件及所需的库文件产生最终的可执行文件。链接主要解决了模块间的相互引用的问题,分为地址和空间分配,符号解析和重定位几个步骤。实
际上在编译阶段生成目标文件时,会暂时搁置那些外部引用,而这些外部引用就是在链接时进行确定的。链接器在链接时,会根据符号名称去相应模块中寻找对应符
号。待符号确定之后,链接器会重写之前那些未确定的符号的地址,这个过程就是重定位。
‘叁’ 被包含文件是在编译时先单独生成目标文件,然后连接到可执行文件中去. 对吗
不知道你是说那种语言,如果是C/C++的话,一般我们使用#include指令包含头文件(当然,头文件也是可以有实现),编译器首先通过预编译,将所有使用#include的地方全部使用包含的文件替换,然后在执行编译,所以被包含不会生成单独的目标文件
生成单独的目标文件一般是头文件的实现文件,头文件的实现就是先编译成单独的目标文件,然后通过链接器连接到一起,成为一个完整的可执行文件
‘肆’ 用C语言编的程序,要生成可执行文件的时候,要编译、链接,编译是什么意思啊链接是什么意思编译和链接
编译就是把C代码转换成CPU可执行的机器指令,每个.c文件生成一个.obj文件。
链接就是把生成的(多个) .obj 文件及用到的库文件(.lib)一起组合生成可执行文件(.exe)。
‘伍’ lib文件静态库和dll文件动态连接库有什么不同,分别有什么作用!在编译时各自起什么作用
个人理解(不一定完全对):
静态库之所以叫做“静态”,其含义是:一旦内容发生改变,必须进行重新编译
而动态连接库则不必这样,我们编译好一个程序,如果他使用的动态连接库有所改变,我们只需要更新对应的DLL文件即可,而不必重新编译整个程序
在编译时,静态库整个函数库的所有数据都会被整合进目标代码中,而动态库则不会,动态库只是在使用时才会进行加载
‘陆’ lib文件是什么是不是编译自动生成我不加lib文件运行不了
lib文件是静态库,这种文件中有头文件中声明的函数的实现代码,一般用在静态连编上,编译链接时,将lib文件与其他模块编译生成的目标代码链接,从而形成能够运行的可执行文件。
#pragma comment(lib, "pcc32_vc6.lib")就是连入一个库文件,表示链接pcc32_vc6.lib这个静态库文件来生成可执行文件。
‘柒’ 怎么用Keil将C程序封装成lib库
在团队工作中,经常会有模块维护和代码封装的问题。把需要封装的代码打成一个lib无疑是一种很好的方式。
1.创建lib
创建一个lib很容易,只需要创建一个target,然后把需要封装的代码全部加进来,然后再Options of Target中选择Create Library,然后编译,因为是lib所以不需要链接,编译过了,你的lib就创建了。当然了,为了别人可以轻松的使用,请提供头文件支持哦。
2.使用lib
使用lib就更容易了,把lib和头文件加入你的工程,直接调用就是了。lib库会和你工程中其它编译后的obj一起链接,形成最后的目标文件。
3.注意事项
首先,Startup和中断处理程序不要封入LIB,这些程序会在链接的时候产生问题。具体的原因么,有点复杂,应该是中断程序的link机制有所不同的关系吧。
其次,Lib的文件要分的细一点,没有调用关系的两个函数不要放到同一个C文件中,因为LIB51在链接的时候是按模块来链接的,一个模块就对应一个C文件,假如链接器因为要使用你一个函数fA而引入了A模块,那么A模块中的另外的函数也会被引入,而另外的函数你又没有使用的话,那么就会引发Keil经典的UNCALLED FUNC的warning。这个warning在Keil的文档中说的好清楚了,我粘过来吧:
It is common practice ring the development process to write but not call
additional functions. While the compiler permits this without error, the
Linker/Locator does not treat this code casually because of the support for data
overlaying, and emits a warning message.
Interrupt functions are never called, they are invoked by the hardware. An
uncalled routine is treated as a potential interrupt routine by the linker. This
means that the function is assigned non-overlayable data space for its local
variables. This quickly exhausts all available data memory (depending upon the
memory model used).
If you unexpectedly run out of memory, be sure to check for linker warnings
relating to uncalled or unused routines. You can use the linker’s IXREF
directive to include a cross reference list in the linker map (.M51) file.
大意就是说,Keil的内存应用模式是指定地址的,也就是要根据调用关系来决定哪块地址可以被复用。对于这种没人调用的函数,Keil会认为是中断处理程序,并不能决定调用关系,所以此类uncalled函数的空间不能和其他的程序共享,也就是说,这函数用多少RAM,你就少多少RAM。那uncall多了会怎么样?----废话,当然是内存溢出了。
所以,lib的功能可以做的大而全,但是里面的模块一定要分的要多细,有多细,只有这样,你才能像在windows上用CRT一样舒服的使用LIB。
个人总结
1. 生成lib 的工程可以没有main函数,可以只有一个.c文件,一个.c文件中可以只有一个函数
2. 需要在lib工程中建立一个.h文件, 必须用extern声明各全局变量和函数.
3. 调用lib文件的工程中必须包括lib中的.h文件, 也就是lib工程和调用工程都包含同一个.h文件(好像有点废话)
4.Lib的文件要分的细一点,没有调用关系的两个函数不要放到同一个C文件中. 没有调用关系的最好是一个函数单独放在一个.c文件中.这是为了避免在keil中应用程序调用lib库里出现告警. 因为LIB51在链接的时候是按模块来链接的,一个模块就对应一个C文件,假如链接器因为要使用你一个函数fA而引入了A模块,那么A模块中的另外的函数也会被引入,而另外的函数你又没有使用的话,那么就会引发Keil经典的UNCALLED FUNC的warning。
通常为每一个函数编一个.C文件,而整个lib用一个.h文件,这样就可以使只有被调用的函数参与连接
5.调用lib库时需要在工程中将.lib文件加进来. 在Group中右键,然后Add ,注意文件类型中选择*.lib.
‘捌’ c++ 编译 链接是怎么回事
compile和link是大多数语言从原代码生成可执行程序的两个步骤。
之所有有这两个步骤因为几乎任何一个程序都不是用一个原文件写出来的。compile是先针对单独原文件进行处理。link是把compile处理的结果组合成一个完整的可执行文件。
其实C/C++完全也可以一步成型,不需要compile和link两个步骤,但是那样的后果就是:一,每次生成可执行程序,必须翻译全部源代码;二,C语言的执行库(printf, scanf这些)必须都以源代码形式存在。这怎么样也说不过去吧。
另外头文件不属于compile和link过程,头文件是预编译过程的文件。
C/C++语言的完整编译过程是
一、预编译
处理#define #if #include这类#开头的语句,这些称为预编译指令。这个过程中会把.h文件和.c/.cpp文件组合成最终交给compile过程的原文件。这个原文件是不包含任何#开头的语句的。所有#define定义的宏也会被替换。
二、编译
把上面那个原文件编译成.o或者VC里是.obj文件。这个文件保存了机器码化的函数、函数的描述、全局变量的描述、乃至段的描述等等。
三、连接
把可执行程序需要的所有的编译过程产生的.o或者.obj文件组合到一起。(这里也包括.lib文件,.lib文件件本质上就是打包的.obj文件集合)。另外连接过程还会组合一些其他数据,比如资源、可执行文件头等等。