Makefile学习

1、多个if判断

DEMO := 2

all:
ifeq ($(DEMO), 1)
    @echo "DEMO 1"
else ifeq ($(DEMO), 2)
    @echo "DEMO 2"
else ifeq ($(DEMO), 3)
    @echo "DEMO 3"
else
    @echo "DEMO Other"
endif

输出:

DEMO 2
DEMO2

2、打印变量

可以使用 ${} 或者$() 或者 $ ,其中 $ 用于单字符变量,对于多字符变量,只能用前面两个

DEMO := 1
X := 1

all:
        @echo $${DEMO} = ${DEMO}
        @echo $$(DEMO) = $(DEMO)
        @echo $$X = $X

输出:

${DEMO} = 1
$(DEMO) = 1
$X = 1

3、=、:= 和 ?=

x := 1
y = 1
x ?= 2

all:
        @echo x=$(x)
        @echo y=$(y)

y = 2
y ?= 3

输出:

x=1
y=2

4、ifdef和ifndef使用

X := 1
Y :=
Z := 2

all:
ifndef X
        @echo "X = $(X)"
else ifdef Y
        @echo "Y = ${Y}"
else ifdef Z
        @echo "Z = ${Z}"
endif

输出:

Z = 2

5、origin获得变量来源

w1 := $(origin W)
x1 := $(origin X)
y1 := $(origin Y)
Z := 1
z1 := $(origin Z)
c := $(origin CC)


all:
        @echo "W: ${w1}"
        @echo "X: ${x1}"
        @echo "Y: ${y1}"
        @echo "Z: ${z1}"
        @echo "CC: ${c}"

运行:

$ X=1 make -f mk5 Y=2
W: undefined
X: environment
Y: command line
Z: file
CC: default

6、递归编译的三种方式

目录结构:

.
├── Makefile
├── sub1
│   └── Makefile
├── sub2
│   └── Makefile
├── sub3
│   └── Makefile
├── sub4
│   └── Makefile
└── sub5
    └── Makefile

子目录的Makefile内容只输出一句话:

sub1/Makefile内容:
all:
        @echo "	This is sub1"

sub2/Makefile内容:
all:
        @echo "	This is sub2"

sub3/Makefile内容:
all:
        @echo "	This is sub3"

sub4/Makefile内容:
all:
        @echo "	This is sub4"

sub5/Makefile内容:
all:
        @echo "	This is sub5"

顶层Makefile内容如下:

SUB_DIRS := $(sort $(wildcard sub*))

all: subdir
        @echo "		**** method 2 ****"
        @echo "In top dir"
        @cd sub1 && make -s
        @cd sub2 && make -s
        @cd sub3 && make -s
        @cd sub4 && make -s
        @cd sub5 && make -s

        @echo "
		**** method 3 ****"
        @echo "In top dir"
        @for dir in $(SUB_DIRS); do 
                make -s -C $$dir; 
        done

.PHONY: log $(SUB_DIRS)
subdir:log $(SUB_DIRS)

log:
        @echo "SUB_DIRS: 
	$(SUB_DIRS)"
        @echo "
		**** method 1 ****"
        @echo "In top dir"

$(SUB_DIRS):
        @make -s -C $@

输出:

SUB_DIRS: 
        sub1 sub2 sub3 sub4 sub5

                **** method 1 ****
In top dir
        This is sub1
        This is sub2
        This is sub3
        This is sub4
        This is sub5
                **** method 2 ****
In top dir
        This is sub1
        This is sub2
        This is sub3
        This is sub4
        This is sub5

                **** method 3 ****
In top dir
        This is sub1
        This is sub2
        This is sub3
        This is sub4
        This is sub5

7、make -n 或者 make --just-print

可以用于调试Makefile的一些问题,此时make执行时只显示所要执行的命令,但不会真正的去执行这些命令

8、make -s 或者 make --slient

禁止所有执行命令的显示,就好像所有的命令行均使用"@"开始一样

9、.PHONY

使用这个修饰的目标,对应的命令会被无条件执行。而如果没有修饰的话,对于没有依赖文件的目标,只要目标文件不存在时才会执行定义的命令。

实例:

all:
        @echo "all is compiled"

.PHONY:clean
clean:
        @echo "clean is compiled"

体会下面的输出:

//此时当前目录只有一个Makefile文件
$ ls
Makefile

//执行make后,all作为第一个目标,由于当前目录下不存在all这个文件,所以all的命令被执行
$ make
all is compiled
$ make all
all is compiled

// clean由于是PHONY的,所以每次都执行
$ make clean
clean is compiled

// 然后在当前目录下分别创建all和clean两个文件
$ touch all
$ touch clean
$ ls
all  clean  Makefile

// 此时在编译all时,all的命令就不会执行了,因为当前目录已经存在all文件,并且all没有任何依赖文件
$ make
make: 'all' is up to date.
$ make all
make: 'all' is up to date.

// clean由于是PHONY的,命令无条件执行
$ make clean
clean is compiled

// 将all删除,发现all又可以执行了
$ rm all 
$ ls
clean  Makefile
$ make all
all is compiled

// clean由于是PHONY的,命令无条件执行
$ make clean
clean is compiled

如果在对Makefile做个修改:

all:clean
        @echo "all is compiled"

.PHONY:clean
clean:
        @echo "clean is compiled"

 即,将all的依赖文件设置为clean,那么此后,all也会被无条件执行了

$ ls
all  clean  Makefile
$ make all
clean is compiled
all is compiled
$ make
clean is compiled
all is compiled

10、模式匹配

  • %

当前目录下有如下几个文件:

$ ls
abc.A.abc  a.c  demo2.y  demo.sh  donglin.w  Makefile

Makefile内容如下:

all:demo demo2.x pengdonglin.w helloAworld
        @echo "all command"

%:%.c
        @echo generate $@ through $<

%:%.sh
        @echo generate $@ through $<

%.x:%.y
        @echo generate $@ through $<

hello%world:abc.%.abc
        @echo generate $@ through $<

peng%:%
        @echo generate $@ through $<

下面是运行结果:

generate demo through demo.sh
generate demo2.x through demo2.y
generate pengdonglin.w through donglin.w
generate helloAworld through abc.A.abc
all command

 11、make -p 或 make --print-data-base

可以查看在当前环境下make内置了那些规则

 12、 $(if $(KBUILD_VERBOSE:1=),@)  语法释疑

 https://blog.csdn.net/lcw_202/article/details/6656633

 等价于:

$(if $(patsubst %1,%,$(KBUILD_VERBOSE)),@)

也就是,如果KBUILD_VERBOSE为1,那么上面的表达式就是空,否则的话,就是@,这样后面的命令就会静默输出

 13、调用shell脚本

Makefile中的shell用法

makefile中的shell编程注意点

Shell脚本——make命令和Makefile文件

https://www.jb51.net/article/109797.htm

shell 文件内调用makefile文件

#!/bin/bash
cd ctemplate-2.1
./configure
sudo make -f install
cd ../
cd TemplateProcesser
make

说明:./configure文件是shell脚本文件,即shell内调用shell文件是很容易的;TemplateProcesser目录内有Makefile文件,调用方式,直接:make

makefile文件内调用shell脚本文件:

SHELL := /bin/bash
test:
@pwd
cd ./TemplateProcesser && pwd
sh ./build.sh
@pwd

说明:build.sh为shell脚本文件。

调用perl文件
/usr/bin/perl *.pl
调用python文件
/usr/bin/env *.py

 13、X:Y:Z

X := 1.o 2.o 3.o
Y := 4.o 5.o 6.o

all:$(X) $(Y)

X_c := $(patsubst %.o,%.c,$(X))
Y_c := $(patsubst %.o,%.c,$(Y))

$(X):%.o:%.c
        @echo "$@ <---- $<"

$(Y):%.o:%.c
        @echo "$@ <==== $<"

.PHONY:$(X_c) $(Y_c)

 输出:

1.o <---- 1.c
2.o <---- 2.c
3.o <---- 3.c
4.o <==== 4.c
5.o <==== 5.c
6.o <==== 6.c

===

原文地址:https://www.cnblogs.com/pengdonglin137/p/9678067.html