Makefile关系到了整个工程的编译规则。一个工程中的源文件不计其数,并且按类型、功能、模块分 别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译, 哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可 以执行操作系统的命令。
Makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极 大的提高了软件开发的效率。 make是一个命令工具,是一个解释makefile中指令的命令工具。
在Unix下进行软件编译,需要学会自己写makefile。会不会 写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
下面这个非常详细的教程,包含几乎GNU make的Makefile的所有细节:
跟我一起写Makefile
Makefile小模板
适用于纯 C 语言
# 指令编译器和选项
CC=gcc
CFLAGS=-Wall -std=gnu99
# 目标文件
TARGET=main
SRCS = main1.c \
main2.c \
main3.c
INC = -I./
OBJS = $(SRCS:.c=.o)
$(TARGET):$(OBJS)
$(CC) -o $@ $^
clean:
rm -rf $(TARGET) $(OBJS)
%.o:%.c
$(CC) $(CFLAGS) $(INC) -o $@ -c $<
注意:Makefile有个规则就是命令行是以tab键开头,4个空格或其他则会报错:
Makefile:2: *** missing separator。stop
- 相比于单个文件和多个文件的makefile,通过变量INC制定了头文件路径。头文件路径之间通过空格隔开。
- 编译规则%.o:%.c中加入了头文件参数
(CFLAGS)
@ -c $<,
- 单个文件和多个文件的makefile相比增加了头文件路径参数。
- SRCS变量中,文件较多时可通过“\”符号续行。
- $@ --代表目标文件
- $^ --代表所有的依赖文件
- $< --代表第一个依赖文件(最左边的那个)。
适用于 C/C++ 混合编译
目录结构如下:
httpserver
│ main.cpp
│ Makefile
└─────inc
│ │ mongoose.h
│ │ http_server.h
│
──────src
│ │ http_server.cpp
│ │ mongoose.c
│ │ ...
Makefile 如下:
CC=gcc
CXX=g++
# 编译器在编译时的参数设置,包含头文件路径设置
CFLAGS:=-Wall -O2 -g
CFLAGS+=-I $(shell pwd)/inc
CXXFLAGS:=-Wall -O2 -g -std=c++11
CXXFLAGS+=-I $(shell pwd)/inc
# 库文件添加
LDFLAGS:=
LDFLAGS+=
# 指定源程序存放位置
SRCDIRS:=.
SRCDIRS+=src
# 设置程序中使用文件类型
SRCEXTS:=.c .cpp
# 设置运行程序名
PROGRAM:=httpserver
SOURCES=$(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))
OBJS=$(foreach x,$(SRCEXTS),$(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))
.PHONY: all clean distclean install
%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
%.o: %.cxx
$(CXX) -c $(CXXFLAGS) -o $@ $<
$(PROGRAM): $(OBJS)
ifeq ($(strip $(SRCEXTS)),.c)
$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
else
$(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS)
endif
install:
install -m 755 -D -p $(PROGRAM) ./bin
clean:
rm -f $(shell find -name "*.o")
rm -f $(PROGRAM)
distclean:
rm -f $(shell find -name "*.o")
rm -f $(shell find -name "*.d")
rm -f $(PROGRAM)
all:
@echo $(OBJS)