文章目录
一. Makefile作用
makefile 带来的好处就是自动化编译,一但写好,只需要 make 命令,整个工程全完自动化编译,极大的提高了开发效率,make 是一个命令工具,是一个解释makefile 中指令的命令工具,一般来说,大多数 ide 都有这个命令 比如 vc++ 的 nmake, linux 下的 gnu 的 make
二. Makefile组成和优势
makefile组成三要素:目标,依赖, 命令
targets(目标):prequisities(依赖)
command(命令,command前面要有一个tab键)
- 依赖(相当于原材料) -> 命令(加工)-> 目标(产物)
makefile优势:
-
大量代码的关系维护
大项目中源代码较多,手工维护 编译时间长而且编译命令复杂,把代码维护命令及编译命令写在 makefile 文件中,然后再用make 工具解析此文件自动执行相应命令 可实现合理编译
-
减少重复编译时间
在改动其中一个文件时,能判断哪些文件被修改过,可以只对该文件进行重新编译,然后重新链接所有的目标文件,节省编译时间
三. Makefile推导
目录结构:
1. 第一阶段Makefile文件
编译结果:
2. 第二阶段Makefile文件
使用变量
3. 第三阶段Makefile文件
自动推导
4. 第四阶段Makefile文件:
自动变量($^ $< $@)
具体意义如下:
> $@ : 目标文件
$^ : 所有依赖文件
$< : 第一个依赖文件
如下:
5. 第五阶段Makefile文件
Makefile函数
wildcard函数查找文件下所有文件名
patsubst查找替换
四. Makefile工作原理
目标的生成: a. 检查规则中的依赖文件是否存在; b. 若依赖文件不存在,则寻找是否有规则用来生成该依赖文件。
比如上图中,生成calculator的规则是gcc main.o add.o sub.o mul.o div.o -o,Makefil会先检查main.o, add.o, sub.o, mul.o, div.o是否存在,如果不存在,就会再寻找是否有规则可以生成该依赖文件。
比如缺少了main.o这个依赖,Makefile就会在下面寻找是否有规则生成main.o。当它发现gcc main.c -o main.o这条规则可以生成main.o时,它就利用此规则生成main.o,然后再生成终极目标calculator。
整个过程是向下寻找依赖,再向上执行命令,生成终极目标。
目标的更新: a. 检查目标的所有依赖,任何一个依赖有更新时,就重新生成目标; b. 目标文件比依赖文件时间晚,则需要更新。
比如,修改了main.c,则main.o目标会被重新编译,当main.o更新时,终极目标calculator也会被重新编译。其它文件的更新也是类推。
附录:
gcc 命令的常用选项
经典Makefile
CC := g++
CFLAGS := -g
TARGET := test
SRCS := $(wildcard *.cpp)
OBJS := $(patsubst %cpp,%o,$(SRCS))
all:$(TARGET)
%.o:%.cpp
$(CC) $(CFLAGS) -c $< -o $@
$(TARGET):$(OBJS)
$(CC) $(CFLAGS) -o $@
clean:
rm -rf $(TARGET) *.o
万能Makefile
####################################################
# Generic makefile - 万能Makefile
# for compiling and linking C++ projects on Linux
# Author: George Foot Modified:Jackie Lee
####################################################
### Customising
#
# Adjust the following if necessary; EXECUTABLE is the target
# executable's filename, and LIBS is a list of libraries to link in
# (e.g. alleg, stdcx, iostr, etc). You can override these on make's
# command line of course, if you prefer to do it that way.
#
#
EXECUTABLE := main # 可执行文件名
LIBDIR:= # 静态库目录
LIBS := # 静 态 库 文 件 名
INCLUDES:=. # 头文件目录
SRCDIR:= # 除了当前目录外,其他的源代码文件目录
#
# # Now alter any implicit rules' variables if you like, e.g.:
CC:=g++
CFLAGS := -g -Wall -O3
CPPFLAGS := $(CFLAGS)
CPPFLAGS += $(addprefix -I,$(INCLUDES))
CPPFLAGS += -MMD
#
# # The next bit checks to see whether rm is in your djgpp bin
# # directory; if not it uses del instead, but this can cause (harmless)
# # `File not found' error messages. If you are not using DOS at all,
# # set the variable to something which will unquestioningly remove
# # files.
#
RM-F := rm -f
# # You shouldn't need to change anything below this point.
#
SRCS := $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR)))
OBJS := $(patsubst %.cpp,%.o,$(SRCS))
DEPS := $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS := $(filter-out $(wildcard $(DEPS)),$(DEPS))
MISSING_DEPS_SOURCES := $(wildcard $(patsubst %.d,%.cpp,$(MISSING_DEPS)))
.PHONY : all deps objs clean veryclean rebuild info
all: $(EXECUTABLE)
deps : $(DEPS)
objs : $(OBJS)
clean :
@$(RM-F) *.o
@$(RM-F) *.d
veryclean: clean
@$(RM-F) $(EXECUTABLE)
rebuild: veryclean all
ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS) :
@$(RM-F) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(EXECUTABLE) : $(OBJS)
$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))
info:
@echo $(SRCS)
@echo $(OBJS)
@echo $(DEPS)
@echo $(MISSING_DEPS)
@echo $(MISSING_DEPS_SOURCES)
多级目录结构的Makefile
二级目录结构下的Makefile的写法参照 Linux编程工具-Makefile(二)