首页 > 代码库 > Makefile使用,Makefile的优化全过程
Makefile使用,Makefile的优化全过程
以一组简单的.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 appapp是目标 ‘:’冒号后面是这个目标的依赖项,下面的命令是要执行的命令,需要加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
所以我们继续优化Makefile 下面我们使用Makefile的函数来获取需要的文件,
src=http://www.mamicode.com/$(wildcard *.c)>
这样,我们先获取当前目录下的所有的.c文件,保存在变量src中,然后再将所有的.c替换成.o 保存在变量obj中.下面的$(obj)只是取变量的值。所以,我们在当前目录增加多少个.c文件也不需要修改这个文件了。仅限当前单目录编译哦。但是,又但是了,我都烦了,但是真的得再但是一下,优化是作为程序猿一直要做的事情。所以,继续优化Makefile,比如我想在编译的时候很方便的指定各项参数,输出的可执行文件名字,甚至,我想换个编译器。能行吗 ? 好吧,确实可以这么干。但是还得看下面的:
CFLAGS= -g -Wall LDFLAGS= CPPFLAGS=-I. CC=gcc #CC=clang target=app src=http://www.mamicode.com/$(wildcard *.c)>
OK 最终版单目录无干扰c文件的通用编译Makefile 就写好了。这个文件可以指定 编译选项,预处理选项,和库文件选项,可以更换编译器,也可以修改输出文件名,而且都是只需要修改文件最前方的几个变量就可以了。
Makefile使用,Makefile的优化全过程