Makefile
make和Makefile介绍
make工具
利用make工具可以自动完成编译工作。这些工作包括:如果仅修改了某几个源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。利用这种自动编译可大大简化开发工作,避免不必要的重新编译。
Makefile
make工具通过一个称为Makefile的文件来完成并自动维护编译工作。Makefile文件描述了整个工程的编译、链接等规则。
Makefile基本规则
- 规则
TARGET...:DEPENDENCIES ...
COMMAND
...
-
目标
目标(TARGET)程序产生的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如clean,也称为伪目标。 -
依赖
依赖(DEPENDENCIES)是用来产生目标的输入文件列表,一个目标通常依赖于多个文件。 -
命令
命令(COMMAND)是make执行的动作(命令是shell命令或是可在shell下执行的程序)。注意:每个命令行的起始字符必须是TAB字符!如果DEPENDENCIES中有一个或多个文件更新的话,COMMAND就要执行,这就是Makefile最核心的内容
简单的Makefile编写
main:main.o add.o sub.o
gcc main.o add.o sub.o -o main
main.o:main.c add.h sub.h
gcc -c main.c -o main.o
add.o:add.c add.h
gcc -c add.c -o add.o
sub.o:sub.c sub.h
gcc -c sub.c sub.o
clean:
rm -rf main main.o add.o sub.o
Make自动化变量
选项名 | 作用 |
---|---|
$@ | 规则的目标文件名 (main) |
$< | 规则的第一个依赖文件名 (main.o) |
$^ | 规则的所有依赖文件列表 (main.o add.o sub.o) |
.PHONY:clean
OBJECTS=main.o add.o sub.o
main:$(OBJECTS)
gcc $^ -o $@
main.o:main.c add.h sub.h
gcc -c $< -o $@
add.o:add.c add.h
gcc -c $< -o $@
sub.o:sub.c sub.h
gcc -c $< -o $@
clean:
rm -rf main $(OBJECTS)
执行make命令的时候,会查找Makefile或makefile文件;如果需要指定Makefile文件,可以使用
make clean -f Makefile.1
执行命令的时候如果不想打印输出,可以加@
@echo "begin clean ..."
Makefile编译多个可执行文件
模式规则
%.c : %.o
后缀规则
.c.o:
01test.c
int main(void)
{
return 0;
}
02test.c
int main(void)
{
return 0;
}
Makefile
.PHONY:clean all
BIN=01test 02test
all:$(BIN)
clean:
rm -f *.o $(BIN)
这里all也是伪目标,它依赖BIN,Makefile会生产BIN(01test 02test),当前并没有给出生成规则,编译器会自动推导,将通用的.c文件变成通用的可执行文件;如果不想使用推导的,也可以自己定义生产规则
.PHONY:clean all
BIN=01test 02test
all:$(BIN)
01test:01test.o
gcc -Wall -g $^ -o $@
02test:02test.o
gcc -Wall -g $^ -o $@
clean:
rm -f *.o $(BIN)
这时,01test.o、02test.o文件是自动推导生成的,从.o文件到可执行文件,是按照我们的指定的规则生成的;可以使用模式规则或后缀规则来指定.o文件的生成规则
.PHONY:clean all
BIN=01test 02test
all:$(BIN)
#将当前文件夹下的.c文件生产对应的.o文件
#%.o:%.c
.c.o:
gcc -Wall -g -c $< -o $@
01test:01test.o
gcc -Wall -g $^ -o $@
02test:02test.o
gcc -Wall -g $^ -o $@
clean:
rm -f *.o $(BIN)
定义常用的变量
CC=gcc
CFLAGS=-Wall -g
.PHONY:clean all
BIN=01test 02test
all:$(BIN)
#将当前文件夹下的.c文件生产对应的.o文件
#%.o:%.c
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
01test:01test.o
$(CC) $(CFLAGS) $^ -o $@
#如果02test还依赖其他文件,只需要在02test.o 后加上其他文件即可
02test:02test.o
$(CC) $(CFLAGS) $^ -o $@
clean:
rm -f *.o $(BIN)
编译器会自动根据自定义的CC和CFLAGS生产推导规则
CC=gcc
CFLAGS=-Wall -g
.PHONY:clean all
BIN=01test 02test
all:$(BIN)
.c.o:
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f *.o $(BIN)
make常用内嵌函数
函数调用
$(funcation arguments)
$(wildcard PATTERN)
当前目录下匹配模式的文件
src=$(wildcard *.c)
$(patsubst PATTERN,REPLACEMENT,TEXT)
模式替换函数
$(patsubst %.c,%.o,$src) == $(src:.c=.o)
shell函数
执行shell命令
$(shell ls -d */)
多级目录Makefile
CC=gcc
CFLAGS=-Wall -g
BIN=main
SUBDIR=$(shell ls -d */)
ROOTSRC=$(wildcard *.c)
ROOTOBJ=$(ROOTSRC:%.c=%.o)
SUBSRC=$(shell find $(SUBNAME) -name '*.c')
SUBONJ=$(SUBSRC:%.c=%.o)
$(BIN):$(ROOTSRC) $(SUBOBJ)
$(CC) $(CFLAGS) -o $(BIN) $(ROOTBIN) $(SUBOBJ)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(BIN) $(ROOTOBJ) $(SUBOBJ)
生产多个可执行文件
SUBDIRS = test1 test2
.PHONY:default all clean $(SUBDIRS)
#default是伪目标,依赖all
default:all
#生成all和clean
#$(MAKE)=make
#TARGET=$@ $@=all
all clean:
$(MAKE) $(SUBDIRS) TARGET=$@
#-C表示会进入test1 test2文件夹,调用文件夹下的Makefile
$(SUBDIRS):
$(MAKE) -C $@ $(TARGET)
test1 Mafile
CC=gcc
BIN=test1
OBJS=test1.o
.PHONY:all clean print
all:print $(BIN)
print:
@echo "-----make all in $(PWD) ------"
$(BIN):$(OBJS)
$(CC) $(OBJS) -o $@
%.o:%.c
$(CC) -c $<
clean:
@echo "------make clean in $(PWD) ------"
rm -f $(BIN) $(OBJS)
test2 Makefile
CXX=g++
CPPFLAGS=-Wall -g
BIN=test2
OBJS=test2.o
.PHONY:all clean print
all:print $(BIN)
print:
@echo "------make all in $(PWD)------"
$(BIN):$(OBJS)
$(CXX) $(OBJS) -o $@
%.o:%.cpp
$(CXX) -c $<
clean:
@echo "------make clean in $(PWD)------"
rm -f $(BIN) $(OBJS)
其它
#make就会在当前目录找不到的情况下,到所指定的目录中去找寻文件。
VPATH = ./src1 ./src2 ./src3
#指定库文件路径
#LDFLAGS
#指定要链接的库
#LIBS
#静态库与动态库
STATIC_LIB= -Wl,-Bstatic -lcrypto -lnet -lpcap
DYNAMIC_LIB= -Wl,-Bdynamic -lpthread -lmysqlclient -Wl,--as-needed