5.链接程序
由汇编程(www.cppentry.com)序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。例如,某个源文件中的函数可能引用了另一个 源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
(1)静态链接 在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
(2) 动态链接 在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的 名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录 的信息找到相应的函数代码。
对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较 短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。 在某些情况下动态链接可能带来一些性能上损害。
Makefile编译
makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接-----但是不是所有的文件都需要重新编译,makefile能够纪录文件的信息,决定在链接的时候需要重新编译哪些文件!在unix系统下,makefile是与make命令配合使用的。
举个例子吧,我现在有main.c 、window.c 、model.c 、data.c 4个。c文件和window.h 、model.h 、data.h 3个。h文件。main.c是主程序,里面有main()函数。其他的都是模块。
如果要生成最终的可执行文件,要做以下步骤:
1、分别编译window.c 、model.c 、data.c 、main.c ,将会得到4个目标文件:window.o 、model.o 、data.o 、main.o
2、把这4个。o (在windows下就是。obj)文件链接起来,得到main.out(在windows下就是main.exe)。
那么这些文件就要有逻辑关系,否则编译器不知道怎么编译。
all:main.out
main.out:main.o window.o model.o data.o
gcc -o main.out main.o window.o model.o data.o
#上面的意思是说:
#all:main.out
如果想要编译所有:make all,那么将会生成main.out可执行文件。
#main.out:main.o window.o model.o data.o而要生成这个main.out,需要依赖main.o,window.o,model.o,data.o 4个文件。
# gcc -o main.out main.o window.o model.o data.o
这句是调用编译器编译,vc用的是cl.编译的时候可以加上很多的参数、定义的宏、链接库路径等。
当然,还没有完呢,这些main.out依赖的这些 .o 怎么来的?
window.o:window.c window.h
gcc -c window.c
model.o:model.c model.h
gcc -c model.c
data.o:data.c data.h
gcc -c data.c
上面的-c参数是指定编译器编译出一个。o文件就可以了,不要再寻找main()函数做链接工作。这些和到一起,就是一个makefile,当然这些功能还太少,可以加上很多别的项目。但宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。现在的VC++(www.cppentry.com)真是太好了,不用一个字一个字的去敲Makefile 了。