系列文章目录
-前言
make工具会在必要时重新编译所有受改动影响的源文件。
make命令不仅仅用于编译程序,无论何时,当需要通过多个输入文件来生成输出文件时,都可以利用它来完成任务。它的其他用法还包括文档处理(例如针对troff或Tex文档)。
-make命令的3个常用选项
- -k:让make命令在发现错误时仍然继续执行,而不是遇到错误立即停止。作用:一次操作发现所有为编译成功的源文件。
- -n:让make命令输出将要执行的操作步骤,而不真正执行这些操作。
- -f <filename>:将哪个作为Makefile文件。若不适用该选项则默认指定makefile或Makefile
1. 依赖关系
规则:
<最终的文件名>:<apace/tab><file.o ... 文件之间用空格或tab隔开>
如:
myapp: main.o 2.o 3.o
main.o: main.c
2.o: 2.c
3.o: 3.c
# 一次创建多个文件
# 如果未指定一个all目标,则make命令将只创建它在文件Makefile中找到的第一个目标
all: myapp myapp.1
g++ -MM xx.cpp 显示出文件依赖
2. 规则
规则必须以tab开头,不能是空格,Makefile文件必须严格限制空格和tab的使用
简单Makefile文件示例:
# 未指定all则 myapp为最终输出 all: myapp
myapp: main.o 2.o 3.o
g++ -o myapp main.o 2.o 3.o
main.o: main.cpp
g++ -c main.cpp
2.o: 2.cpp
g++ -c 2.cpp
3.o: 3.cpp
g++ -c 3.cpp
-宏 / 变量
MACRONAME=value
使用宏:
$(MACRONAME)
makefile文件中的宏常被用于设置编译器的选项。在软件开发过程中将调试信息包含进去,对于发布的软件需要去除调试信息。
在调用make命令时在命令上给出宏定义,如make CC=c98
.命令行上的宏定义将覆盖makefile文件中的宏定义。宏定义中对空格敏感
eg:
all: myapp
# Which compiler
CC=g++
# Where are include files kept
INCLUDE =.
# Options for release
# CFLAGS=-O -Wall -ansi
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.cpp
$(CC) -I $(INCLUDE) $(CFLAGS) -c main.c
2.o: 2.c
$(CC) -I $(INCLUDE) $(CFLAGS) -c 2.c
3.o: 3.c
$(CC) -I $(INCLUDE) $(CFLAGS) -c 3.c
常用宏
MACRO | 定义 |
---|---|
$? | 当前目标所依赖的文件列表中比当前目标文件还要新的文件 |
$@ | 当前目标的名字 |
$< | 当前依赖文件的名字(第一个依赖) |
$* | 不包括后缀名的当前依赖文件的名字(第一个依赖) |
CC | gcc |
CXX | g++ |
$^ | 所有依赖 |
- -:告诉make命令忽略所有错误。如,想创建一个目录,但又想忽略任何错误(目录已存在)
- @:告诉make在执行某条命令前不要将该命令显示在标准输出上。如果想用echo命令给出一些说明信息,这个字符将非常有用。
all: myapp
# Which compiler
# Where to install
INSTDIR=~/root/vscode/Projs/Exe/
# Where are include files kept
INCLUDE=.
# Options for development
CFLAGS= -g -Wall -ansi
# Options for release
# CFLAGS= -O -Wall -ansi
myapp: main.o 2.o 3.o
$(CC) -o myapp main.o 2.o 3.o
main.o: main.cpp
$(CC) -I $(INCLUDE) $(CFLAGS) -c main.cpp
2.o: 2.cpp
$(CC) -I $(INCLUDE) $(CFLAGS) -c 2.cpp
3.o: 3.cpp
$(CC) -I $(INCLUDE) $(CFLAGS) -c 3.cpp
# 目标clean后无规则,则clean总会执行
clean:
-rm *.o
install: myapp
@if [ -d $(INSTDIR) ]; \
then \
cp myapp $(INSTDIR); \
chmod a+x $(INSTDIR)myapp; \
chmod og-w $(INSTDIR)myapp; \
echo "Installed in $(INSTDIR)";\
else \
echo "Sorry, $(INSTDIR) does not exist";
注:shell脚本中 ls && cd …; 代表ls执行成功后再执行cd … ; ls;cd …;代表按顺序执行不检查前一个命令是否执行成功。
输入make后clean和install不会执行需要输入make clean或make install显示得到让其执行
由于从make -p中可以看到内部由大量的规则,所以对于简单的项目只指定目标和依赖不写出规则,make也可正确的编译
-模式规则
见下
-用make管理库文件
略
-Makefile
Makefile
app:first.o second.o
gcc first.o second.o -o app
first.o: first.c
gcc first.c -c -o first.o
second.o: second.c
gcc second.c -c -o second.o
apt install make
make
添加变量后
dependence=first.o second.o
target=app
$(target):$(dependence)
$(CC) $^ -o $(target)
%.o:%.c
$(CC) -c $< -o $@
使用函数
src=$(wildcard *.c)
objs=$(patsubst %.c, %.o, $(src))
target=add
#规则1(主)必须是tab不能是空格
$(target):$(objs)
$(CC) $(objs) -o $(target) #-I ./include
%.o:%.c
$(CC) $< -c -o $@ -I ./include
# 规则2
.PHONY:clean #不让clean受touch clean影响
clean:
rm -f $(objs)
make #不会执行clean
make clean