通用Makefile模板&说明

1、快速使用

  • 下载demo可以直接克隆Gitee仓库,文章末尾也会贴上Makefile文件

  • demo工程结构如下,对于用户的工程,只需将Makefile复制到工程根目录下,将.c文件和.h文件路径,添加到MakefileSRC_DIRSINC_DIRS参数中即可:

.
├── inc
│   └── print_func.h
├── main
│   └── main.c
├── Makefile
├── README.md
└── src
    └── print_func.c
  • 添加完工程的.c.h文件路径后,确认OUTPUT(目标文件)、DEBUG(调试等级)、DEFS(宏开关)、TOOLCHAIN_PREFIX(工具链前缀)等参数无误,在工程根目录下执行make可执行编译,执行make execute可运行目标,执行make clean可删除编译中间文件(build目录),执行make distclean可删除build目录及目标文件

2、Makefile文件详解

  • (1)目标文件

a)target文件的名称,编译中会在工程根目录下创建build存放中间文件,目标文件也会在build中生成

OUTPUT      := common-makefile.bin
  • (2)调试等级

a)Makefile中定义了DEBUG_CFLAGS/DEBUG_LDFLAGSRELEASE_CFLAGS/RELEASE_LDFLAGS宏,将一些常见的调试参数放了进去,然后做了个DEUBG开关,可以很方便地切换编译等级
b)以上参数会归入CFLAGSLDFLAGS2个变量,最终参加编译
c)一般编译调试将DEBUG打开,对外释放则关闭(否则目标文件中,会多出一些调试参数)

DEBUG       := YES

DEBUG_CFLAGS    := -Wall -Wno-format -MMD -DDEBUG -std=gnu99
RELEASE_CFLAGS  := -Wall -Wno-unknown-pragmas -Wno-format -MMD -O3 -std=gnu99
LIBS            := -lpthread -lrt

DEBUG_LDFLAGS   := -g
RELEASE_LDFLAGS :=

ifeq (YES, ${DEBUG})
  CFLAGS    += ${DEBUG_CFLAGS}
  LDFLAGS   := ${DEBUG_LDFLAGS}
else
  CFLAGS    += ${RELEASE_CFLAGS}
  LDFLAGS   := ${RELEASE_LDFLAGS}
endif
  • (3)编译宏开关

a)编译中用到的宏开关,可以统一添加到DEFS中,例如-DDEBUG_LEVEL=0
b)DEFS参数会归入CFLAGS变量,参加编译

DEFS        :=
CFLAGS      := ${DEFS}
  • (4)源文件和头文件路径

a)源文件和头文件路径,是需要重点修改的地方,用户自定义的所有.c.h文件,其路径要逐个添加到SRC_DIRSINC_DIRS变量中
b)其中第1个被添加的路径用:=添加(表示如果变量被定义过,则覆盖原定义),后续添加的路径用+=添加(表示如果变量被定义过,则追加定义)
c)对于demo工程的结构,有如下路径定义(CURDIRMakefile中的默认变量,表示文件当前所在目录,abspathMakefile内置函数,表示取绝对路径):

PROJ_DIR    := $(abspath ${CURDIR})
INC_DIRS    := ${PROJ_DIR}/inc
SRC_DIRS    := ${PROJ_DIR}/main
SRC_DIRS    += ${PROJ_DIR}/src
  • (5)源文件和头文件参数的展开

a)SRC_DIRS变量通过以下方式,展开成一个.c文件的列表,其中foreachwildcard都是Makefile内置的函数,前者表示遍历变量的每个元素,后者表示匹配目录下的特定文件(此处表示匹.c文件)
b)后续再将上面解析出的.c文件列表,依次转换成.o中间文件、.d依赖文件(生成到build目录下)

SRC_DIRS    := ${PROJ_DIR}/main
SRC_DIRS    += ${PROJ_DIR}/src

SRC_FILES   := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))
OBJ_FILES   := $(SRC_FILES:%.c=$(BUILD_DIR)/%.o)
DEP_FILES   := $(OBJ_FILES:%.o=%.d)

c)INC_DIRS变量,通过-I参数包含用户自定义的头文件。在编译过程中,寻找.c文件中包含的.h文件,都会到INC_DIRS中去查找(标准头文件则会到/usr/include路径下面查找)

INC_DIRS    := -I${PROJ_DIR}/inc
INC_DIRS    +=

@$(CC) $(CFLAGS) ${INC_DIRS} ${LDFLAGS} ${LIBS} ${EXTRA_LIBS} -c $< -o $@
  • (6)编译工具链相关

a)每种平台的编译工具链都不相同,但至少都包含了gccar工具,用户需要修改工具链的前缀
b)例如linux平台默认就是gccar,所以不需要加前缀,arm平台可能用arm-none-eabi-gcc等交叉工具链,前缀就是arm-none-eabi-

TOOLCHAIN_PREFIX    :=
CC                  := $(TOOLCHAIN_PREFIX)gcc
LD                  := $(TOOLCHAIN_PREFIX)gcc
AR                  := $(TOOLCHAIN_PREFIX)ar
  • (7)编译过程解析

需要花点时间,有空再补充

  • (8)cleandistcleanexecute

做一些清理工作,和一些执行动作

clean:
	-rm -rf $(BUILD_DIR)

distclean:
	-rm -rf ${BUILD_DIR} ./${OUTPUT}

execute :
	-cp ${BUILD_DIR}/${OUTPUT} ./
	./${OUTPUT}

3、demo工程

a)工程结构

.
├── inc
│   └── print_func.h
├── main
│   └── main.c
├── Makefile
├── README.md
└── src
    └── print_func.c

b)Makefile文件

#****************************************************************************
# target output
#****************************************************************************
OUTPUT      := common-makefile.bin

#****************************************************************************
# DEBUG can be set to YES to include debugging info, or NO otherwise
#****************************************************************************
DEBUG       := YES

#****************************************************************************
# PROFILE can be set to YES to include profiling info, or NO otherwise
#****************************************************************************
PROFILE     := NO

#****************************************************************************
# add your compile macro, such as: -DDEBUG_LEVEL=0
#****************************************************************************
DEFS        :=
CFLAGS      := ${DEFS}

#****************************************************************************
# add your source & header file path
#****************************************************************************
PROJ_DIR    := $(abspath ${CURDIR})
INC_DIRS    := -I${PROJ_DIR}/inc
INC_DIRS    +=
SRC_DIRS    := ${PROJ_DIR}/main
SRC_DIRS    += ${PROJ_DIR}/src

#****************************************************************************
# set your toolchain prefix
#****************************************************************************
TOOLCHAIN_PREFIX    :=
CC                  := $(TOOLCHAIN_PREFIX)gcc
LD                  := $(TOOLCHAIN_PREFIX)gcc
AR                  := $(TOOLCHAIN_PREFIX)ar

#****************************************************************************
# set your compile parameters
#****************************************************************************
DEBUG_CFLAGS    := -Wall -Wno-format -MMD -DDEBUG -std=gnu99
RELEASE_CFLAGS  := -Wall -Wno-unknown-pragmas -Wno-format -MMD -O3 -std=gnu99
LIBS            := -lpthread -lrt

DEBUG_LDFLAGS   := -g
RELEASE_LDFLAGS :=

ifeq (YES, ${DEBUG})
  CFLAGS    += ${DEBUG_CFLAGS}
  LDFLAGS   := ${DEBUG_LDFLAGS}
else
  CFLAGS    += ${RELEASE_CFLAGS}
  LDFLAGS   := ${RELEASE_LDFLAGS}
endif

ifeq (YES, ${PROFILE})
  CFLAGS    += -pg -O3
  LDFLAGS   += -pg
endif

#****************************************************************************
# lib files path
#****************************************************************************
LIB_DIRS    :=
EXTRA_LIBS  := $(foreach dir, $(LIB_DIRS), $(wildcard $(dir)/*.a))

#****************************************************************************
# start prepare operation
#****************************************************************************
BUILD_DIR   := ${PROJ_DIR}/build
SRC_FILES   := $(foreach dir, $(SRC_DIRS), $(wildcard $(dir)/*.c))
OBJ_FILES   := $(SRC_FILES:%.c=$(BUILD_DIR)/%.o)
DEP_FILES   := $(OBJ_FILES:%.o=%.d)

#****************************************************************************
# start compile operation
#****************************************************************************
${OUTPUT} : $(BUILD_DIR)/$(OUTPUT)
${BUILD_DIR}/${OUTPUT} : ${OBJ_FILES}
	@echo "Build $(notdir $@)..."
	@-mkdir -p ${@D}
	@$(CC) $^ ${CFLAGS} ${INC_DIRS} ${LDFLAGS} ${LIBS} ${EXTRA_LIBS} -o $@
-include ${DEP_FILES}

.PHONY : all clean distclean execute
all:
${BUILD_DIR}/%.o : %.c
	@echo "Build $(notdir $<)..."
	@-mkdir -p $(@D)
	@$(CC) $(CFLAGS) ${INC_DIRS} ${LDFLAGS} ${LIBS} ${EXTRA_LIBS} -c $< -o $@

clean:
	-rm -rf $(BUILD_DIR)

distclean:
	-rm -rf ${BUILD_DIR} ./${OUTPUT}

execute :
	-cp ${BUILD_DIR}/${OUTPUT} ./
	./${OUTPUT}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当编写一个通用Makefile 模板时,可以使用以下内容作为起点: ```makefile # 编译器 CC = gcc # 编译选项 CFLAGS = -Wall -Wextra -std=c99 # 目标文件夹 BUILD_DIR = build # 源文件夹 SRC_DIR = src # 源文件后缀 SRC_EXT = c # 获取所有源文件 SRCS = $(wildcard $(SRC_DIR)/*.$(SRC_EXT)) # 获取所有目标文件 OBJS = $(patsubst $(SRC_DIR)/%.$(SRC_EXT), $(BUILD_DIR)/%.o, $(SRCS)) # 目标可执行文件 TARGET = app # 默认目标 all: $(TARGET) # 编译目标文件 $(BUILD_DIR)/%.o: $(SRC_DIR)/%.$(SRC_EXT) mkdir -p $(BUILD_DIR) $(CC) $(CFLAGS) -c $< -o $@ # 构建可执行文件 $(TARGET): $(OBJS) $(CC) $(CFLAGS) $^ -o $@ # 清理生成的文件 clean: rm -rf $(BUILD_DIR) $(TARGET) .PHONY: all clean ``` 这个模板定义了以下几个变量和规则: - `CC`:编译器的名称,此处为 `gcc`,你可以根据需要修改为其他编译器。 - `CFLAGS`:编译选项,例如 `-Wall` 和 `-Wextra` 是常见的警告选项,`-std=c99` 指定了 C99 标准。 - `BUILD_DIR`:目标文件夹的名称,可以根据需要修改。 - `SRC_DIR`:源文件夹的名称,可以根据需要修改。 - `SRC_EXT`:源文件的扩展名,此处为 `c`,你可以根据需要修改为其他扩展名。 - `SRCS`:所有源文件的列表。 - `OBJS`:所有目标文件的列表。 - `TARGET`:可执行文件的名称。 - `all`:默认目标,依赖于 `$(TARGET)`。 - `$(BUILD_DIR)/%.o`:用于将源文件编译为目标文件的规则。 - `$(TARGET)`:构建可执行文件的规则。 - `clean`:清理生成的文件的规则。 使用该模板时,将源文件放置在 `src` 文件夹中,然后运行 `make` 命令即可编译生成可执行文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值