TODO 💤

源码

Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
export QUIET := @

# MAKEFLAG make 命令的参数
# -j <num> 指定并行编译的线程数,缺省值为1
# -k 如果某个目标无法被成功构建,则继续构建其他目标,而不是中止整个构建过程
# -s 静默模式,禁止输出命令执行过程中的信息
# -p 打印Makefile中的变量等信息
# -d 显示调试信息
# -t 更新目标文件的时间戳
# -n 仅显示需要执行的命令,而不实际执行他们
# -e 将环境变量覆盖到Makefile中
export MAKEFLAG := -s

include ./path.mk

IN_TARGET := $(RELEASE_LIB_PATH)/libcstudy.so
IN_TARGET_SRC_PATH := $(SRC_PATH)
IN_TARGET_OBJ_PATH := $(RELEASE_OBJ_PATH)

all: pre_build target_build end_build

pre_build:
@if [ ! -d $(RELEASE_PATH) ]; then \
mkdir -p $(RELEASE_PATH) -m 777; \
fi
@if [ ! -d $(RELEASE_INC_PATH) ]; then \
mkdir -p $(RELEASE_INC_PATH) -m 777; \
fi
@if [ ! -d $(RELEASE_SRC_PATH) ]; then \
mkdir -p $(RELEASE_SRC_PATH) -m 777; \
fi
@if [ ! -d $(RELEASE_OBJ_PATH) ]; then \
mkdir -p $(RELEASE_OBJ_PATH) -m 777; \
fi
@if [ ! -d $(RELEASE_LIB_PATH) ]; then \
mkdir -p $(RELEASE_LIB_PATH) -m 777; \
fi

include $(TARGET_FILE)

$(IN_TARGET):
@ar -rc -o $@ $^

end_build:
@echo "make: built all targets of $(RELEASE_PATH)"
@ls $(RELEASE_LIB_PATH)
@echo "=========================================================="

clean:
$(QUIET)rm -rf -v $(RELEASE_PATH)
$(QUIET)echo "clean done"
compile.mk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
ifeq ($(IN_COMP_SRC_DIR), )
$(error not define compile src dir)
endif

ifeq ($(IN_COMP_OBJ_DIR), )
$(error not define release obj dir)
endif

ifeq ($(IN_COMP_INC_DIR), )
$(error not define inc dir)
endif

CC := ${CROSS_COMPILE}gcc
CPP := ${CROSS_COMPILE}g++
CFLAGS := -fPIC -shared -Wall $(IN_COMP_INC_DIR)
CXXFLAGS := -fPIC -shared -Wall $(IN_COMP_INC_DIR)

COMPILE_SRC_DIR := $(abspath $(IN_COMP_SRC_DIR))
COMPILE_OBJ_DIR := $(abspath $(IN_COMP_OBJ_DIR))

COMP_CSRCS := $(wildcard $(COMPILE_SRC_DIR)/*.c)
COMP_CPPSRCS := $(wildcard $(COMPILE_SRC_DIR)/*.cpp)

# 不带路径的.c文件
COMP_CSRC_FILES := $(notdir $(COMP_CSRCS))

# 不带路径的.cpp文件
COMP_CPPSRC_FILES := $(notdir $(COMP_CPPSRCS))

SUB_CSRC_RELEASE = $(foreach file,$(COMP_CSRC_FILES), $(COMPILE_OBJ_DIR)/$(file))
SUB_CPPSRC_RELEASE = $(foreach file,$(COMP_CPPSRC_FILES), $(COMPILE_OBJ_DIR)/$(file))
# release/obj路径下的.o文件
SUB_OBJ_RELEASE += $(SUB_CSRC_RELEASE:.c=.o)
SUB_OBJ_RELEASE += $(SUB_CPPSRC_RELEASE:.cpp=.o)

# release/obj路径下的.d文件
SUB_DEP_RELEASE := $(SUB_OBJ_RELEASE:.o=.d)

all: $(SUB_OBJ_RELEASE)

vpath %.c $(COMPILE_SRC_DIR)
vpath %.cpp $(COMPILE_SRC_DIR)

# $@ 目标文件 $(@D) 文件路径中的路径部分,不以'/'结尾 $(@F)文件路径中的文件名部分
# $^ 所有的依赖文件
# $< 第一个依赖文件
# $* 不包括后缀名的当前依赖文件的名称
# $? 所有比目标新的依赖目标的集合,以空格分隔
# $+ 所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$(COMPILE_OBJ_DIR)/%.o: %.c
@echo "Compiling $(<F)"
@$(CC) $(CFLAGS) -MMD -MP -c $< -o $@

$(COMPILE_OBJ_DIR)/%.o: %.cpp
@echo "Compiling $(<F)"
@$(CPP) $(CXXFLAGS) -MMD -MP -c $< -o $@

sinclude $(SUB_DEP_RELEASE)
path.mk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# realpath 	获取文件名序列中存在的文件或目录的真实路径,可跨过软链接
# 并判断文件或目录是否存在,如果不存在则返回空
CUR_PATH := $(realpath $(shell pwd))
SRC_PATH := $(realpath $(CUR_PATH)/../code)

# abspath 获取文件名序列中存在的文件或目录的真实路径,可跨过软链接
# 不检查文件或目录是否存在
RELEASE_PATH := $(abspath $(CUR_PATH)/../release)
RELEASE_BIN_PATH := $(RELEASE_PATH)/bin
RELEASE_OBJ_PATH := $(RELEASE_PATH)/obj
RELEASE_LIB_PATH := $(RELEASE_PATH)/lib
RELEASE_API_PATH := $(RELEASE_PATH)/api

export TARGET_FILE := $(CUR_PATH)/target.mk
export COMPILE_FILE := $(CUR_PATH)/compile.mk
target.mk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 输入变量,若没定义则报错退出
ifeq ($(IN_TARGET), )
$(error not define compile target)
endif

ifeq ($(IN_TARGET_SRC_PATH), )
$(error not define compile target src dir)
endif

ifeq ($(IN_TARGET_OBJ_PATH), )
$(error not define compile target obj dir)
endif

# ' =' 整个makefile展开后,再决定变量的值,变量的值将会是整个Makefile中最后被指定的值
# ':=' 变量的值取决于它在Makefile中的位置,而不是整个Makefile展开后的最终值
# '+=' 追加赋值,旧值保持不变,将新值放到旧值后面,以空格隔开
# '?=' 当某变量前面已经定义赋值过,则不执行本次定义赋值,否则执行本次赋值

# source file root dir
TARGET_SRC_DIR := $(abspath $(IN_TARGET_SRC_PATH))

# object file root dir
TARGET_OBJ_DIR := $(abspath $(IN_TARGET_OBJ_PATH))

# 源码根目录及其所有的子目录路径
TARGET_SRC_DIRS := $(shell find $(TARGET_SRC_DIR) -maxdepth 6 -type d)

# 引入可能存在的过滤文件,过滤文件用于定义当前不进行编译的目录
# 不进行编译的目录使用 filter-y += $(dir_name) 定义,通过 'sinlude' 将变量引入
# include 包含的文件不存在时,会告警提示并退出
# -include 包含的文件不存在时,不会有错误提示、不会退出
# sinclude make程序的兼容项,可以使用 sinclude 来代替 -include
FILTER_FILES := $(foreach dir, $(TARGET_SRC_DIRS), $(dir)/filter.mk)
sinclude $(FILTER_FILES)

# 过滤掉的路径
FILTER_OUT_OBJ := $(foreach dir_name, $(filter-y), $(shell find $(TARGET_SRC_DIR) -name $(dir_name)))
FILTER_OUT_DIRS := $(foreach dir, $(FILTER_OUT_OBJ), $(shell find $(dir) -type d))

# 需要编译的路径
COMPILE_DIRS := $(abspath $(filter-out $(FILTER_OUT_DIRS), $(TARGET_SRC_DIRS)))

# 为每个路径前加上-I
COMPILE_INC_DIRS := $(foreach dir,$(COMPILE_DIRS), -I$(dir))
export IN_COMP_INC_DIR := $(COMPILE_INC_DIRS)

# 需要编译的源文件
COMPILE_CSRCS := $(foreach dir, $(COMPILE_DIRS), $(wildcard $(dir)/*.c))
COMPILE_CPPSRCS := $(foreach dir, $(COMPILE_DIRS), $(wildcard $(dir)/*.cpp))

# 取得所有源文件的目录,去除重复的目录
COMPILE_CSRC_DIRS := $(filter $(abspath $(dir $(COMPILE_CSRCS))), $(COMPILE_DIRS))

COMPILE_CPPSRC_DIRS := $(filter $(abspath $(dir $(COMPILE_CPPSRCS))), $(COMPILE_DIRS))
COMPILE_TARGET_DIRS += $(filter-out $(COMPILE_CPPSRC_DIRS), $(COMPILE_CSRC_DIRS))
COMPILE_TARGET_DIRS += $(COMPILE_CPPSRC_DIRS)

# 需要编译的路径的相对路径
COMPILE_RELATIVE_PATHS := $(foreach path, $(foreach dir,$(COMPILE_TARGET_DIRS), $(subst $(abspath $(TARGET_SRC_DIR)/../),, $(dir))), \
$(subst /$(notdir $(TARGET_SRC_DIR))/,/./, $(path)/))

# 取得所有目标文件的目录
BUILD_TARGET_DIRS := $(subst $(TARGET_SRC_DIR)/,$(TARGET_OBJ_DIR)/, $(COMPILE_TARGET_DIRS))

# 所有的源文件
COMPILE_CSRC_FILES := $(notdir $(COMPILE_CSRCS))
COMPILE_CPPSRC_FILES := $(notdir $(COMPILE_CPPSRCS))

BUILD_OBJ_FILES += $(foreach src, $(COMPILE_CSRC_FILES), \
$(foreach dir, $(COMPILE_DIRS), $(subst $(TARGET_SRC_DIR)/,$(TARGET_OBJ_DIR)/, \
$(firstword $(subst .c,.o,$(wildcard $(dir)/$(src)))))))

BUILD_OBJ_FILES += $(foreach src, $(COMPILE_CPPSRC_FILES), \
$(foreach dir, $(COMPILE_DIRS), $(subst $(TARGET_SRC_DIR)/,$(TARGET_OBJ_DIR)/, \
$(firstword $(subst .cpp,.o,$(wildcard $(dir)/$(src)))))))

target_build: target_check_dir target_build_objs $(IN_TARGET)

target_check_dir:
@if [ ! -d $(IN_TARGET_OBJ_PATH) ]; then \
mkdir -p $(IN_TARGET_OBJ_PATH) -m 777; \
fi
@for dir in $(BUILD_TARGET_DIRS); do \
if [ ! -d $$dir ]; then \
mkdir -p $$dir -m 777; \
fi; \
done

target_build_objs:
@printf "*******************************************\n"
@printf "* Compiles [%-12s/*] source file *\n" $(notdir $(TARGET_SRC_DIR))
@printf "*******************************************\n"
$(QUIET)for rpath in $(COMPILE_RELATIVE_PATHS); do $(MAKE) $(MAKEFLAG) -f $(COMPILE_FILE) \
IN_COMP_SRC_DIR=$(TARGET_SRC_DIR)$${rpath} \
IN_COMP_OBJ_DIR=$(TARGET_OBJ_DIR)$${rpath} \
|| exit $$? ; done
@printf "*******************************************\n"
@printf "* Completion [%-12s/*] object file *\n" $(notdir $(TARGET_OBJ_DIR))
@printf "*******************************************\n"

$(IN_TARGET):$(BUILD_OBJ_FILES)
self_section_def.lds
1
2
3
4
5
6
SECTIONS {
.self_section ALIGN(8) :{
KEEP (*(SORT(.self_section_*)));
}
}
INSERT BEFORE .rodata;