Makefile-ABC.
Makefile是组织编译的命令脚本文件-构建生成可执行文件的依赖关系树.
make
根据makefile的规则关系树, 构建出编译可执行程序.
# 目标: 目标依赖
# 命令
a.out: demo.c
gcc -o $@ $<
make指令
windows 环境
运行make -v
会出现:
'make' 不是内部命或外部命令, 也不是可执行的程序, 或批处理文件.
# 系统在环境变量中找不到 make 命令执行文件
解决方法:
- 找到
mingw
安装目录, 打开bin
目录, 找到mingw32-make.exe
- 将
mingw32-make.exe
将该文件重命名为make.exe
编译过程
Makefile
- 变量 使用
$(val)
获取val
的值
.PHONY: clean
CC=g++
BIN=exec
OBJS=AddTwoSum.o utils.o
$(BIN): $(OBJS)
@echo "start compiling..."
@echo $(CC)
$(CC) -o $(BIN) $(OBJS)
@echo "compile done"
AddTwoSum.o: AddTwoSum.cpp
$(CC) -c -o $@ $<
utils.o: utils.cpp
$(CC) -c -o $@ $<
clean:
rm -f $(BIN) $(OBJS)
- 条件复制
#条件赋值 ?=
#追加赋值 +=
CC = g++
CC ?= gcc
OBJS = AddTwoSum.o
OBJS += utils.o
echo:
@echo $(CC)
@echo $(OBJS)
- 立即变量和延迟变量
# 使用 := 赋值, 立即变量
# 使用 = 赋值, 延迟变量(关系变量)
a = 1
b = 2
val_a := $(a) # val_a=1 解析即赋值 立即解析赋值
val_b = $(b) # val_b的值随着b的变化而变化 绑定变量关系
a = 10
# b = 20
echo:
@echo $(val_a)
@echo $(val_b)
- 自动变量
# 常用自动变量
# $@ 目标
# $^ 所有依赖项
# $< 目标依赖项中的第一个
# $? 所有依赖项中被修改过的
.PHONY: clean
CC=g++
BIN=exec
OBJS=AddTwoSum.o utils.o
$(BIN): $(OBJS)
@echo "start compiling..."
@echo $(CC)
$(CC) -o $@ $^
@echo "compile done"
AddTwoSum.o: AddTwoSum.cpp
$(CC) -c -o $@ $<
utils.o: utils.cpp
$(CC) -c -o $@ $<
clean:
rm -f $(BIN) $(OBJS)
- 变量替换(模式匹配)
.PHONY: echo
SRC = demo.c demo1.c
OBJ = $(SRC:.c=.o)
OBJ1 = $(SRC:%.c=%.o)
echo:
@echo "SRC=$(SRC)"
@echo "OBJ=$(OBJ)"
@echo "OBJ1=$(OBJ1)"
# SRC=demo.c demo1.c
# OBJ=demo.o demo1.o
# OBJ1=demo.o demo1.o
- 环境变量
环境变量运行时载入makefile. 如果有相同命名的变量, 系统环境变量会被覆盖.
.PHONY: echo
CFLAGS = -g
echo:
@echo "CFLAGS = $(CFLAGS)"
@echo "SHELL = $(SHELL)"
@echo "MAKE = $(MAKE)"
@echo "HOSTNAME = $(HOSTNAME)"
# CFLAGS = -g
# SHELL = D:/sortwares/Git/usr/bin/sh.exe
# MAKE = D:/sortwares/mingw64/bin/make
# HOSTNAME = TX-PC0N4UHP
# 运行make 可以传值改变 export方式
# make HOSTNAME=CodeMax
# HOSTNAME = CodeMax
- 条件判断
# ifeq 判断相等
mode = debug
echo:
ifeq ($(mode),debug)
@echo "debug mode"
else
@echo "release mode"
endif
# ifneq
echo:
ifeq ($(mode),)
@echo "debug mode"
else
@echo "release mode"
endif
# ifdef
echo:
ifdef mode
@echo "debug mode"
else
@echo "release mode"
endif
- 函数
- 自定义函数 通过call调用
- make内嵌函数 直接make调用
- 函数与参数使用空格隔开 参数之间使用,隔开
# 内嵌函数
SRC = $(wildcard *.cpp)
echo:
@echo "SRC = $(SRC)"
# 自定义函数
define func
@echo "param1 = $(0)"
@echo "param = $(1)"
endef
echo:
$(call func, hello world)
- 遍历 foreach
$(foreach VAR, LIST, TEXT)
- VAR 将空格隔开的每一个选项赋值给VAR
- TEXT 处理VAR的脚本
- if 函数
# $(if(condition, then[, else]))
install__path =
install_path = $(if $(install__path), $(install__path), /usr/local)
echo:
@echo "$(install_path)"
- call 函数
# $(call def_func, <parm1>, <param2>...)
- error warning 函数
# $(error TEXT...)
# $(warning TEXT...)
example
# 如果当前目录中,正好有一个文件叫做clean,那么这个命令不会执行。
# 因为Make发现clean文件已经存在,就认为没有必要重新构建了,就不会执行指定的rm命令
# 就有了下面的伪声明
.PHONY: clean
# 编译Cpp
CC = g++
# 设置编译参数设置
# -g表示编译时候加入调试信息,
# -DDEBUG表示编译debug版本
# -W -Wall表示输出所有警告
# -fPIC是生成dll时候用的
CFLAGS = -g -DDEBUG -W -Wall -fPIC
# 头文件的目录为./ 当前目录
HEADER = -I./
ALGONAME = AddTwoSum
TOOLNAME = utils
OBJS= $(ALGONAME).o $(TOOLNAME).o
TARGET = algo
$(TARGET): $(OBJS)
@echo "start compiling..."
$(CC) $(CFLAGS) -o $@ $^
@echo "compile done"
$(ALGONAME).o: $(ALGONAME).cpp
$(CC) -c -o $@ $<
$(TOOLNAME).o: $(TOOLNAME).cpp
$(CC) -c -o $@ $<
clean:
rm -f $(TARGET) $(OBJS)