Make
make是工具,makefile是个文件;
make
make -f md ;指定make的输入文件
make -v ;输出版本号
make -n ;只输出命令,不执行命令
make -s ;只执行命令 ,不显示具体命令
make -w ;显示执行前执行后的路径
make -C ;指定makefile所在的目录
make -h ;显示帮助
makefile中的变量
系统变量
$* 不包括扩展名的目标文件名称
$+ 所有的以来文件,以空格分隔
$< 表示规则中的第一个条件
$? 所有时间戳比目标文件晚的依赖文件,以空格分隔
$@ 目标文件的完整名称
$^ 所有不重复的依赖文件,以空格分隔
$% 如果目标是归档成员,则该变量表示目标的归档成员名称
举例:
a.o :a.c
gcc -c $^ -o $@
自定义变量
TARGET=main ;
注意注意
示例1:
#makefile文件
x=y
x=$(x)1
a:
echo $(x)
运行结果(报错)
book@100ask:~/make_text$ make -f ma
ma:3: *** Recursive variable 'x' references itself (eventually). Stop.
示例2:
#makefile文件
x=y
x:=$(x)1
a:
echo $(x)
#/************运行结果*************/
book@100ask:~/make_text$ make -f ma
echo y1
y1
示例3
x=1
y=$(x)
x=2
a:
echo $(y)
运行结果:
book@100ask:~/make_text$ make -f ma
echo 2
2
两种变量赋值的方法
= 赋值,但是用终值,就是不管变量调用写在赋值前还是赋值后,调用时都是终值
:= 也是赋值 ,但是只受当前行及之前代码的影响,而不会受后面赋值的影响
makefile中的伪目标
.PHONY:a b #声明为伪目标后,makefile将不会判断目标是否存在或该目录是否需要更新
模式匹配
%.o:%.c #采用通配符%
wildcard #$(wildcard ./*.c) 获取当前目录下所有的.c文件
patsubst #$(patsubst %.cpp,%.o, ./*.^cpp)将对应的cpp文件名替换成.o文件名
.PHONY :clean
BY=gcc
TARGET=main
OBJ=$(patsubst %.c,%.o,$(wildcard ./*.c))
$(TARGET):$(OBJ)
$(BY) $^ -o $@
%.o:%.c
$(BY) -c $^ -o $@
clean:
rm -rf $(OBJ)
运行结果
book@100ask:~/make_text$ make clean
rm -rf ./a.o ./c.o ./main.o ./b.o
book@100ask:~/make_text$ make
gcc -c a.c -o a.o
gcc -c c.c -o c.o
gcc -c main.c -o main.o
gcc -c b.c -o b.o
gcc a.o c.o main.o b.o -o main
book@100ask:~/make_text$ ./main
funa()
funb()
func()
公共头文件
include /home/book/Makefile #调用公共makefile
举例
公共Makefile
ifndef TARGET
TARGET:=main
endif
.PHONY :clean
BY=gcc
OBJ=$(patsubst %.c,%.o,$(wildcard ./*.c))
OBJ:=$(OBJ)
$(TARGET):$(OBJ)
$(BY) $^ -o $@
clean:
rm -rf $(OBJ)
私有makefile
TARGET=main
include ../Makefile
运行结果
book@100ask:~/make_text$ make clean
rm -rf ./a.o ./c.o ./main.o ./b.o
book@100ask:~/make_text$ make
cc -c -o a.o a.c
cc -c -o c.o c.c
cc -c -o main.o main.c
\cc -c -o b.o b.c
gcc a.o c.o main.o b.o -o main
book@100ask:~/make_text$ ./main
funa()
funb()
func()
Makefile中调用shell命令
x=$(shell pwd)
y=1
z=$x
a:
echo $(x)
echo $z
if [ 1 -eq $y ];then echo eq;fi;
运行结果
book@100ask:~/make_text$ make -f ma
echo /home/book/make_text
/home/book/make_text
echo /home/book/make_text
/home/book/make_text
if [ 1 -eq 1 ];then echo eq;fi;
eq
makefile 中的嵌套调用
001和002文件夹内容
book@100ask:~$ cat 001/makefile
a:
echo a
book@100ask:~$ cat 002/makefile
b:
echo b
另一个文件夹中的makefile:
DIR=001 002
.PHONY : all $(DIR)
all:$(DIR)
echo done
$(DIR):
make -C $@
clean:
make -C $(DIR)
运行结果:
book@100ask:~$ make -f ma
make -C 001
make[1]: Entering directory '/home/book/001'
echo a
a
make[1]: Leaving directory '/home/book/001'
make -C 002
make[1]: Entering directory '/home/book/002'
echo b
b
make[1]: Leaving directory '/home/book/002'
echo done
条件判断
ifdef ;判断变量是否存在
ifndef ;判断变量是否不存在
ifeq ;判断是否相等
ifneq ;判断是否不相等
x=1
ifneq ($(x),1)
a=1
else
a=0
ifneq ($(x),2)
c=1
else
c=0
endif
endif
ifndef x
b=1
else
b=0
endif
a:
echo $(b)
echo $(a)
echo $(c)
运行结果:
book@100ask:~/make_text$ make -f ma
echo 0
0
echo 0
0
echo 1
1
注意 ifeq 没有elif搭配
循环
DIR=001 002 003
a:
echo $(foreach v,$(DIR),$(v))
运行结果:
book@100ask:~/make_text$ make -f ma
echo 001 002 003
001 002 003
除了这种循环方式,还可以使用shell命令循环
函数
#自定义函数,不是真正的函数,本质上是多行命令,放在外面
#没有返回值
#$(0)指的是函数名,$(1)指的是传进第一个参数
define FUNC1
echo $(1) $(2) $(3)
echo func1
endef
all:
$(call FUNC1,abc,def)
make install
001_text.c 文件
#include "stdio.h"
int main()
{
int i=0;
for(;i<10;++i){
printf("001_run%d\n",i);
}
return 0;
}
makefile文件
TARGET:=001_text
SOURCE:=$(wildcard ./*.c)
OBJ:=$(patsubst %.c,%.o,$(SOURCE))
bin:=/usr/local/bin/
path:=/home/book/make_text/002
START:=start
STOP:=stop
LOG:=$(path)/log.txt
.PHONY: clean install clean_log
$(TARGET):$(OBJ)
gcc $^ -o $@
%.o: %.c
gcc -c $^ -o $@
install:$(TARGET)
if [ -d $(path) ]; \
then echo $(path) exist; \
else \
echo $(path) not exist; \
mkdir $(path); \
fi; \
touch $(LOG); \
chmod a+rwx $(LOG);\
echo "$(TARGET)>$(LOG) & " > $(path)/$(START); \
echo "killall $(TARGET)" > $(path)/$(STOP);\
chmod +x $(path)/$(STOP);\
chmod +x $(path)/$(START);\
cp $(TARGET) $(path)/$(TARGET); \
sudo ln -sv $(path)/$(START) $(bin); \
sudo ln -sv $(path)/$(STOP) $(bin); \
sudo ln -sv $(path)/$(TARGET) $(bin); \
clean:
sudo rm -rf $(TARGET) $(OBJ) $(bin)/$(TARGET) $(path)/$(TARGET) $(path)/$(START) $(path)/$(STOP) $(bin)/$(START) $(bin)/$(STOP)
clean_log:
rm -f $(LOG)
运行结果:
book@100ask:~/make_text/001$ ls /usr/local/bin
001_text start stop
book@100ask:~/make_text/001$ start
book@100ask:~/make_text/001$ cat ../002/log.txt
001_run0
001_run1
001_run2
001_run3
001_run4
001_run5
001_run6
001_run7
001_run8
001_run9
-rf $(TARGET) $(OBJ)
(
b
i
n
)
/
(bin)/
(bin)/(TARGET)
(
p
a
t
h
)
/
(path)/
(path)/(TARGET)
(
p
a
t
h
)
/
(path)/
(path)/(START)
(
p
a
t
h
)
/
(path)/
(path)/(STOP)
(
b
i
n
)
/
(bin)/
(bin)/(START)
(
b
i
n
)
/
(bin)/
(bin)/(STOP)
clean_log:
rm -f $(LOG)
运行结果:
```shell
book@100ask:~/make_text/001$ ls /usr/local/bin
001_text start stop
book@100ask:~/make_text/001$ start
book@100ask:~/make_text/001$ cat ../002/log.txt
001_run0
001_run1
001_run2
001_run3
001_run4
001_run5
001_run6
001_run7
001_run8
001_run9