通常在windows上编写代码后,需要将其在linux上编译之后才可以运行,以gcc 为例。
对于简单的我们一般直接使用:
gcc example.c -o example
其中主要做了如下工作:
对于复杂多个源码文件安装,一般有如下几个步骤:
./configure
make
make install
下面介绍这几个步骤所做的事:
1. configure
这一步主要是检查系统的环境,检查函数库,指定软件的安装位置,这些都可以通过指定的参数设置,叫做配置,其中配置信息保存在configure可执行文件中,通常是通过autoconf工具生成的,configure 脚本考虑了不同系统的差异,并且设定了一些默认的参数,如ac_default_prefix=/usr/local。
我们也可以根据需要自己输入一些参数:
./configure --prefix=/usr/local/python --with-mysql
安装Python时安装在/usr/local/python目录,并且编译时加入mysql模块的支持。
2. 确定标准头文件和依赖库的位置
一般而言,linux默认是/usr 、/usr/lib作为库目录的搜索路径,编译第二步就是找标准库和头文件的目录;,一般配置文件中会列出几个目录,编译的时候编译器按照这个方式查找,对于自己新增的库,可通过环境变量LD_LIBRARY指明库的搜索路劲:
export LD_LIBRARY_PATH=<your-lib-path>:$LD_LIBRARY_PATH
ENV=~/.bash_profile
echo "export LD_LIBRARY_PATH=/opt/MESA/lib/:\$LD_LIBRARY_PATH" >> $ENV
或是在/etc/ld.so.conf中注明
/opt/MESA/lib
3. 确定文件的依赖关系
如果有两个文件A, B,必须先编译完A后才可以编译B,这时就需要在makefile中写明它们的编译顺序,makefile通过configure脚本生成,因此需要先运行configure,生成makefile。
4. 头文件的预编译
多个源码文件可能使用到同一个头文件,编译源码时,头文件也会编译,为节省时间,编译器一般会编译头文件,且只编译一次,但是不会编译头文件的宏定义,如 #define,#if ...
5. 预处理
编译完头文件后,编译器将源码中使用的头文件和宏替换掉,如下:
extern FILE *stdout;
6. 编译
预处理之后,就开始编译生成机器代码,有些编译器,还会生成中间汇编代码,然后在把汇编代码转为机器代码。
将源码转换成汇编代码,转码后的文件称为对象文件(后缀名 obj)
7. 链接
对象文件还不能直接运行,因为用到了头文件中函数,如stdout, fgets()等,需要进一步转换成可执行文件,编译器需要将外部的函数代码(通常在.lib和.a)添加到可执行文件中,称为链接,有静态链接和动态链接。
make 的作用就是从4-7步。
8. 安装
链接一般是在内存中生成可执行文件,然后就是将可执行文件安装到指定的目录,通常是安装在/usr/share/local下,并且设置相关的执行权限等其他操作。
9. 操作系统链接
程序安装成功后,需要通知操作系统该程序可用,比如office装成功后,默认可以打开指定的word文档。
这就是操作系统登记该程序的元数据:文件名,文件描述,关联的后缀名等,windows下还会在启动菜单中,建立快捷方式,linux中,在/usr/sharea/application中建立对用的.desktop文件。
make install 就完成8-9。
10. 生成安装包
通常很少这样发行软件,一般是编译器对程序进行打包,将可执行文件和相关的数据文件,以一定的目录方式打包成压缩文件,如java中的jar包,或是rpm。
11. 动态链接和静态链接
正常情况下,到这一步,程序已经可以运行了。至于运行期间(runtime)发生的事情,与编译器一概无关。但是,开发者可以在编译阶段选择可执行文件连接外部函数库的方式,到底是静态连接(编译时连接),还是动态连接(运行时连接)。所以,最后还要提一下,什么叫做动态连接。
前面已经说过,静态连接就是把外部函数库,拷贝到可执行文件中。这样做的好处是,适用范围比较广,不用担心用户机器缺少某个库文件;缺点是安装包会比较大,而且多个应用程序之间,无法共享库文件。动态连接的做法正好相反,外部函数库不进入安装包,只在运行时动态引用。好处是安装包会比较小,多个应用程序可以共享库文件;缺点是用户必须事先安装好库文件,而且版本和安装位置都必须符合要求,否则就不能正常运行。
现实中,大部分软件采用动态连接,共享库文件。这种动态共享的库文件,Linux平台是后缀名为.so的文件,Windows平台是.dll文件,Mac平台是.dylib文件。