# Makefile for compiling TestCode
# 设置 GCC 编译器的路径(根据实际情况进行调整)
GCC_PATH := E:/gnu/gcc-arm-none-eabi-5_4-20160926/bin/
GCC := $(GCC_PATH)arm-none-eabi-gcc-5.4.1
AR := $(GCC_PATH)arm-none-eabi-ar
# 编译选项
CFLAGS := -Ofast -DKERNEL -D__ZEPHYR__=1 -c -g -std=c99
# 链接选项
CMACRO := -nostartfiles -nodefaultlibs -nostdlib -static -r
# 目录设置
DIR_INC := ./TestCode
DIR_SRC := ./TestCode
DIR_OBJ := ./Obj
OUTPUT := ./output
# Files to be compiled
SRC := $(wildcard $(DIR_SRC)/*.c)
OBJS := $(SRC:$(DIR_SRC)/%.c=$(DIR_OBJ)/%.o)
BUILD := $(OBJS:$(DIR_OBJ)/%.o=./%)
# 不自动删除 *.o 文件
.SECONDARY: $(OBJS)
# 目标:创建静态库
TARGET_STATIC := TestCode.a
$(TARGET_STATIC): $(OBJS)
@echo "Creating $(TARGET_STATIC)"
@mkdir -p $(OUTPUT)
@rm -rf $(OUTPUT)/*.*
@$(AR) -rc $(OUTPUT)/$(TARGET_STATIC) $(OBJS)
@cp $(DIR_INC)/TestCode.h $(OUTPUT)
# 目标:创建动态库
TARGET_SHARED := libTestCode.so
$(TARGET_SHARED): $(OBJS)
@echo "Creating $(TARGET_SHARED)"
@mkdir -p $(OUTPUT)
@rm -rf $(OUTPUT)/*.*
@$(GCC) $(CFLAGS) $(CMACRO) -shared -o $(OUTPUT)/$(TARGET_SHARED) $(OBJS)
@cp $(DIR_INC)/TestCode.h $(OUTPUT)
# 目标:编译每个 *.c 文件为 *.o 文件
$(DIR_OBJ)/%.o: $(DIR_SRC)/%.c
@echo + GCC $<
@mkdir -p $(DIR_OBJ)
@$(GCC) $(CFLAGS) $(CMACRO) -I $(DIR_INC) -c -o $@ $^
# 目标:编译所有源文件
all: $(BUILD)
# 目标:清理
.PHONY: clean
clean:
rm -rf $(OBJS) $(TARGET_STATIC) $(TARGET_SHARED)
详细解释Makefile:
-
# Makefile for compiling TestCode
:这是注释行,用于描述 Makefile 的用途。 -
GCC_PATH := E:/gnu/gcc-arm-none-eabi-5_4-20160926/bin/
:定义了一个变量GCC_PATH
,用于存储 GCC 编译器的路径。 -
GCC := $(GCC_PATH)arm-none-eabi-gcc-5.4.1
:定义了一个变量GCC
,它是完整的 GCC 编译器路径。 -
AR := $(GCC_PATH)arm-none-eabi-ar
:定义了一个变量AR
,它是静态库生成工具ar
的路径。 -
CFLAGS := -Ofast -DKERNEL -D__ZEPHYR__=1 -c -g -std=c99
:定义了一个变量CFLAGS
,它包含了编译选项,如优化级别、宏定义、只编译不链接、生成调试信息和使用 C99 标准。-Ofast
:启用最高级别的优化。-DKERNEL
:定义了一个宏KERNEL
。-D__ZEPHYR__=1
:定义了一个宏__ZEPHYR__
并赋值为 1。-c
:只编译源文件,不进行链接。-g
:生成调试信息。-std=c99
:使用 C99 标准。
-
CMACRO := -nostartfiles -nodefaultlibs -nostdlib -static -r
:定义了一个变量CMACRO
,它包含了链接选项,如不使用默认启动文件、不使用默认库和生成静态库。-nostartfiles
:不使用默认启动文件。-nodefaultlibs
:不使用默认库。-nostdlib
:不使用标准库。-static
:生成静态库。-r
:生成可重定位目标文件。
-
DIR_INC := ./TestCode
:定义了一个变量DIR_INC
,它存储了头文件目录的路径。 -
DIR_SRC := ./TestCode
:定义了一个变量DIR_SRC
,它存储了源文件目录的路径。 -
DIR_OBJ := ./Obj
:定义了一个变量DIR_OBJ
,它存储了目标文件目录的路径。 -
OUTPUT := ./output
:定义了一个变量OUTPUT
,它存储了输出目录的路径。 -
SRC = $(wildcard $(DIR_SRC)/*.c)
:使用通配符获取了源文件目录下所有的.c
文件列表,并将其存储在变量SRC
中。 -
OBJS := $(SRC:$(DIR_SRC)/%.c=$(DIR_OBJ)/%.o)
:将源文件列表中的每个.c
文件替换为目标文件列表中的.o
文件。 -
.SECONDARY: $(OBJS)
:这是一个特殊的目标,用于防止自动删除中间文件(.o
文件)。 -
TARGET_STATIC := TestCode.a
:定义了一个变量TARGET_STATIC
,它存储了静态库的名称。 -
$(TARGET_STATIC): $(OBJS)
:这是一个规则,表示生成静态库的目标文件是$(TARGET_STATIC)
,依赖于目标文件列表$(OBJS)
。 -
@echo "Creating $(TARGET_STATIC)"
:输出一条消息,表示正在创建静态库。 -
@mkdir -p $(OUTPUT)
:创建输出目录。 -
@rm -rf $(OUTPUT)/*.*
:删除输出目录中的所有文件。 -
@$(AR) -rc $(OUTPUT)/$(TARGET_STATIC) $(OBJS)
:使用ar
工具创建静态库。 -
@cp $(DIR_INC)/TestCode.h $(OUTPUT)
:将头文件复制到输出目录。 -
类似地,后面的规则和命令用
(1) Makefile基础 - 廖雪峰的官方网站. https://www.liaoxuefeng.com/wiki/1599771213037600/1599771942846497.
(2) GNU Make - Makefile 是如何解析的 - Runebook.dev. https://bing.com/search?q=makefile+%e9%80%90%e8%a1%8c%e8%a7%a3%e9%87%8a.
(3) GNU Make - Makefile 是如何解析的 - Runebook.dev. https://runebook.dev/zh/docs/gnu_make/parsing-makefiles.
(4) makefile 常规+进阶使用方法(附代码示例)_mkf文件-CSDN博客. https://blog.csdn.net/m0_66766911/article/details/123563601.