0.目录
1.gcc编译源码及常用选项
1.1 直接编译
写一个C程序,内容hello world:
[root@local1 hello]# vim hello.c
# include <stdio.h>
int main()
{
printf("hello world.\n");
}
使用gcc指令直接编译,生成对应的名为a.out的二进制文件:
[root@local1 hello]# gcc hello.c
[root@local1 hello]# ls
a.out hello.c
执行a.out:
[root@local1 hello]# ./a.out
hello world.
1.2 编译为目标文件再连结成二进制文件
1.2.1 编译单个文件
仍以上例,使用-c选项先生成目标文件(目标文件以.o结尾):
[root@local1 hello]# gcc -c hello.c
[root@local1 hello]# ls
a.out hello.c hello.o
使用选项-o,以目标文件生成二进制文件hello(文件名可自定义):
[root@local1 hello]# gcc -o hello hello.o
[root@local1 hello]# ls
a.out hello hello.c hello.o
执行hello:
[root@local1 hello]# ./hello
hello world.
1.2.2 编译多个文件
对于单个文件,先编译为目标文件再生成对应的二进制文件,显得有些“多余”。但程序代码往往要写于多个文件,这样就无法使用指令直接编译了,要先生成目标文件而后连结。
写一个程序,主函数调用子函数,子函数写在不同文件中:
[root@local1 meet]# vim meet1.c
# include <stdio.h>
int main()
{
printf("Nice to meet you.\n");
meet2();
}
[root@local1 meet]# vim meet2.c
# include <stdio.h>
void meet2()
{
printf("Glad to meet you.\n");
}
把这两文件编译为目标文件后,连结生成二进制文件meet并执行:
[root@local1 meet]# gcc -c meet1.c meet2.c
[root@local1 meet]# gcc -o meet meet1.o meet2.o
[root@local1 meet]# ls
meet meet1.c meet1.o meet2.c meet2.o
[root@local1 meet]# ./meet
Nice to meet you.
Glad to meet you.
把程序写在多个文件中,可使程序更易读易排错。且更改程序某部分后重新编译时,只需编译更改过的文件即可,节省时间等成本。
2.make
2.1 为何使用make
如果程序写在更多文件中(这些文件往往相互依赖,甚至对编译各文件的次序也有要求),那么使用上述指令逐一编译各文件会非常繁琐。工具make会根据发行软件者制作的makefile,进行一次性的编译(生成对应目标文件、连结等操作)。
2.2 makefile
2.2.1 makefile基本语法
makefile基本语法:
target:目标文件1 目标文件2......
<tab>gcc -o 欲建立的二进制文件 目标文件1 目标文件2......
以上述meet程序为例,makefile就写为:
main:meet1.o meet2.o
gcc -o meet meet1.o meet2.o
make可根据这个makefile,生成meet1.c和meet2.c对应的目标文件和二进制文件。查看执行结果如下:
[root@local1 meet]# ls
makefile meet1.c meet2.c
[root@local1 meet]# make
cc -c -o meet1.o meet1.c
cc -c -o meet2.o meet2.c
gcc -o meet meet1.o meet2.o
[root@local1 meet]# ls
makefile meet meet1.c meet1.o meet2.c meet2.o # make根据编写的makefile,生成了目标文件meet1.o、meet2.o和可执行文件meet
[root@local1 meet]# ./meet
Nice to meet you.
Glad to meet you.
2.2.2 编写不同target以执行不同指令
比如在上述makefile中加入clean这个target,动作就是清除当前目录下所有的目标文件(.o文件):
main:meet1.o meet2.o
gcc -o meet meet1.o meet2.o
clean:
rm -f *.o
之后只需改变make的参数即可令其执行不同的指令:
[root@local1 meet]# ls
makefile meet meet1.c meet1.o meet2.c meet2.o
[root@local1 meet]# make clean # 执行clean对应的指令
rm -f *.o
[root@local1 meet]# ls
makefile meet meet1.c meet2.c
[root@local1 meet]# make # 注意编译的指令可省略target,直接写make
cc -c -o meet1.o meet1.c
cc -c -o meet2.o meet2.c
gcc -o meet meet1.o meet2.o
[root@local1 meet]# ls
makefile meet meet1.c meet1.o meet2.c meet2.o
注意,源码的makefile一般都包含了clean这个target,且执行动作就是清除当前目录下的目标文件。因为如果当前目录下已经有对应源码文件的目标文件,则该文件不会再次被编译(即使源码已经修改了)。为避免这种情况,在使用make编译前应先执行make clean清除已经存在的目标文件1。
2.2.3 makefile中也可使用变量
对于makefile中出现较多的字符串等可使用变量引用之;target下的指令可使用“$@”引用target。
如上述的meet程序的makefile可简写为:
OBJS=meet1.o meet2.o
main:${OBJS}
gcc -o $@ ${OBJS} # $@表示当前的target,即main
clean:
rm -f *.o
2.2.4 侦测程序configure(或config)
源码编译很可能在不同的硬件、操作系统环境,这样makefile不一定是相同。所以一般源码包中都附带侦测程序configure(或config),作用就是侦测当前环境以生成makefile。工具make就根据生成的makefile进行编译。
至于怎么制作configure程序本篇不述。
3.源码编译安装
3.1 源码编译安装步骤
源码编译安装程序大致可分为如下步骤:
1、下载源码包,解压至/usr/local/src目录下;
2、阅读源码包所带的README或INSTALL文档,一般可根据提示执行./configure或./config,以生成makefile;
3、执行make clean,以删除已存在的目标文件,否则对应的源码文件不会被编译(即使源码文件已修改);
使用make、make install命令编译、安装,一般安装在目录/usr/local/对应软件下(即一个软件对应一个目录)2;
4、这样源码编译安装的软件二进制程序的路径肯定不在PATH环境变量中,执行时需使用绝对路径,如有必要可把其路径添加至PATH中;
5、对于man文档也同样,可把该软件的帮助文档路径添加至/etc/man.config中。
3.2 以httpd2.2为例
按上述源码编译安装步骤安装apache:
下载源码
从官网或镜像站点下载源码,放置在/usr/local/src目录下:
[root@local1 ~]# ls /usr/local/src/ httpd-2.2.32.tar.bz2
查看源码包中的INSTALL文档,可看到文档前几行已说明如何执行编译安装指令:
Quick Start - Unix <hr /> For complete installation documentation, see [ht]docs/manual/install.html or http://httpd.apache.org/docs/2.2/install.html $ ./configure --prefix=PREFIX $ make $ make install $ PREFIX/bin/apachectl start NOTES: * Replace PREFIX with the filesystem path under which Apache should be installed. A typical installation might use "/usr/local/apache2" for PREFIX (without the quotes). 。。。。。。
根据文档,执行./configure命令,并使用–prefix选项指定安装路径(上述说明文档中有提示3):
[root@local1 httpd-2.2.32]# ./configure --prefix=/usr/local/apache
生成makefile后,使用make,删除已存在的目标文件(make clean,习惯上操作下),然后编译、安装。
把命令、man文档等添加至环境变量和配置文件:
编译安装完毕后,可看到指定路径下,该软件包含的个目录:[root@local1 httpd-2.2.32]# ls /usr/local/apache/ bin build cgi-bin conf error htdocs icons include lib logs man manual modules
把它的二进制程序添加至环境变量PATH4:
[root@local1 httpd-2.2.32]# PATH=$PATH:/usr/local/apache/bin [root@local1 ~]# httpd -v # 添加后才可使用命令httpd,否则要使用绝对路径 Server version: Apache/2.2.32 (Unix) Server built: Jun 29 2017 18:34:47
man路径添加至/etc/man.config:
。。。 MANPATH /usr/man MANPATH /usr/share/man MANPATH /usr/local/man MANPATH /usr/local/share/man MANPATH /usr/X11R6/man MANPATH /usr/local/apache/man 。。。
注:
1、导出完PATH后有时还要导出库文件(以便其他程序使用该软件所提供的库)。在/etc/ld.so.conf.d/下创建一个以这个软件命名的文件,其中的内容就是这个软件库文件的路径即可。而且要让系统重新生成缓存,使用命令ldconfig。
2、也可能需要导出头文件。把该软件的include目录复制到/usr/include就可以,不过更简单的是创建链接。这个在/usr/include目录下创建符号链接即可。链接可以是头文件目录的链接也可以是目录下每个头文件的链接,反正链到/usr/include即可。
如果仅是使用源码编译安装的软件(而非使用它的库文件开发等),则上述两步不一定用到。
(完)
- 如果只是某个文件修改了,则单独删除这个文件对应的目标文件(如果有的话)再重新编译即可。这样make会只编译更改过的文件。 ↩
- 如果直接安装在目录/usr/local下而不是一个软件单独一个目录,那么该软件的执行文件、配置文件等就会放置在/usr/local/bin、/usr/local/etc等目录下。
如果安装多个软件后,他们的执行文件、配置文件等就会放置在同样目录下,这样对于后期的升级、移除等操作会带来很大麻烦;而如果一个软件安装在一个对应目录下,移除时只需删除该目录即可。 ↩ - 不同软件源码的./configure命令往往都有多个选项,根据文档提示使用。 ↩
- 如需永久有效,则把命令添加至配置文件即可。一般写在/etc/profile.d目录下以对应软件为名的.sh文件中,比如Apache的就叫apache.sh ↩