【PA2】Read a Makefile

这里是NJU的PA2.2里面要求读懂的Makefile,是abstract-machine的。这里会放一些与读懂这个Makefile有关的知识。
下面是用ChatGPT解释的代码。只做大致的了解,写Makefile的时候还是要具体去看官方手册。
官方手册:make.pdf
(gnu.org)

# Makefile for AbstractMachine Kernels and Libraries

### *Get a more readable version of this Makefile* by `make html` (requires python-markdown)
html:
    cat Makefile | sed 's/^\([^#]\)/    \1/g' | markdown_py > Makefile.html
.PHONY: html


    ## 1. Basic Setup and Checks

    ## 创建一个裸机内核镜像
    ### Default to create a bare-metal kernel image
    ifeq ($(MAKECMDGOALS),)
      MAKECMDGOALS  = image
      .DEFAULT_GOAL = image
    endif

    ### Override checks when `make clean/clean-all/html`
    ifeq ($(findstring $(MAKECMDGOALS),clean|clean-all|html),)

    ### Print build info message
    $(info # Building $(NAME)-$(MAKECMDGOALS) [$(ARCH)])

    ### Check: environment variable `$AM_HOME` looks sane
    ifeq ($(wildcard $(AM_HOME)/am/include/am.h),)
      $(error $$AM_HOME must be an AbstractMachine repo)
    endif

    ### Check: environment variable `$ARCH` must be in the supported list
    ARCHS = $(basename $(notdir $(shell ls $(AM_HOME)/scripts/*.mk)))
    ifeq ($(filter $(ARCHS), $(ARCH)), )
      $(error Expected $$ARCH in {$(ARCHS)}, Got "$(ARCH)")
    endif

    ### Extract instruction set architecture (`ISA`) and platform from `$ARCH`. Example: `ARCH=x86_64-qemu -> ISA=x86_64; PLATFORM=qemu`
    ARCH_SPLIT = $(subst -, ,$(ARCH))
    ISA        = $(word 1,$(ARCH_SPLIT))
    PLATFORM   = $(word 2,$(ARCH_SPLIT))

    ### Check if there is something to build
    ifeq ($(flavor SRCS), undefined)
      $(error Nothing to build)
    endif

    ### Checks end here
    endif

    ## 2. General Compilation Targets

    ### Create the destination directory (`build/$ARCH`)
    WORK_DIR  = $(shell pwd)
    DST_DIR   = $(WORK_DIR)/build/$(ARCH)
    $(shell mkdir -p $(DST_DIR))

    ### Compilation targets (a binary image or archive)
    IMAGE_REL = build/$(NAME)-$(ARCH)
    IMAGE     = $(abspath $(IMAGE_REL))
    ARCHIVE   = $(WORK_DIR)/build/$(NAME)-$(ARCH).a

    ### Collect the files to be linked: object files (`.o`) and libraries (`.a`)
    OBJS      = $(addprefix $(DST_DIR)/, $(addsuffix .o, $(basename $(SRCS))))
    LIBS     := $(sort $(LIBS) am klib) # lazy evaluation ("=") causes infinite recursions
    LINKAGE   = $(OBJS) \
      $(addsuffix -$(ARCH).a, $(join \
        $(addsuffix /build/, $(addprefix $(AM_HOME)/, $(LIBS))), \
        $(LIBS) ))

    ## 3. General Compilation Flags

    ### (Cross) compilers, e.g., mips-linux-gnu-g++
    AS        = $(CROSS_COMPILE)gcc
    CC        = $(CROSS_COMPILE)gcc
    CXX       = $(CROSS_COMPILE)g++
    LD        = $(CROSS_COMPILE)ld
    AR        = $(CROSS_COMPILE)ar
    OBJDUMP   = $(CROSS_COMPILE)objdump
    OBJCOPY   = $(CROSS_COMPILE)objcopy
    READELF   = $(CROSS_COMPILE)readelf

    ### Compilation flags
    INC_PATH += $(WORK_DIR)/include $(addsuffix /include/, $(addprefix $(AM_HOME)/, $(LIBS)))
    INCFLAGS += $(addprefix -I, $(INC_PATH))

    ARCH_H := arch/$(ARCH).h
    CFLAGS   += -O2 -MMD -Wall -Werror $(INCFLAGS) \
                -D__ISA__=\"$(ISA)\" -D__ISA_$(shell echo $(ISA) | tr a-z A-Z)__ \
                -D__ARCH__=$(ARCH) -D__ARCH_$(shell echo $(ARCH) | tr a-z A-Z | tr - _) \
                -D__PLATFORM__=$(PLATFORM) -D__PLATFORM_$(shell echo $(PLATFORM) | tr a-z A-Z | tr - _) \
                -DARCH_H=\"$(ARCH_H)\" \
                -fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \
                -Wno-main -U_FORTIFY_SOURCE
    CXXFLAGS +=  $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptions
    ASFLAGS  += -MMD $(INCFLAGS)
    LDFLAGS  += -z noexecstack

    ## 4. Arch-Specific Configurations

    ### Paste in arch-specific configurations (e.g., from `scripts/x86_64-qemu.mk`)
    -include $(AM_HOME)/scripts/$(ARCH).mk

    ### Fall back to native gcc/binutils if there is no cross compiler
    ifeq ($(wildcard $(shell which $(CC))),)
      $(info #  $(CC) not found; fall back to default gcc and binutils)
      CROSS_COMPILE :=
    endif

    ## 5. Compilation Rules

    ### Rule (compile): a single `.c` -> `.o` (gcc)
    $(DST_DIR)/%.o: %.c
        @mkdir -p $(dir $@) && echo + CC $<
        @$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $(realpath $<)

    ### Rule (compile): a single `.cc` -> `.o` (g++)
    $(DST_DIR)/%.o: %.cc
        @mkdir -p $(dir $@) && echo + CXX $<
        @$(CXX) -std=c++17 $(CXXFLAGS) -c -o $@ $(realpath $<)

    ### Rule (compile): a single `.cpp` -> `.o` (g++)
    $(DST_DIR)/%.o: %.cpp
        @mkdir -p $(dir $@) && echo + CXX $<
        @$(CXX) -std=c++17 $(CXXFLAGS) -c -o $@ $(realpath $<)

    ### Rule (compile): a single `.S` -> `.o` (gcc, which preprocesses and calls as)
    $(DST_DIR)/%.o: %.S
        @mkdir -p $(dir $@) && echo + AS $<
        @$(AS) $(ASFLAGS) -c -o $@ $(realpath $<)

    ### Rule (recursive make): build a dependent library (am, klib, ...)
    $(LIBS): %:
        @$(MAKE) -s -C $(AM_HOME)/$* archive

    ### Rule (link): objects (`*.o`) and libraries (`*.a`) -> `IMAGE.elf`, the final ELF binary to be packed into image (ld)
    $(IMAGE).elf: $(OBJS) am $(LIBS)
        @echo + LD "->" $(IMAGE_REL).elf
        @$(LD) $(LDFLAGS) -o $(IMAGE).elf --start-group $(LINKAGE) --end-group

    ### Rule (archive): objects (`*.o`) -> `ARCHIVE.a` (ar)
    $(ARCHIVE): $(OBJS)
        @echo + AR "->" $(shell realpath $@ --relative-to .)
        @$(AR) rcs $(ARCHIVE) $(OBJS)

    ### Rule (`#include` dependencies): paste in `.d` files generated by gcc on `-MMD`
    -include $(addprefix $(DST_DIR)/, $(addsuffix .d, $(basename $(SRCS))))

    ## 6. Miscellaneous

    ### Build order control
    image: image-dep
    archive: $(ARCHIVE)
    image-dep: $(OBJS) am $(LIBS)
        @echo \# Creating image [$(ARCH)]
    .PHONY: image image-dep archive run $(LIBS)

    ### Clean a single project (remove `build/`)
    clean:
        rm -rf Makefile.html $(WORK_DIR)/build/
    .PHONY: clean

    ### Clean all sub-projects within depth 2 (and ignore errors)
    CLEAN_ALL = $(dir $(shell find . -mindepth 2 -name Makefile))
    clean-all: $(CLEAN_ALL) clean
    $(CLEAN_ALL):
        -@$(MAKE) -s -C $@ clean
    .PHONY: clean-all $(CLEAN_ALL)

1. Basic Setup and Checks

Default to create a bare-metal kernel image

MAKECMDGOALS

Make会将特殊变量MAKECMDGOALS设置为您在命令行上指定的目标列表。如果在命令行上没有指定目标,则此变量为空。请注意,这个变量只应在特殊情况下使用。
适当使用的一个例子是在清理规则中避免包含.d文件(参见第4.13节[自动先决条件],第42页),这样make就不会创建这些文件,只是立即删除它们。
换句话说,MAKECMDGOALS变量可以用于根据命令行上指定的目标来执行特定的操作或规则。在清理规则中,您可以检查MAKECMDGOALS变量,以决定是否需要清理.d文件。这样可以避免不必要的创建和删除.d文件的开销。
在这里插入图片描述

这段代码片段展示了一个示例的
Makefile 开头部分。 首先,定义了一个变量sources,其中包含了要编译的源文件列表,例如 foo.cbar.c。接下来,使用条件语句 ifeq 来检查 MAKECMDGOALS 变量中是否包含了clean 目标。MAKECMDGOALS 变量存储了在命令行上指定的目标列表。 如果MAKECMDGOALS 中不包含 clean 目标,那么会执行 include语句。这里使用了变量替换和模式替换,将 sources 中的 .c 后缀替换为.d 后缀,然后包含这些 .d 文件。.d文件通常是由编译器生成的依赖关系文件,用于跟踪源文件之间的依赖关系。通过这段代码,可以在编译程序之前自动包含并处理依赖关系文件,以确保在源文件或头文件发生更改时,相关的文件会被重新编译。这有助于提高构建的效率和准确性。

ifeq ($(MAKECMDGOALS),)
  MAKECMDGOALS  = image
  .DEFAULT_GOAL = image
endif

如果MAKECMDGOALS 变量为空,即没有在命令行上指定目标,则会执行里面的代码,将MAKECMDGOALS、.DEFAULT_GOAL都指向image这个镜像。
### Override checks when make clean/clean-all/html

ifeq ($(findstring $(MAKECMDGOALS),clean|clean-all|html),)

也是说我们输入make clean/make clean-all/makehtml,可以避免在执行清理或生成 HTML等特定操作时,执行不必要的检查(也就是下面的Check)或设置。

Printbuild info message

pass,没啥好说的。

Check: environment variable$AM_HOME looks sane

ifeq ($(wildcard $(AM_HOME)/am/include/am.h),)
  $(error $$AM_HOME must be an AbstractMachine repo)
endif

用于检查环境变量 $AM_HOME 是否指向 Abstract-Machine 仓库

Check:environment variable $ARCH must be in the supported list

检查是否是支持的ISA

Extract instruction set architecture (ISA)and platform from $ARCH. Example:

ARCH=x86_64-qemu -> ISA=x86_64; PLATFORM=qemu没啥好说的,也就是做了一点类似字符串的截取的工作。

Check if there

is something to build 检查是否需要build。

2. General Compilation Targets

Create the destination directory (build/$ARCH)

生成目标的文件路径,创建文件。 ### Compilation targets (a binary image
or archive)

IMAGE_REL = build/$(NAME)-$(ARCH)
IMAGE     = $(abspath $(IMAGE_REL))
ARCHIVE   = $(WORK_DIR)/build/$(NAME)-$(ARCH).a

这段代码片段定义了编译目标的变量。 首先,定义了一个变量IMAGE_REL,它表示编译生成的二进制镜像的相对路径。路径由build/$(NAME)(名称变量)和 $(ARCH)(架构变量)组成。接下来,定义了一个变量 IMAGE,它使用 abspath 函数将 IMAGE_REL的相对路径转换为绝对路径。这样可以确保在不同的工作目录中也能正确地引用生成的二进制镜像。最后,定义了一个变量 ARCHIVE,它表示编译生成的静态库的路径。路径由$(WORK_DIR)(工作目录变量)、build/$(NAME)$(ARCH) 组成。通过这些变量,可以方便地引用编译生成的二进制镜像和静态库的路径,以便后续的操作和使用。
生成了一个库文件。
在这里插入图片描述

Collect the files to be linked: object files (.o) and libraries (.a)

这段代码片段用于收集需要链接的文件,包括目标文件(.o)和库文件(.a)。首先,定义了一个变量 OBJS,它使用 addprefixaddsuffixbasename 函数来生成目标文件的路径。addprefix函数用于在每个文件名前添加目标目录的路径 $(DST_DIR)addsuffix函数用于在每个文件名后添加 .o 后缀,basename函数用于去除源文件的扩展名。通过这些函数的组合,可以生成目标文件的完整路径。接下来,使用 sort 函数对变量 LIBS 进行排序,并将 amklib添加到 LIBS 变量中。这里使用了 := 运算符,表示对 LIBS变量进行延迟求值,避免无限递归的问题。 最后,定义了一个变量LINKAGE,它包含了需要链接的文件列表。这个列表由目标文件 $(OBJS)和库文件组成。库文件的路径由 $(AM_HOME)$(LIBS)-$(ARCH).a组合而成。通过 join 函数和字符串操作,可以生成每个库文件的完整路径。通过这些变量,可以方便地收集需要链接的目标文件和库文件,并在链接过程中使用它们。

3. General Compilation Flags

(Cross) compilers, e.g.,mips-linux-gnu-g++

进行交叉编译。通过这些变量,可以方便地配置和切换不同的编译器和工具链,以适应特定的编译环境和目标平台。

Compilation flags

定义了一些编译标志(Compilation flags)。

4. Arch-Specific Configurations

Paste in arch-specific configurations(e.g., from scripts/x86_64-qemu.mk)

这段代码片段用于包含特定架构的配置文件。使用 -include 指令,将$(AM_HOME)/scripts/$(ARCH).mk 文件包含到当前的 Makefile
中。这个文件路径由 $(AM_HOME)(AbstractMachine 仓库路径)和$(ARCH)(架构变量)组成。通过包含特定架构的配置文件,可以在构建过程中应用特定的架构相关配置。这样可以根据不同的架构定制编译和链接的行为,以适应特定的目标平台和需求。这方式可以使Makefile 更加灵活和可配置,以适应不同的架构和配置需求。 ### Fall backto native gcc/binutils if there is no cross compiler这段代码片段用于在没有交叉编译器的情况下,回退到本地的 gcc 和 binutils。

5. Compilation Rules - 定义编译规则,将源文件编译为目标文件。 -

  • 定义编译规则,将源文件编译为目标文件。
  • 定义递归规则,构建依赖库(am、klib 等)的静态库。
  • 定义链接规则,将目标文件和库文件链接为最终的 ELF 二进制文件。
  • 定义归档规则,将目标文件打包为静态库。
  • 定义 .d 文件的包含规则,用于处理头文件的依赖关系。

6. Miscellaneous

这段代码片段控制了构建的顺序和清理操作。 首先,定义了目标image,它依赖于目标 image-dep。这表示在构建 image 之前,需要先构建image-dep。同样地,定义了目标 archive,它依赖于变量$(ARCHIVE),表示在构建 archive 之前,需要先生成 $(ARCHIVE)。在目标 image-dep 中,定义了依赖关系,它依赖于目标 $(OBJS)am$(LIBS)。这表示在构建 image-dep 之前,需要先生成目标文件$(OBJS)、构建 am 和构建 $(LIBS)。 在目标 clean中,定义了清理操作,它会删除 Makefile.html 文件和 $(WORK_DIR)/build/目录。 在目标 clean-all 中,定义了清理所有子项目的操作。通过使用find 命令找到所有深度为 2 的 Makefile文件,并提取出对应的目录。然后,通过递归调用 $(MAKE)命令在每个子项目中执行 clean 目标。通过这些目标和规则,可以控制构建的顺序,并提供清理操作以清除构建生成的文件。

END

  1. 里面对于make clean、make html、make
    clean-all进行了处理,使得它们不需要进行检查和下面的操作,节省了很多时间;
  2. 对于交叉编译做了处理,如果没有交叉编译的环境则回退到原环境;
  3. Arch-Specific Configurations的Paste in arch-specific configurations
    (e.g., from scripts/x86_64-qemu.mk)使用 -include 指令,将$(AM_HOME)/scripts/$(ARCH).mk 文件包含到当前的 Makefile
    中。也是就是包含了特定架构的配置文件,可以在构建过程中应用特定的架构相关配置。使得一个n*m的问题变成了n + m!
    在这里插入图片描述

Answered by ChatGPT:

这个 Makefile 是用于构建 AbstractMachine 内核和库的。下面对其中的内容进行解释:

1. Basic Setup and Checks(基本设置和检查):
   - 检查默认目标,并设置 `MAKECMDGOALS` 和 `.DEFAULT_GOAL`。
   - 检查环境变量 `$AM_HOME` 是否指向 AbstractMachine 仓库。
   - 检查环境变量 `$ARCH` 是否在支持的架构列表中。
   - 提取 `$ARCH` 中的指令集架构 (`ISA`) 和平台信息。

2. General Compilation Targets(通用编译目标):
   - 创建目标目录 `build/$ARCH`。
   - 定义编译目标:`IMAGE_REL`(二进制镜像路径)和 `ARCHIVE`(静态库路径)。
   - 收集需要链接的文件:目标文件(`.o`)和库文件(`.a`)。

3. General Compilation Flags(通用编译标志):
   - 定义编译器和工具链的变量。
   - 定义编译标志,包括包含路径、宏定义和其他编译选项。

4. Arch-Specific Configurations(特定架构的配置):
   - 根据 `$ARCH` 包含特定架构的配置文件(例如 `scripts/x86_64-qemu.mk`)。
   - 如果没有交叉编译器,则使用本地的 gcc 和 binutils。

5. Compilation Rules(编译规则):
   - 定义编译规则,将源文件编译为目标文件。
   - 定义递归规则,构建依赖库(am、klib 等)的静态库。
   - 定义链接规则,将目标文件和库文件链接为最终的 ELF 二进制文件。
   - 定义归档规则,将目标文件打包为静态库。
   - 定义 `.d` 文件的包含规则,用于处理头文件的依赖关系。

6. Miscellaneous(其他):
   - 定义构建顺序控制的目标。
   - 定义清理目标,用于清除构建生成的文件和目录。

这个 Makefile 提供了一套通用的编译规则和目标,用于构建 AbstractMachine 内核和库。根据不同的架构和目标,可以通过修改和扩展这个 Makefile 来满足具体的构建需求。
  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智慧校园建设是在国家政策推动下,为深化教育改革、提升教育质量和管理效率而提出的重要项目。该项目旨在通过信息化手段,解决传统教育中存在的资源分散、管理混乱等问题,实现教育资源的高效利用和教学质量的全面提升。 目前,教育信息化虽取得一定进展,但面临“孤岛架构”的挑战,包括硬件资源无法共享、数据孤岛、应用孤岛等问题,导致资源浪费和管理效率低下。为此,智慧校园的建设目标聚焦于家校沟通便捷化、校园管理科学化、校园生活轻松化、课堂教学互动化和校园设施智能化,以提高教学效率和学生学习体验。 智慧校园的核心价值在于构建先进的网络教学平台和管理信息系统,实现教学资源的高效配置和利用,促进师生互动,提高管理效率,降低成本,构建健康高雅的生活环境。解决方案涵盖综合应用平台规划、系统架构设计、媒体发布、数字会议系统等,通过后台服务层、基础接入层和用户接入层的有机结合,实现智慧校园的全面功能。 智慧校园管理平台作为核心组成部分,提供模块化体系,包括公开课、直播、教学资源等23大应用,支持与第三方接口对接,实现多级管理。电教预约管理平台通过移动端APP或web后台简化预约流程,提高教室和会议室资源利用率,支持会议预订、审批、信息发布和环境管控。 教育录播系统和云平台支持教师制作和分享优质教学资源,进行在线组卷和评卷,同时提供学生应用,如高清视频录制、在线直播和互动交流,促进教学资源的共享和教育均衡化发展。这些系统的整合应用,将极大地推动教育信息化进程,实现教育资源的最大化利用和教育质量的全面提升。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值