Linux操作系统认识的语言是二进制文件。具体的从编程到执行的过程是:首先利用高级语言(例如c语言)在文本编辑器(例如vim)写好源程序,再利用编译器(例如gcc)进行编译,再链接到已存在的函数库,最终产生可以执行的可执行文件。如图:
下面对c语言代码编译来逐步了解如何利用gcc编译程序
1.单个程序
#include<stdio.h> int main() { printf("Hello World!"); return 0; }
看看编译过程:
可以指定可执行文件的名称。有两个参数重要的参数 -c——生成目标文件(.o文件) -o——生成可执行文件。看下面执行过程
2.多个程序
//main.c文件 #include<stdio.h> int main() { int x, y; printf("Input the x:"); scanf("%d", &x); //输入x printf("Input the y:"); scanf("%d", &y); //输入y printf("%d\n", sum1(x, y)); return 0; } //sum1.c文件 int sum1(int a, int b) { return a + b; }
问题来了:既然可以直接生成可执行文件,那为嘛要生成那中间的目标文件(.o)?
原因是这样的:当源码文件有很多时,编译大量的源码文件需要大量的时间,但是如果生成目标文件的话,就可以在编译的时候只编译改变的目标文件。
3.调用函数库
#include<stdio.h>
#include<math.h> int main() { int x, y; printf("Input the x:"); scanf("%d", &x); printf("%.3f\n", sqrt(x)); //调用函数库函数sqrt()函数开方 return 0; }
看到程序出现错误,说没有定义sqrt。此时头文件#include<math.h>是无济于事的。因为查看/usr/include/目录下的math.h没有对sqrt()的定义。C语言的数学函数大部分写在libm.so函数库中,此函数库主要放在/lib、/usr/bin.所以要在编译时的链接过程
声明:-L/lib、-L/usr/lib
4.makefile文件
现在问题又来了:为了以后修改不至于大幅度的编译源文件,生成了目标文件,但是有大量的目标文件,那不有大量的gcc -c .......很麻烦,为了比比按这种重复的工作,就要用的了makefile(Makefile)文件。还是利用2中的例子。编写makefile如下
main: main.o sum1.o gcc -o main main.o sum1.o clean: rm main.o sum1.o main
编译过程:
编写makefile规则:
执行文件名: 1.o 2.o ... <tab> gcc -o 执行文件名 1.o 2.o ...
注意:第二行开头一<tab>键开头,颜色是高亮的。
5.优化makefile文件
在书写makefile时可以看到有很多重复的内容,这样就可以把重复的内容用一个变量代替。例如上边的makefiel可以改写如下:
OBJS = main.o sum1.o main: ${OBJS} gcc -o main ${OBJS} clean: rm ${OBJS}
注意:
- 变量常用大写表示
- 此时变量赋值可以有空格(不像shell)
- 下边调用变量的时候用格式${OBJS}
- 数学函数不要在gcc 最后竹山 -lm
$@可以表示当前的可执行文件名称,那么上边的makefile改写如下:
OBJS = main.o sum1.o main: ${OBJS} gcc -o $@ ${OBJS} clean: rm ${OBJS}
本文转自jihite博客园博客,原文链接:http://www.cnblogs.com/kaituorensheng/archive/2013/03/27/2983888.html,如需转载请自行联系原作者