6、实现baremetal编译¶
最终希望的 baremetal 目录应包括src、obj、output,其中src目录下源码和头文件可以随意放置。如下:
├── Makefile
├── obj
│ ├── board
│ │ └── prog1.o
│ ├── common
│ │ └── prog2.o
│ └── main.o
├── output
│ └── target
├── README.md
└── src
├── board
│ ├── prog1.c
│ └── prog1.h
├── common
│ ├── prog2.c
│ └── prog2.h
└── main.c
Makefile需要实现自动找到所有的 .c文件,编译成 .o 文件,并最后链接生成 binary 放入 output。这样可以在任意目录增加 c文件或者头文件,都会被编译进去。
基于上一个例子修改如下:
# ------------------------
# Generic Makefile
# ------------------------
# Project name
Target = target
# Compile command and flag
CC = gcc
CFLAG = -Wall
# Linker command and flag
LINKER = gcc
LFLAG =
# Dir
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = output
# Source directorys, find all source directory ,like src/board src/common
SRC_DIRS = $(shell find src -maxdepth 3 -type d)
# OBJ_DIRS, change src to obj, match the source directorys, like obj/board obj/common
OBJ_DIRS := $(foreach dir,$(SRC_DIRS),$(subst src,obj,$(dir)))
# INCLUDES, add source directorys to include, like -Isrc/board -Isrc/common
INCLUDES = $(foreach dir, $(SRC_DIRS),-I$(dir))
# Source files, c srouce files and asmeble source files. like src/board/test.c src/board/test.S
C_SRC += $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.c))
S_SRC := $(foreach dir,$(SRC_DIRS),$(wildcard $(dir)/*.S))
# OBJ files, object files. like obj/board/test.o obj/board/test.o
OBJ_S_FILES := $(foreach file,$(S_SRC),$(patsubst %.S,%.o,$(subst src,obj,$(file))))
OBJ_C_FILES := $(foreach file,$(C_SRC),$(patsubst %.c,%.o,$(subst src,obj,$(file))))
OBJ_FILES := $(OBJ_S_FILES) $(OBJ_C_FILES)
# 1. Create obj directorys and bin directory
# 2. Comple all OBJ_FILES, from .c .S to .o
# 3. Link all .o to binary target
$(BIN_DIR)/$(Target) : $(OBJ_DIRS) $(BIN_DIR) $(OBJ_FILES)
$(LINKER) -o $@ $(LFLAG) $(OBJ_FILES)
@echo "Linking complete!"
# Compile .c to .o
obj/%.o : src/%.c
@echo Compiling $< to $@
$(CC) $(CFLAG) $(INCLUDES) -c $< -o $@
PHONY: clean
clean :
rm -rf $(BIN_DIR) $(OBJ_DIR)
@echo "Cleanup complete!"
$(OBJ_DIRS):
mkdir -p $@
$(BIN_DIR):
mkdir -p $@
注解
大部分都通过注释说明了,其中有几个makefile专有命令说明下 。
$(foreach <var>,<list>,<text>)
names := a b c d
files := $(foreach n,$(names),$(n).o)
$(files)的值是“a.o b.o c.o d.o”
$(subst <from>,<to>,<text>)
把text中的from 替换为 to
$(subst ee,EE,feet on the street),
“fEEt on the strEEt”
$(patsubst %.c,%.o,x.c.c bar.c)
把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”