makefile是在linux/unix下主要使用的build工具,支持推导、模式匹配等,可以通过简单的语句来描述编译依赖关系。
在linux/unix下,这个的使用是必不可少的。
通过读“跟我一起写Makefile”和其它资料,加深了对makefile的了解,也写了一个例子加深印象。
首先写了一个依赖文件,这个依赖文件把所有的推导关系都完整的写了出来,然后基于参考文档再对例子简化。
文件结构:
sslserver.cpp
sslclient.cpp
myerr.h
makefile
all : client server
client : sslclient.o
gcc -o client sslclient.o -L/usr/local/opt/openssl/lib -lssl -lcrypto
server : sslserver.o
gcc -o server sslserver.o -L/usr/local/opt/openssl/lib -lssl -lcrypto
sslclient.o : myerr.h sslclient.cpp
gcc -c sslclient.cpp -I/usr/local/opt/openssl/include -o sslclient.o
sslserver.o : myerr.h sslserver.cpp
gcc -c sslserver.cpp -I/usr/local/opt/openssl/include -o sslserver.o
clean :
rm client sslclient.o
rm server sslserver.o
上面的完整例子包含了基本上手动编译的所有内容,描述了完整的依赖关系。但是其实有些是不需要的,makefile缺省依赖关系中已经有了描述。一项一项的来简化:
[/Users/aaa]$ export|grep CPPFLAGS
declare -x CPPFLAGS="-I/usr/local/opt/openssl/include"
sslclient : sslclient.o
${CC} -o $(@) $(<) -lssl -lcrypto
另外对于库的引用,可以通过缺省引用变量定义,使用缺省变量定义后:如果没有特别之处,命令行也可省略
LDLIBS = -lssl -lcrypto
sslclient : sslclient.o
${CC} -o $(@) $(<) ${LDLIBS}
4.为clean添加 .PHONY 定义, .PHONY声明的依赖项为 伪目标,不用有依赖文件,添加声明后更规范
5. rm前改为-rm,这样删除不到文件error会被忽略,不会导致make失败
修改后的makefile文件为
all : sslclient sslserver
CXX = gcc
LDLIBS = -lssl -lcrypto
sslclient : sslclient.o
sslserver : sslserver.o
$(CXX) -o $(@) $(^) ${LDLIBS}
*.o : myerr.h
.PHONY : clean
clean :
-rm sslclient sslserver *.o
文件结构调整如下:调整后.h .cpp与makefile都不在一个目录中
build:
makefile
include:
myerr.h
src:
sslserver.cpp
sslclient.cpp
此时需要通过vpath添加查找路径,例如:
vpath %.h …/include :从…/include目录中搜索.h文件
vpath %.cpp …/src : 从…/src目录中搜索.cpp文件
也或使用VPATH直接指定搜索路径
VPATH = …/src …/include
obj推导可以使用函数
$(wildcard pattern…)函数可以把对应模式的文件一一列出来
$(patsubst ,, ) 可以做后缀的替换
$(notdir
OBJS := $(notdir $(patsubst %.cpp, %.o, $(wildcard *.cpp)))
all : sslclient sslserver
CXX = gcc
vpath %.h ../include
vpath %.cpp ../include
OBJS := $(notdir $(patsubst %.cpp, %.o, $(wildcard *.cpp)))
LDLIBS = -lssl -lcrypto
sslclient : sslclient.o
sslserver : sslserver.o
$(OBJS) : myerr.h
.PHONY : clean
clean :
-rm sslclient sslserver $(OBJS)
从上面语句中,我们可以看出能够通过下面两种方法来执行xxx命令
@xxx
${shell xxx}
内置规则为make缺省使用的规则,其中的变量也为缺省使用的变量,像常见的CPPFLAGS、LDFLAGS、LDLIBS等;
当我们使用的规则和缺省规则一致时,命令可以不用写出来,从而简化makefile文件。
C编译内置规则:编译命令使用 $(CC) $(CPPFLAGS) ( C F L A G S ) − c n . o i s m a d e a u t o m a t i c a l l y f r o m n . c w i t h a r e c i p e o f t h e f o r m ‘ (CFLAGS) -c n.o is made automatically from n.c with a recipe of the form ‘ (CFLAGS)−cn.oismadeautomaticallyfromn.cwitharecipeoftheform‘(CC) $(CPPFLAGS) $(CFLAGS) -c’.
C++编译内置规则:编译命令使用 $(CXX) $(CPPFLAGS) ( C X X F L A G S ) − c n . o i s m a d e a u t o m a t i c a l l y f r o m n . c c , n . c p p , o r n . C w i t h a r e c i p e o f t h e f o r m ‘ (CXXFLAGS) -c n.o is made automatically from n.cc, n.cpp, or n.C with a recipe of the form ‘ (CXXFLAGS)−cn.oismadeautomaticallyfromn.cc,n.cpp,orn.Cwitharecipeoftheform‘(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’. We encourage you to use the suffix ‘.cc’ for C++ source files instead of ‘.C’.
C链接规则:链接时缺省使用 $(CC) $(LDFLAGS) n.o $(LOADLIBES) ( L D L I B S ) n i s m a d e a u t o m a t i c a l l y f r o m n . o b y r u n n i n g t h e l i n k e r ( u s u a l l y c a l l e d l d ) v i a t h e C c o m p i l e r . T h e p r e c i s e r e c i p e u s e d i s ‘ (LDLIBS) n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘ (LDLIBS)nismadeautomaticallyfromn.obyrunningthelinker(usuallycalledld)viatheCcompiler.Thepreciserecipeusedis‘(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
使用 make --help可以查看make支持的命令行:一些很有用的命令行,如:
-f 指定makefile文件
-n 打印执行的语句,并不真正执行
-B 不比较时间,强制make所有target
–debug make时打印依赖查找过程
-i 忽略执行错误
-I DIRECTORY 用于添加包含include文件
[/Users/aaa]$make --help
Usage: make [options] [target] ...
Options:
-b, -m Ignored for compatibility.
-B, --always-make Unconditionally make all targets.
-C DIRECTORY, --directory=DIRECTORY
Change to DIRECTORY before doing anything.
-d Print lots of debugging information.
--debug[=FLAGS] Print various types of debugging information.
-e, --environment-overrides
Environment variables override makefiles.
-f FILE, --file=FILE, --makefile=FILE
Read FILE as a makefile.
-h, --help Print this message and exit.
-i, --ignore-errors Ignore errors from commands.
-I DIRECTORY, --include-dir=DIRECTORY
Search DIRECTORY for included makefiles.
-j [N], --jobs[=N] Allow N jobs at once; infinite jobs with no arg.
-k, --keep-going Keep going when some targets can't be made.
-l [N], --load-average[=N], --max-load[=N]
Don't start multiple jobs unless load is below N.
-L, --check-symlink-times Use the latest mtime between symlinks and target.
-n, --just-print, --dry-run, --recon
Don't actually run any commands; just print them.
-o FILE, --old-file=FILE, --assume-old=FILE
Consider FILE to be very old and don't remake it.
-p, --print-data-base Print make's internal database.
-q, --question Run no commands; exit status says if up to date.
-r, --no-builtin-rules Disable the built-in implicit rules.
-R, --no-builtin-variables Disable the built-in variable settings.
-s, --silent, --quiet Don't echo commands.
-S, --no-keep-going, --stop
Turns off -k.
-t, --touch Touch targets instead of remaking them.
-v, --version Print the version number of make and exit.
-w, --print-directory Print the current directory.
--no-print-directory Turn off -w, even if it was turned on implicitly.
-W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
Consider FILE to be infinitely new.
--warn-undefined-variables Warn when an undefined variable is referenced.
-N OPTION, --NeXT-option=OPTION
Turn on value of NeXT OPTION.
(Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu)
参考:《跟我一起写Makefile》
参考:https://blog.csdn.net/mcgrady_tracy/article/details/27240139
参考:https://www.gnu.org/software/make/manual/html_node/Catalogue-of-Rules.html#Catalogue-of-Rules
参考:https://en.wikipedia.org/wiki/Make_(software)
参考:https://blog.csdn.net/yangzhongxuan/article/details/7355170