Makefile是由target和命令构成的,最简单的Makefile:
build:
gcc test.c -o test
然后执行 make build
就会执行gcc这条命令,但是一般推荐先将源文件构建为对象文件,然后再统一编译为可执行文件
build: test.o
gcc test.o -o test
test.o:
gcc test.c -c
文件目标test.o是build伪目标依赖的文件,当执行build是会首先去执行文件目标的操作,所以:后面的称为目标的依赖
这种对多文件来说会更合适
build: test.o lib.o
gcc test.o lib.o -o test
test.o:
gcc test.c -c
lib.o:
gcc lib.c -c
除此之外,make编译时候可以指定很多Flags,例如
- CC:指定C语言编译器
- CXX:指定CPP语言编译器
- CFLAGS:指定C选项
- CXXFLAGS:指定CPP选项
- CPPFLAGS:指定编译过程中预处理选项
- LDFLAGS:指定链接器选项
make -p
可以查看所有预设的变量
除此之外也可以定义一些自定义变量,使用变量直接用$()即可。变量还可以使用?=,这个表示只有make时没有指定时才生效,否则不会执行到
有点值得注意,就是变量的值永远都是字符串,不需要用双引号括起来
DEBUG = 1
EXECUTABLE_NAME = test
CC = gcc
CFLAGS = -g -O0
COMPILER_CALL = $(CC) $(CFLAGS)
build: test.o lib.o
$(COMPILER_CALL) test.o lib.o -o $(EXECUTABLE_NAME)
test.o:
$(COMPILER_CALL) test.c -c
lib.o:
$(COMPILER_CALL) lib.c -c
makefile也支持条件语句,关键字有 ifeq
、ifneq
、ifdef
、ifndef
、else
、endif
DEBUG = 1
ifeq ($(DEBUG), 1)
CFLAGS = -g -O0
else
CFLAGS = -O3
endif
如果源文件很多的话,一个一个指定文件目标会很麻烦,所以就要通配符来简化操作
- $<:第一个依赖
- $@:文件目标名
- $^:所有依赖名
然后可以通过%来匹配文件名
EXECUTABLE_NAME = test
CC = gcc
CFLAGS = -g -O0
COMPILER_CALL = $(CC) $(CFLAGS)
C_OBJECTS = test.o lib.o
build: $(C_OBJECTS)
$(COMPILER_CALL) $(C_OBJECTS) -o $(EXECUTABLE_NAME)
%.o: %.c
$(COMPILER_CALL) $< -c -o $@
我们还可以更进一步,因为C_OBJECTS还不够自动化,没有自动识别.o文件自动添加,所以可以通过内置函数去实现
- $(wildcard <pattern...>):获取指定格式化的文件列表
- $(dir <names...>):获取文件所在目录
- $(suffix <names...>):获取文件后缀
- $(basename <names...>:去除文件后缀
- $(subst
, , :替换字符 - $(patsubst <src_pattern>,<dst_pattern>,
):按格式替换字符 - $(strip
):去除开头和结尾的空白字符
EXECUTABLE_NAME = test
CC = gcc
CFLAGS = -g -O0
COMPILER_CALL = $(CC) $(CFLAGS)
C_SOURCES = $(wildcard *.c)
C_OBJECTS = $(patsubst %.c, %.o, $(C_SOURCES))
build: $(C_OBJECTS)
$(COMPILER_CALL) $(C_OBJECTS) -o $(EXECUTABLE_NAME)
%.o: %.c
$(COMPILER_CALL) $< -c -o $@
在makefile有两种目标,一种是文件目标,比如test.o,还有一种是伪目标,例如build,对于伪目标最好通过.PHONY标记
.PHONY: build
如果需要创建目录,需要额外创建一个目标来处理
create:
@mkdir -p build
@会隐藏命令回显,而-p指的是如果目录不存在则创建,还有点值得注意的是,每行命令其实是拥有单独的shell环境,所以以下代码
create:
@mkdir -p build
@cd build
@touch test
这个create不会在build目录下创建文件,因为对于touch来说,当前目录并没有进入build,可以如下执行
create:
@mkdir -p build && cd build && touch test
标签:gcc,lib,Makefile,CALL,build,test,COMPILER
From: https://www.cnblogs.com/musing/p/18463119