linux c编程:make编译一

mac2022-06-30  56

一个工程中的源文件不计其数,按照不同的功能分类在若干的目录里面,makefile定义了一系列的规则,来制定那些文件需要先编译,那些文件后编译,那些文件重新编译。makefile最大的好处就是自动化编译。一旦写好,只需要一个make命令,整个过程都自动编译。极大提高开发的效率。我们先来看个简单的例子:如果一个工程里面有1个头文件calc.h和2个C文件main.c,calc.cmain.c的内容如下:#include "stdio.h"#include "calc.h"int main(){    int n,k;    int c;    n=3;    k=4;    c=calculate(n,k);    printf("the value is %d\n",c);}calc.c的内容如下:#include "calc.h"int calculate(int n,int k){    return n*k;}calc.h的内容如下:#ifdef CALC_H#define CALC_Hint calculate(int n,int k);#endif为了完成对工程文件案的编译,并生成执行文件main,按照如下的方式编译文件root@zhf-linux:/home/zhf/zhf/c_prj/make_function# gcc main.c calc.c -o main但是如果我对main.c做了修改。就需要把所有源文件都重新编译一遍,即使其他文件没有任何变化。也要跟着重新编译。一个大的软件项目上千个源文件组成,编译一次耗时很长。一个源文件修改导致全部重新编译肯定不合理。我们可以这样优化下:gcc -c main.cgcc -c calc.cgcc main.o calc.o -o main如果编译之后有对main.c做了修改,重新编译之需要两步:gcc -c main.cgcc main.o calc.o -o main这样比之前的要省事一些了,但还是有问题,在calc.c和main.c都包含了calc.h。如果我对calc.h做了改动。所有包含calc.h的文件都得改动。而且还得到处去找那些包含了calc.h。还是很麻烦。比如在calc.h中增加了一个宏定义。并且在man.c和calc.c中都有用到这个变量。那么一旦calc.h修改了宏定义变量的值。calc.c和main.c都必须重新编译。#define max_value 40那么我们需要一种什么样的编译方式才能最省事呢:1 如果这个工程没有被编译过,那么我们的所有C文件都要编译并被链接2 如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并连接目标程序3 如果这个工程的头文件被修改了,那么我们需要编译引用了这几个头文件的C文件并链接目标程序。能达到上述目的的就是makefile文件了。在工程的文件路径下新建一个Makefile文件。其中内容如下:main:main.o calc.o    gcc -o main main.o calc.omain.o:main.c calc.h    gcc -c main.ccalc.o:calc.c calc.h    gcc -c calc.cclean:    rm *.o    rm main执行make命令root@zhf-linux:/home/zhf/zhf/c_prj/make_function# makegcc -c main.cgcc -c calc.cgcc -o main main.o calc.o来看下Makefile的规则:1 第一条规则的目标为main。而为了得到main,必须先得到main.o calc.o这2个文件。所以make会进一步查找这2个条件为目标的规则。2 第二条规则和第三套规则的目标三main.o和calc.o。main.o依赖于main.c和calc.h。为了得到main.o必行执行gcc -c main. Calc.o依赖于calc.c和calc.h。为了得到calc.o必须执行gcc -c calc.c3 最后的clean操作清除执行过程中产生的临时文件。当用make命令执行的时候,clean下的命令不会执行,要以make clean方式单独执行。执行后,所有*.o和main都被删除。root@zhf-linux:/home/zhf/zhf/c_prj/make_function# ls -altotal 40drwxr-xr-x 2 root root 4096 Nov 10 09:15 .drwxr-xr-x 3 root root 4096 Nov  8 10:35 ..-rw-r--r-- 1 root root  118 Nov 10 08:55 calc.c-rw-r--r-- 1 root root   94 Nov 10 08:54 calc.h-rw-r--r-- 1 root root 1056 Nov 10 09:15 calc.o-rwxr-xr-x 1 root root 7396 Nov 10 09:15 main-rw-r--r-- 1 root root  182 Nov 10 08:56 main.c-rw-r--r-- 1 root root 1196 Nov 10 09:15 main.o-rw-r--r-- 1 root root  142 Nov 10 09:15 Makefile执行make cleanroot@zhf-linux:/home/zhf/zhf/c_prj/make_function# make cleanrm *.orm mainroot@zhf-linux:/home/zhf/zhf/c_prj/make_function# ls -altotal 24drwxr-xr-x 2 root root 4096 Nov 10 09:29 .drwxr-xr-x 3 root root 4096 Nov  8 10:35 ..-rw-r--r-- 1 root root  118 Nov 10 08:55 calc.c-rw-r--r-- 1 root root   94 Nov 10 08:54 calc.h-rw-r--r-- 1 root root  182 Nov 10 08:56 main.c-rw-r--r-- 1 root root  142 Nov 10 09:15 Makefile下面我们来修改calc.h中的内容,#define max_value 50看下编译内容。由于calc.c和main.c都包含了calc.h因此calc.c和main.c都会编译root@zhf-linux:/home/zhf/zhf/c_prj/make_function# makegcc -c main.cgcc -c calc.cgcc -o main main.o calc.o如果只修改calc.c中的内容。calc.c修改如下int calculate(int n,int k){    printf("the value is %d",max_value);    return n*k+n*k;}可以看到只编译了calc.c。main.c没有编译root@zhf-linux:/home/zhf/zhf/c_prj/make_function# makegcc -c calc.cgcc -o main main.o calc.o当没有任何文件修改的时候:会提示main is up to dateroot@zhf-linux:/home/zhf/zhf/c_prj/make_function# makemake: 'main' is up to date.那么make是如何工作的呢:1 make会在当前目录下查找名为makefile或者Makefile的文件2 如果找到,它会找文件中的第一个目标文件,在上面的例子中,它会找到main这个文件3 如果main不存在,或者main所依赖的后面的.o文件的修改时间比main晚,那么就会执行后面所定义的命令来生成main这个文件4 如果main所依赖的.o文件存在,那么make会在当前文件中查找目标为.o文件的依赖性,如果找到,则再根据那个规则生成.o文件5 当C文件和H文件存在时,make会生成.o文件。然后再用.o文件生成make的终结任务也就是执行文件main也就是说,main会一层一层的寻找文件的依赖关系,直到编译出一个目标文件。如果在查找过程中依赖的文件找不到那么就会直接退出或报错。继续来看下之前的makefile文件。在第一条规则的时候。.o文件被重复了两次。如果工程需要加入一个新的.o文件,那么就需要在2个地方加。如果makefile很复杂。那么就可有可能忘掉一个需要加入的地方。而导致编译失败。所以为了makefile的易维护,在makefile中可以使用变量。可以理解为C语言中的宏定义main:main.o calc.o    gcc -o main main.o calc.o文件修改如下:objects=main.o calc.omain:$(objects)    gcc -o main $(objects)

转载于:https://www.cnblogs.com/zhanghongfeng/p/7813172.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)