三个文件:
- hellomake.c
#include "hellomake.h"
int main() {
// call a function in another file
myPrintHelloMake();
return(0);
}
- hellofunc.c
#include <stdio.h>
#include "hellomake.h"
void myPrintHelloMake(void) {
printf("Hello makefiles!\n");
return;
}
- hellomake.h
/*
example include file
*/
void myPrintHelloMake(void);
- 如果用常规的方法编译:
gcc -o hellomake hellomake.c hellofunc.c -I.
生成hellomake程序 用hellomake.c 和 hellofunc.c 并且包含当前目录下的.h文件
这样会导致一个问题,如果你修改了三个文件中的任何一个,你都需要用上下键来恢复编译的这条命令,但是,如果你增加了一个文件,那么你需要用上下键恢复编译的这条命令,并且添加刚添加的文件,重新编译。而且,你浪费了时间在重新编译已经编译过的文件。其实就是懒
- 所以,你可以用makefile文件来解决这个问题
make的工作流
- make在当前目录下寻找“Makefile”或“makefile”文件
- 若找到,查找文件中的第一个目标文件.o
- 若目标文件不存在,根据依赖关系查找.s文件
- 若.s文件不存在,根据依赖关系查找.i文件
- 若.i文件不存在,根据依赖关系查找.c文件,此时.c文件一定存在,于是生成一个.o文件,再去执行
编写makefile:将命令行的方式编写到一个文件中
- There must be a tab at the beginning of any command, and make will not be happy if it's not there.
hellomake:hellomake.c hellofunc.c
gcc -o hellomake hellomake.c hellofunc.c -I.
1.编写makefile 更有效
CC=gcc
CFLAGS=-I.
DEPS=hellomake.h
%.o:%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
$(CC) -o hellomake hellomake.o hellofunc.o
- 当make之后,等价于:
gcc -c -o hellomake.o hellomake.c -I.
gcc -c -o hellofunc.o hellofunc.c -I.
gcc -o hellomake hellomake.o hellofunc.o
解释:
Make命令允许对文件名,进行类似正则运算的匹配,主要用到的匹配符是%。当前目录下有两个.c文件hellomake.c和hellofunc.c,make会遍历替换。**即.o文件依赖于.c文件和头文件,执行下面的命令。
$(CC) -c -o $@ $< $(CFLAGS)
操作符 | 说明 | 本例中指代 |
---|---|---|
\(@|表示当前的目标文件|.o文件| |\)< | 第一个依赖项 | .c文件 |
2.编写makefile 更有效:不用牵一发而动全身
- 编译器如果换了?g++?
- 想要改变生成的obj文件名字?
CC=gcc
CFLAGS=-I.
DEPS=hellomake.h
OBJ=hellomake.o hellofunc.o
%.o:%.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake:$(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
- make 输出为
gcc -o hellomake hellomake.o hellofunc.o -I.
操作符 | 说明 | 本例中指代 |
---|---|---|
$^ | 表示所有的依赖项 | hellomake.o hellofunc.o文件 |
3.编写makefile更有效:指定编译后输出文件目录-自动生成!!!
IDIR=../include
CC=gcc
CFLAGS=-I$(IDIR)
ODIR=obj
LDIR=../lib
#LIBS=-lm
_DEPS=hellomake.h
DEPS=$(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ=hellomake.o hellofunc.o
OBJ=$(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake:$(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
解释:
函数patsubst 模式替换函数,
$(patsubst pattern,replacement,text)
将text按照pattern替换成replacement
上面的两个替换表示将.o移动到obj目录下,.c文件移动到include目录下,%相当于占位符