Makefile的总结

       Make是一个很通用的用于编译我们程序的工具,否则对于较大的工程,进行编译可能就是一件很麻烦的事情。今天对makefile进行了一点自己的总结,肯定不是那种从原理上能把makefile讲得面面俱到,很详细的那种,但是应该比较实用,希望对初学者能够有所帮助。想要有深入的了解,网上也有很多详细的资料。

        说Makefile,首先说说一说编译与链接。

        编译:一般来说,无论是CC++首先要把源文件编译成中间代码文件,在Windows下也就是.obj文件,UNIX下是.o 文件,即 Object File,这个动作叫做编译(compile)。编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

        链接:把大量的Object File合成执行文件,这个动作叫作链接(link链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。文件打个包,在Windows下这种链接器并不管函数所在的源文件,只管函数的中间目标文件(ObjectFile),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标包叫“库文件”(LibraryFile),也就是.lib 文件,在UNIX下,是Archive File,也就是.a 文件。

        编译&链接:源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的ObjectFile中找寻函数的实现,如果找不到,那到就会报链接错误码(LinkerError),在VC下,这种错误一般是:Link2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的ObjectFile.

        make命令执行时,需要一个Makefile文件,以告诉make命令需要怎么样的去编译和链接程序。

             满足下列条件Makefile将会被执行:

             1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。

        2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。

        3 )如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的 C 文件,并链接目标程序

              Makefile的规则:

              target... : prerequisites ...

              command

         ...

         ...

       target就是一个目标文件,可以是ObjectFile,也可以是执行文件。还可以是一个标签(Label),例如:cleaninstall

       prerequisites就是要生成那个target所需要的文件或是目标。

       command也就是make需要执行的命令。(任意的Shell命令)需要一个TAB

       举个例子:

       mainmain.o object1.o object2.o

       gcc -o main main.o object1.o object2.o

       main.omain.c object1.h object2.h

       gcc -c main.c

       object1.oobject1.c object1.h

       gcc -c object1.c

       object2.oobject2.c object2.h

       gcc -c object2.c

       有用的变量:

      $@--目标文件;

      $^--所有的依赖文件;

      $<--第一个依赖的条件。

      上面的程序可以简化为:

      mainmain.o  object1.o object2.o

      gcc -o $@ $^

      main.omain.c object1.h object2.h

      gcc -c $<

      object1.oobject1.c object1.h

      gcc -c $<

      object2.oobject2.c object2.h

      gcc -c $<

      .c.o

      被定义为老式的"双后缀规则",在一些大型程序中是很常见的。 双后缀规则定义了一对后缀:目标文件的后缀和依赖目标(源文件)的后缀。如 ". c.o " 相当于 "%o : %c" 后缀规则中所定义的后缀应该是 make 所认识的,例如: ".c" ".o" 都是 make 所知道。因而,如果你定义了一个规则是 ". c.o " 那么其就是双后缀规则,意义就是 ".c" 是源文件的后缀, ".o" 是目标文件的后缀。

       后缀规则不允许任何的依赖文件,如果有依赖文件的话,那就不是后缀规则,那些后缀统统被认为是文件名要让make知道一些特定的后缀,我们可以使用伪目标“.SUFFIXES”来定义或是删除:.SUFFIXES:.c .o .h # 定义自己的后缀

      这样我们前面的程序可以进一步简化:

      mainmain.o object1.o object2.o

      gcc -o $@  $^

      .c.o

      gcc -c  $<

      clean类似C语言中的label,其冒号后面什么也没有,make就不会主动去找文件的依赖性,也就不会执行其后所定义的命令。只有make后显示了label的名字,才会执行其后的命令。程序的打包,程序的备份都可以以此种方式来操作。

       也可以表示为:

      .PHONY:clean

     其中.PHONY表示clean是一个“为目标”。

     还要注意以下几点:

     1.Make只管文件的依赖关系,至于命令中的编译错误,make不管。依赖的文件找不到,make会直接退出

     2.为了Makefile的易维护性,在Makefile中我们可以使用变量,makefile中的变量也就是一个字符串,理解成C语言中的宏更好

     3.如果make找到一个whatever.o那么whatever.c就会是whatever.o的依赖文件。

    4. 通常,make会把其要执行的命令行在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个命令将不被make显示出来,最具代表性的例子是,我们用这个功能来像屏幕显示一些信息。

     @echo正在编译XXX模块......

     make执行时,会输出“正在编译XXX模块            ......”字串,但不会输出命令,如果没有“@”,那么     make 将输出:

    echo 正在编译XXX模块......

    正在编译XXX模块......

    5.如果 make 执行时,带入 make 参数“ -n” 或“ --just-print” ,那么其只是显示命令,但不会执行命令,这个功能很有利于我们调试我们的 Makefile ,看看我们书写的命令是执行起来是什么样子的或是什么顺序的。
    6.
make 参数“ -s” 或“ -- slient 则是全面禁止命令的显示。

     












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值