Makefile使用,Makefile的优化全过程

来源:互联网 发布:vv51软件下载 编辑:程序博客网 时间:2024/05/18 06:44

以一组简单的.c文件为例。从编译命令到Makefile的学习过程。

gcc参数不做过多叙述,如下这几个文件及内容:


add.c

int add(int a int b){    return a+b;}


sub.c

int sub(int a ,int b){    return a-b;}

cal.h

#ifndef __CAL_H_#define __CAL_H_int add(int,int);int sub(int,int);#endif


main.c

#include <stdio.h>#include "cal.h"int main (void){    printf("%d\n",add(33,55));    printf("%d\n",sub(88,55));    return 0;}<p></p>

共有3个源文件,一个头文件,那么现在编译的话需要如下命令

gcc main.c add.c sub.c -o app

假设当前文件夹内没有其他的.c文件了

但是每次编译也需要敲这个命令。这是一个多么让人蛋疼的事情啊。

所以应该有一种办法来搞定这个让人非常蛋疼的事情,没错,它就是Makefile

现在,我们写一个第一版本的Makefile,Makefile文件名固定,第一个字母必须大写。

如下:

app:main.c add.c sub.c     gcc main.c add.c sub.c -o app
app是目标 ‘:’冒号后面是这个目标的依赖项,下面的命令是要执行的命令,需要加tab 缩进


那么现在 我们直接在终端输入make 就可以执行刚才的命令了。

只是,现在问题来了。我可能修改的时候只改动来一个.c文件,这样做不是每个都要重新再编译一遍吗。C CPP的编译是多么浪费时间呀

所以下一个版本就又诞生了

   app:main.o add.o sub.o       gcc main.o add.o sub.o -o app   main.o:main.c      gcc -c main.c   add.o:add.c       gcc -c add.c   sub.o:sub.c       gcc -c sub.c
这个文件表示:最终目标是编译出一个可执行文件,依赖三个预处理文件.o文件,各个.o文件又依赖与.c文件。Makefile 内部机制会检测依赖的.c 和.o文件是否在时间上匹配,如果.c文件较新,则需要重新编译成.o文件。所以,当我们只修改了一个源文件的时候,再make编译也不会全部都编译一遍了,只会编译修改过的文件。

嗯,不错,貌似感觉已经很好了。

不过,我现在又增加了一个mul.c文件,需要一起编译,我了个去,貌似需要改的地方很多呀,要增加app依赖的.o  要修改gcc命令,还要增加新文件的.o目标依赖。

干,这样还是不够智能啊。怎么办呢。   哈哈 ,偷偷告诉你们,Makefile的默认配置已经做好了.o文件依赖.c文件的关联,文件前缀相同即可。

所以,还可以这样写,也没有问题

 app:main.o add.o sub.o       gcc main.o add.o sub.o -o app


这样写跟上面的效果是相同的。但是这样还是达不到我们想要的效果,Dont do yourself

所以我们继续优化Makefile 下面我们使用Makefile的函数来获取需要的文件,

src=$(wildcard *.c)obj=$(patsubst %.c,%.o,$(src))app:$(obj)gcc $(obj) -o app


这样,我们先获取当前目录下的所有的.c文件,保存在变量src中,然后再将所有的.c替换成.o 保存在变量obj中.下面的$(obj)只是取变量的值。所以,我们在当前目录增加多少个.c文件也不需要修改这个文件了。仅限当前单目录编译哦。

但是,又但是了,我都烦了,但是真的得再但是一下,优化是作为程序猿一直要做的事情。所以,继续优化Makefile,比如我想在编译的时候很方便的指定各项参数,输出的可执行文件名字,甚至,我想换个编译器。能行吗 ? 好吧,确实可以这么干。但是还得看下面的:

CFLAGS= -g -WallLDFLAGS=CPPFLAGS=-I.CC=gcc#CC=clangtarget=appsrc=$(wildcard *.c)obj=$(patsubst %.c,%.o,$(src))$(target):$(obj)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $^ -o $@ .PHONY:cleanclean:rm -f $(obj)rm -f $(targe)

OK 最终版单目录无干扰c文件的通用编译Makefile 就写好了。这个文件可以指定 编译选项,预处理选项,和库文件选项,

可以更换编译器,也可以修改输出文件名,而且都是只需要修改文件最前方的几个变量就可以了。







0 0