CC = gcc
LD = gcc
CFLAGS = -Wall -c -Dgliethttp -I../include -L lib_path
LDFLAGS = -lpthread
RCS = $(wildcard *.c source/*.c)
OBJS = $(patsubst %c, %o, $(SRCS))
TARGET = gliethttp
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
@$(LD) $(LDFLAGS) -o $@ $^
%o: %c
@$(CC) $(CFLAGS) -o $@ $<
clean:
@rm -f *.o $(TARGET)
1,特殊符号:四个特殊符号的意义@、$@、$^、$
@:这个符串通常用在“规则”行中,表示不显示命令本身,而只显示它的结果;否则会显示打印该命令信息
$@ --代表目标文件(target) ,如例子的:$(TARGET)
$^ --代表所有的依赖文件(components) ,@$(LD) $(LDFLAGS) -o $@ $^ ;$^代表$(OBJS)所有.o
$< --代表第一个依赖文件(components中最左边的那个),@$(CC) $(CFLAGS) -o $@ $< ;$< 代表依赖的%c.
2,编译文件和依赖文件的获取
RCS=$(wildcard *.c source/*.c)是为了找出目录和指定目录下所有的后缀为c和cpp的文件,这个功能也可以使用RCS=$(shell echo *.c)实现。
OBJ=$(patsubst %c, %o, $(SRCS))中是为了将所有的cpp文件的后缀替换为o文件,这个功能也可以通过CPP_OBJ=$(CPP_SRC:%.c=%.o)实现 ,替换引用规则,即用您指定的变量替换另一个变量。
它的标准格式是$(var:a=b) 或 ${var:a=b};
3,编译c后缀和cpp后缀文件的规则,后缀规则是一种老风格定义隐含规则的方式。新版本的make中使用模式规则取代了这种实现方式,模式规则和它相比更加清晰明了。现在版本保留它的原因只是为了能够兼容旧的makefile文件。
后缀规则有两种类型:“双后缀”和“单后缀”。
双后缀规则定义一对后缀:目标文件的后缀和依赖目标的后缀。它匹配所有后缀为指定目标后
缀的文件名。对于一个匹配的目标文件,它的依赖文件是这样形成:将目标文件中的后缀替换为依
赖文件的后缀之后得到。如:一个描述目标和依赖后缀的“.o”和“.c”的规则就等价于模式规则
“%o : %c”。
单后缀规则只定义一个后缀:此后缀是源文件的后缀。它可以匹配任何文件,其依赖文件名是
这样形成:将源文件后缀追加到目标文件名之后得到。例如:单后缀“.c”就等价于模式规则“% :
%.c”。
后缀规则的识别过程:比较make本身所定义的后缀和规则中出现的后缀,如果规则的目标中
只有一个可识别的后缀,则这个规则是一个“单后缀”规则;当规则的目标中有两个可识别的后缀
时,这个规则就是“双后缀”规则
.c.s:
@$(CC) $(CCFLAGS) -S $<
.s.o:
@$(AS) $(ASFLAGS) -o $*.o $<
.c.o:
@$(CC) $(CCFLAGS) -o $*.o -c $<
@echo [ $*.c Compiled ... ... ]
.cpp.o:
@$(C++) $(CCFLAGS) -o $*.o -c $<
@echo [ $*.cpp Compiled ... ... ]
.c.o和.cpp.o,是为了通配编译c后缀和cpp后缀文件的规则,
“.c”和“.o”都是make可识别的后缀。因此当定义了一个目标是“.c.o”的规则时。
make会将它作为一个双后缀规则来处理,它的含义是目标为“.o”文件、依赖为“.c”文件。下
边是使用后追规则定义的、编译.c源文件的规则:
.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
一个后缀规则依赖关系描述中不能包含依赖文件。否则,此规则将被作为一个普通规则对待。因此
规则:
.c.o: foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
它不是一个后缀规则。它是目标文件为“.c.o”、依赖文件是“foo.h”的普通规则。它不等价于规
则:
%.o: %.c foo.h
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
需要注意的是:没有命令行的后缀规则是没有任何意义的。它和没有命令行的模式规则不同,它并不
能取消之前使用后追规则定义的规则。它所实现的仅仅是将这个后缀规则作为目标加入到make的数据库中。
可识别的后缀指的是特殊目标“.SUFFIXES”的所有依赖的名字。通过给特殊目标“SUFFIXES”添加依赖来增加
一个可被识别的后缀:
.SUFFIXES: .hack .win
它所实现的功能是把后缀“.hack”和“.win”加入到可识别后缀列表的末尾。
如果需要重设默认所有的可识别后缀,可以这样来实现:
.SUFFIXES: #删除所有已定义的可识别后缀
.SUFFIXES: .c .o .h #重新定义
其过程是首先使用没有依赖的特殊目标“.SUFFIXES”来删除所有已定义的可识别后缀;之后再重新定义。
注意: make的“-r”或“-no-builtin-rules”可以清空所有已定义的可识别后缀。
5,去除路径:
file:$(notdir $(src))
6,增加依赖编译的方法:
CC := g++
LD := g++
CFLAGS += -Iinc
LDFLAGS +=
BINARY_PATH ?= out/bin
OBJECT_PATH ?= out/objs
TARGET ?= $(BINARY_PATH)/my-app.exe
SOURCES := $(wildcard src/*.cpp src/*/*.cpp src/*/*/*.cpp)
OBJECTS := $(addsuffix .o,$(addprefix $(OBJECT_PATH)/,$(basename $(notdir $(SOURCES)))))
DEPENDS := $(addsuffix .d,$(OBJECTS))
ifneq (v$(V),v1)
hide?=@
else
hide?=
endif
.PHONY : all clean hello prepare build post-build
all: hello prepare build post-build
clean: ;rm -rf out
hello: ;$(hide) echo ==== start, $(shell date) ====
prepare: $(BINARY_PATH) $(OBJECT_PATH)
post-build: ;$(hide) echo ==== done, $(shell date) ====
build: $(TARGET)
$(BINARY_PATH) $(OBJECT_PATH): ; mkdir -p $@
$(TARGET) : $(OBJECTS)
$(info LD $@)
$(hide) $(LD) -o $@ $(OBJECTS) $(LDFLAGS)
define make-cmd-cc
$2 : $1
$$(info CC $$<)
$$(hide) $$(CC) $$(CFLAGS) -MMD -MT $$@ -MF $$@.d -c -o $$@ $$<
endef
$(foreach afile,$(SOURCES),\
$(eval $(call make-cmd-cc,$(afile),\
$(addsuffix .o,$(addprefix $(OBJECT_PATH)/,$(basename $(notdir $(afile))))))))
-include $(DEPENDS)
完整的参考示例:
# This file use for compile file of upgtools
#
.PHONY: all clean
all:build_linux
CC=gcc
INC = ./
SRCS = \
a.c \
b.c \
c.c \
d.c \
e.c
OBJS := $(SRCS:%.c=%.o)
CFLAGS += --std=c99 -MMD -MP -MF $@.d -MT $@.d
CFLAGS += -Wall -g -I${INC}
%o:%c
@$(CC) -o $@ $(CFLAGS) -c $<
build_linux:${OBJS}
#@echo ${SRCS}
#@echo ${OBJS}
@$(CC) -o $@ $(CFLAGS) $^
clean:
@-rm *.o *.d build_linux -f
头文件关联编译:
-MP:生成头文件目标,避免更改后找不到目标出错;
-MMD:不带系统头文件,-MD 带系统头文件;这个D表示关联错误,编译错误后退出不生成;如果是擦看关联,去掉D和-c;
-MF :生成目标文件,后面跟生成的文件;
-MT:生成.d为目标的关联文件,需要处理%o.d:%c,并转化为%o:%c的关联处理;
DEPS:= $(SRCS:%.c=%.o.d出
%o:%c
#$(CC) -o $@ $(CFLAGS) -c $< -MMD -MP -MF $@.d -MT $@.d
######生成.o为目标的依赖文件######
$(CC) -o $@ $(CFLAGS) -c $< -MMD -MP -MF $@.d
###输出关联.d目标:-MT $@.d,需要处理%o.d:%c#####
%o.d:%c
@if [ -f $@ ];then \
$(CC) -MM -MP $< $(CFLAGS) -MF $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;\
rm $@.$$$$; fi;
###必须在目标之下####
-include ${DEPS}
常见用法:
makefile 条件判断有两种形式,一种是command内部的sh方式,一种是command外部的宏方式:
command内部的sh方式:遵循sh的判断方法,方法如下:
target:
if [ "X$(COPY_BACK_TARGET)" = "XY" ]; then \
cp -f target ../target_back; \
else \
cp -f target img/; \
fi
这种方式,if到fi整个内容为command;
command外部的宏方式:遵循宏的定义和方法,方法如下
ifeq/ifneq/ifdef/ifndef
else
endif
关键字 | 功能 |
---|---|
ifeq | 判断参数是否相等,相等为true,否则为false |
ifneq | 判断参数是否不相等,不相等为true,否则为false |
ifdef | 判断参数是否有值,有值为true,否则为false |
ifndef | 判断参数是否没有值,没有值为true,否则为false |
target:
ifeq ($(COPY_BACK_TARGET),y)
cp -rf target ../target_back(command):
else
cp -rf target img/(cmmand)
endif
这种方式,条件判断在command外部,条件的执行体才是command
执行体赋值方法:在主执行体前声明变量,且只能每次声明一个,在子执行体都可以应用。
.PHONY:p_test p_test1 p_test2 p_test3
p_test1:
@if [ "X${owner}" = "Xgchen" ];then \
cp -rf test1.bin ${targ_dir}; \
else \
cp -rf test2.bin ${targ_dir}; \; \
fi;
p_test2:
@echo " ${owner} ${date} test2!"
p_test3:
@echo " ${owner} ${date} test3!"
p_test:owner=gchen
p_test:date=20200201
p_test:targ_dir=test/gchen/20200201/
p_test:p_test1 p_test2 p_test3
@echo " ${owner} ${date} test!"
多个执行体执行相同的功能[解决在同一次make 执行相同目标后,第二次不执行的问题],问题如下:
function1:
echo "this function1"
p_test :
function1
p_test1 :
function1
test:p_test p_test1
只执行一次function1,解决每次都要支持function1的方法:
1,目标并列法:
.PHONY:p_test p_test1 p_test2 p_test3
p_test1 p_test2 p_test3:
call function1
call function2
call function3
p_test :p_test1 p_test2 p_test3
2,公共执行体定义法:
define function1
echo "this function1";
echo "this function2";
endef
p_test1 :
$(function1)
p_test2 :
$(function1)
条件执行注意:
define function1
echo "this function1";\
echo "this function1 second";[由执行体确定是否加“;”或“\”]
endef
.PHONY:p_test2
p_test2 :
@if [ "X_${selecte}" = "X_function1" ];then \
$(function1);\
else \
$(function2);\
fi
3,多模目标法:
%_test:
echo "this function $@";
test:1_test 2_test 3_test
价值参考:
https://blog.csdn.net/dlf1769/article/details/78997967/
Makefile 在执行体运用变量 ubi_count
ubi_count=$(shell python ubi_test.py -b 128K -e 124K -s 100M)
auto_partition:
@echo "auto partition"
@echo "ubi_count:${ubi_count}"
@mkfs.ubifs -r $(IMAGE_DIR)/datafs -F -m 2048 -e 126976 -c ${ubi_count} -o $(IMAGE_DIR)/dataubifs.img;
遍历目录结构编译方法:
ARCH ?= x86
ifeq ($(ARCH),x86)
CC=gcc
else
CC=arm-linux-gnueabihf-gcc
endif
TARGET=mp3
BUILD_DIR=build
SRC_DIR=module1 module2
INC_DIR=include
CFLAGS=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(patsubst)/*.h))
SOURCES=$(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))
OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)
$(BUILD_DIR)/$(TARGET):$(OBJS)
$(CC) $^ -o $@
$(BUILD_DIR)/%.o:%.c $(INCLUDES) | create_build
$(CC) -c $< -o $@ $(CFLAGS)
.PHONY:clean create_build
clean:
rm -r $(BUILD_DIR)
create_build:
mkdir -p $(BUILD_DIR)