目录
前言
学习Linux的makefile
规范化配置
文件生成过程描述
编码和验证
前言
编译框架搭建遇到了些问题,我对makefile不是那么熟练,能力只停留在能看懂和能改上自己独立写个大工程的编译框架有困难,所以这期我们一起看linux内核的编译框架,边学习边仿制。
学习Linux的makefile
规范化配置
首先映入眼帘的是版本号和作者
ifeq ($(KBUILD_VERBOSE),1)quiet =Q =
elsequiet=quiet_Q = @
endif
-
ifeq ($(KBUILD_VERBOSE),1)
ifeq
是“if equal”的缩写,用于检查两个值是否相等。$(KBUILD_VERBOSE)
是一个变量,其值可能是1或0。这个变量通常在内核编译时被设置,表示是否启用verbose模式。
-
quiet =
- 这行代码设置了
quiet
变量为空字符串。当KBUILD_VERBOSE
为1时,我们不需要使用quiet_
前缀来抑制输出。
- 这行代码设置了
-
Q =
- 这行代码设置了
Q
变量为空字符串。在某些makefile中,Q
用于表示不回显命令,这样在执行make时,命令本身不会被显示在控制台上。
- 这行代码设置了
-
else
- 如果上面的条件不满足(即
KBUILD_VERBOSE
的值不是1),则执行else部分。
- 如果上面的条件不满足(即
-
quiet=quiet_
- 当不在verbose模式时,我们需要在输出中添加
quiet_
前缀,以抑制不必要的输出。
- 当不在verbose模式时,我们需要在输出中添加
-
Q = @
- 当不在verbose模式时,我们将
Q
设置为@
,这意味着命令本身将被回显到控制台上。这通常用于调试目的。
- 当不在verbose模式时,我们将
-
endif
- 结束if条件语句。
这段代码的目的是根据是否启用了verbose模式来控制make命令的输出和安静模式。如果verbose模式被启用(即KBUILD_VERBOSE
的值为1),则make命令将不会显示正在执行的命令;否则,它会显示命令。此外,为了抑制不必要的输出,要么使用空字符串(在verbose模式下)要么使用quiet_
前缀(在非verbose模式下)
他是和V配合使用的,达到控制生成日志数量的功能
ifeq ("$(origin V)", "command line")KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSEKBUILD_VERBOSE = 0
endif
如果命令行定义了这个值就从命令行拿,没定义就默认他是0
文件生成过程描述
那些花里胡哨的功能我们先不看先看核心的编译功能
%.s: %.c prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.i: %.c prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.c prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.lst: %.c prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.s: %.S prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.o: %.S prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
%.symtypes: %.c prepare scripts FORCE
$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
这里主要是两部分的内容,上面是对各种文件生成对应文件的描述,
%.s: %.c prepare scripts FORCE
: 规则描述如何从.c
文件生成.s
汇编文件。$(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
是执行的具体命令,其中$(Q)$(MAKE)
表示运行make工具,$(build)=$(build-dir)
指定构建目录,$(target-dir)$(notdir $@)
指定目标文件的目录和名称(不包括目录部分)。%.i: %.c prepare scripts FORCE
: 规则描述如何从.c
文件生成.i
预处理文件。%.o: %.c prepare scripts FORCE
: 规则描述如何从.c
文件生成.o
对象文件。%.lst: %.c prepare scripts FORCE
: 规则描述如何从.c
文件生成.lst
列表文件。%.s: %.S prepare scripts FORCE
: 规则描述如何从.S
汇编文件生成汇编文件。%.o: %.S prepare scripts FORCE
: 规则描述如何从.S
汇编文件生成.o
对象文件。%.symtypes: %.c prepare scripts FORCE
: 规则描述如何从.c
文件生成.symtypes
符号类型文件。
在每条规则中,prepare scripts FORCE
是一个伪目标,它的作用是确保在执行实际编译命令之前,先运行所有与这个伪目标相关的命令,例如准备脚本或清理之前的构建结果。这样可以确保构建的正确性和一致性。
下面是驱动模块的规则这里暂时不详细展开了
# Modules
/: prepare scripts FORCE
$(cmd_crmodverdir)
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir)
%/: prepare scripts FORCE
$(cmd_crmodverdir)
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir)
%.ko: prepare scripts FORCE
$(cmd_crmodverdir)
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir) $(@:.ko=.o)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
编码和验证
MAJOR = 0
MINOR = 0
PATCH = 0
NAME = tianyu.xin
OUTPUT = hardware_simulation
APP_SRCS = $(wildcard ../APP/src/*.c)
APP_OBJS = $(APP_SRCS:../APP/src/%.c=%.o)
SHOW_SRCS = $(wildcard ../show/src/*.c)
SHOW_OBJS = $(SHOW_SRCS:../show/src/%.c=%.o)
INCLUDE = -I../show/include -I../APP/include
CC = gcc
CFLAGS = -Wall -Werror $(INCLUDE)
# Aesthetic treatment
# log management
ifeq ("$(origin V)", "command line")
KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSE
KBUILD_VERBOSE = 0
endif
ifeq ($(KBUILD_VERBOSE),1)
quiet =
Q =
else
quiet=quiet_
Q = @
endif
all: $(OUTPUT)
# $(Q)$(CURDIR)
$(OUTPUT): $(APP_OBJS) $(SHOW_OBJS)
$(Q)$(CC) $(CFLAGS) $^ -o $@
%.o: ../APP/src/%.c
$(Q)$(CC) $(CFLAGS) -c $< -o $@
%.o: ../show/src/%.c
$(Q)$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OUTPUT) $(APP_OBJS) $(SHOW_OBJS)
FORCE:
$(Q)echo "Forcing target"
.PHONY: FORCE clean all
基本能实现个基础功能后面还需要优化