makefile使用例子

makefile使用例子

  • 完整描述
  • 简化makefile:
  • 调整结构,使用vpath和cpp推导obj
  • 其它常用命令
  • make的命令行

makefile是在linux/unix下主要使用的build工具,支持推导、模式匹配等,可以通过简单的语句来描述编译依赖关系。
在linux/unix下,这个的使用是必不可少的。

通过读“跟我一起写Makefile”和其它资料,加深了对makefile的了解,也写了一个例子加深印象。

首先写了一个依赖文件,这个依赖文件把所有的推导关系都完整的写了出来,然后基于参考文档再对例子简化。
文件结构:
sslserver.cpp
sslclient.cpp
myerr.h
makefile

完整描述

  1. all依赖于sslclient和sslserver
  2. sslclient依赖于sslclient.o (生成命令位于下一行,行首需要tab开始)
  3. sslserver依赖于sslserver.o
  4. sslclient.o 依赖于 myerr.h sslclient.cpp
  5. sslserver.o 依赖于 myerr.h sslserver.cpp
  6. 另外程序依赖了openssl,所以编译时包含openssl的include路径,链接时包含openssl的lib路径,链接时还需要指定包含的库ssl与crypto名称
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:

上面的完整例子包含了基本上手动编译的所有内容,描述了完整的依赖关系。但是其实有些是不需要的,makefile缺省依赖关系中已经有了描述。一项一项的来简化:

  1. .o依赖关系的同名cpp可以省去
    .o文件缺省依赖同名的.c或.cpp文件
  2. 编译.o的命令行省去
    编译出.o文件时,缺省使用对应的同名.c或.cpp文件进行编译输出;
    如果不自己指定命令的话,编译时缺省会带$(CFLAGS) $(CPPFLAGS),对于openssl的include路径包含不用特殊指定了
    例如我本地已经配置了CPPFLAGS路径, 那么编译.o文件的那一行就可以省略掉了
[/Users/aaa]$ export|grep CPPFLAGS
declare -x CPPFLAGS="-I/usr/local/opt/openssl/include"
  1. 在命令行中 @ 代 表 目 标 项 , @ 代表目标项, @<代表首个依赖项,$^代表依赖项集合,基于此可以优化sslserver与sslclient的生成命令
    例如:
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

调整结构,使用vpath和cpp推导obj

文件结构调整如下:调整后.h .cpp与makefile都不在一个目录中
build:
makefile
include:
myerr.h
src:
sslserver.cpp
sslclient.cpp

  1. 此时需要通过vpath添加查找路径,例如:
    vpath %.h …/include :从…/include目录中搜索.h文件
    vpath %.cpp …/src : 从…/src目录中搜索.cpp文件
    也或使用VPATH直接指定搜索路径
    VPATH = …/src …/include

  2. 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)

其它常用命令

  1. 获取当前目录:
    curPath = ${shell dirname ${realpath ${lastword ${MAKEFILE_LIST}}}}
    @echo ${shell dirname ${realpath ${lastword ${MAKEFILE_LIST}}}}

从上面语句中,我们可以看出能够通过下面两种方法来执行xxx命令
@xxx
${shell xxx}

  1. 内置规则

内置规则为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的命令行

使用 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

你可能感兴趣的:(Centos,调测)