免费企业网站制作,沈阳网站设计开发,网站建设主流技术,下瓦房做网站公司Makefile学习笔记18|u-boot顶层Makefile04 希望看到这篇文章的朋友能在评论区留下宝贵的建议来让我们共同成长#xff0c;谢谢。 这里是目录
C语言标准
# With the move to GCC 6, we have implicitly upgraded our language
# standard to GNU11 (see https://gcc.gnu.org/…Makefile学习笔记18|u-boot顶层Makefile04 希望看到这篇文章的朋友能在评论区留下宝贵的建议来让我们共同成长谢谢。 这里是目录
C语言标准
# With the move to GCC 6, we have implicitly upgraded our language
# standard to GNU11 (see https://gcc.gnu.org/gcc-5/porting_to.html).
# Some Linux distributions (including RHEL7, SLES13, Debian 8) still
# have older compilers as their default, so we make it explicit for
# these that our host tools are GNU11 (i.e. C11 w/ GNU extensions).
CSTD_FLAG : -stdgnu11
KBUILD_HOSTCFLAGS $(CSTD_FLAG)ifeq ($(HOSTOS),cygwin)
KBUILD_HOSTCFLAGS -ansi
endifCSTD_FLAG 变量被显式设置为 -stdgnu11指定编译宿主机工具时使用 GNU11 标准。这通常是为了确保代码使用最新的语言特性。KBUILD_HOSTCFLAGS 是一个在构建过程中传递给宿主机编译器的标志集合。会加入前面定义好的 CSTD_FLAG确保所有宿主机编译的 C 代码都采用 GNU11 标准。如果宿主操作系统是 Cygwin本段代码通过添加 -ansi 标志来调整 KBUILD_HOSTCFLAGS。-ansi 标志告诉 GCC 使用 ANSI C 标准也就是 C89 标准。这可能因为这些特定版本的 Cygwin 上的 GCC 默认不支持 GNU11 或者是为了解决特定兼容性问题。
适配MAC OS
# Mac OS X / Darwins C preprocessor is Apple specific. It
# generates numerous errors and warnings. We want to bypass it
# and use GNU Cs cpp. To do this we pass the -traditional-cpp
# option to the compiler. Note that the -traditional-cpp flag
# DOES NOT have the same semantics as GNU Cs flag, all it does
# is invoke the GNU preprocessor in stock ANSI/ISO C fashion.
#
# Apples linker is similar, thanks to the new 2 stage linking
# multiple symbol definitions are treated as errors, hence the
# -multiply_defined suppress option to turn off this error.
#
ifeq ($(HOSTOS),darwin)
# get major and minor product version (e.g. 10 and 6 for Snow Leopard)
DARWIN_MAJOR_VERSION : $(shell sw_vers -productVersion | cut -f 1 -d .)
DARWIN_MINOR_VERSION : $(shell sw_vers -productVersion | cut -f 2 -d .)os_x_before $(shell if [ $(DARWIN_MAJOR_VERSION) -le $(1) -a \$(DARWIN_MINOR_VERSION) -le $(2) ] ; then echo $(3); else echo $(4); fi ;)os_x_after $(shell if [ $(DARWIN_MAJOR_VERSION) -ge $(1) -a \$(DARWIN_MINOR_VERSION) -ge $(2) ] ; then echo $(3); else echo $(4); fi ;)# Snow Leopards build environment has no longer restrictions as described above
HOSTCC $(call os_x_before, 10, 5, cc, gcc)
KBUILD_HOSTCFLAGS $(call os_x_before, 10, 4, -traditional-cpp)
KBUILD_HOSTLDFLAGS $(call os_x_before, 10, 5, -multiply_defined suppress)# macOS Mojave (10.14.X)
# Undefined symbols for architecture x86_64: _PyArg_ParseTuple
KBUILD_HOSTLDFLAGS $(call os_x_after, 10, 14, -lpython -dynamclib, )
endif这些设置帮助构建系统适配在 macOS 各个版本上的差异确保构建过程能够在各种 macOS 环境中顺利执行。尤其在系统的默认编译器和链接器在行为上存在变化的情况下比如Apple 从使用 GCC 切换至 clang。我不使用 MAC OS这里就只是粗略地看一下。
size_check函数
# Check ths size of a binary:
# Args:
# $1: File to check
# #2: Size limit in bytes (decimal or 0xhex)
define size_checkactual$$( wc -c $1 | awk {print $$1}); \limit$$( printf %d $2 ); \if test $$actual -gt $$limit; then \echo $1 exceeds file size limit: 2; \echo limit: $$(printf %#x $$limit) bytes 2; \echo actual: $$(printf %#x $$actual) bytes 2; \echo excess: $$(printf %#x $$((actual - limit))) bytes 2;\exit 1; \fi
endef
export size_check这段代码定义了一个 Makefile 函数 size_check用于检查一个给定文件的大小是否超过了指定的大小限制。如果文件大小超出限制它将打印错误信息并退出构建过程。函数通过传递参数被调用其中 $1 是要检查的文件的路径$2 是大小上限以字节为单位可以是十进制或十六进制形式。让我们详细解析这个函数的工作流程
actual$( wc -c $1 | awk {print $1});
这个命令使用 wcword count工具计算文件 $1 的字节大小然后通过 awk 提取字节计数。
limit$( printf %d $2 );
使用 printf 将大小限制 $2 转换成十进制形式。这样做允许函数接受诸如 “0x10000”十六进制这样的输入参数。
if test $actual -gt $limit; then
这里用 if 测试实际文件大小 a c t u a l 是否大于限制 actual是否大于限制 actual是否大于限制limit。如果超出限制则执行 then 分支。
echo $1 exceeds file size limit: 2; ...
如果文件超出了大小限制在标准错误输出中打印出有关信息。2 重定向输出到标准错误这是一种常见的做法旨在确保错误信息被正确地捕获和显示。
exit 1;
因为超出了大小限制故退出构建过程并返回状态码 1 来表示错误。
包含通用定义
# We need some generic definitions (do not try to remake the file).
scripts/Kbuild.include: ;
include scripts/Kbuild.include定义 scripts/Kbuild.include 为一个空规则。在这种情况下随后紧跟分号的目标意味着 Make 不应该尝试去构建这个文件——即使它不存在或者需要更新。这通常被用来防止含有 Makefile 规则的文件在每次 make 命令运行时被重新创建或下载。
scripts/Kbuild.include
# Kconfig helper macros# Convenient variables
comma : ,
quote :
squote :
empty :
space : $(empty) $(empty)
dollar : $
right_paren : )
left_paren : (# $(if-success,command,then,else)
# Return then if command exits with 0, else otherwise.
if-success $(shell,{ $(1); } /dev/null 21 echo $(2) || echo $(3))# $(success,command)
# Return y if command exits with 0, n otherwise
success $(if-success,$(1),y,n)# $(cc-option,flag)
# Return y if the compiler supports flag, n otherwise
cc-option $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)# $(cc-define,macro)
# Return y if the compiler defines macro, n otherwise
cc-define $(success,$(CC) -dM -E -x c /dev/null | grep -q ^#define \$(1)\)# $(ld-option,flag)
# Return y if the linker supports flag, n otherwise
ld-option $(success,$(LD) -v $(1))# gcc version including patch level
gcc-version : $(shell,$(srctree)/scripts/gcc-version.sh -p $(CC) | sed s/^0*//)scripts/Kbuild.include 中用宏定义了一些符号还定义了几个Makefile宏。
$(if-success,command,then,else):
这个宏执行一个 shell 命令 并根据命令执行的退出状态来返回 或 。如果 成功执行退出状态为 0则返回 否则返回 。
$(success,command):
这个宏使用 $(if-success,…) 来检测 是否成功执行返回 ‘y’ 或 ‘n’。
$(cc-option,flag):
检测编译器通常是 GCC是否支持某个标志 。如果编译器支持则返回 ‘y’不支持则返回 ‘n’。
$(cc-define,macro):
检测编译器是否预定义了一个宏 如果是则返回 ‘y’否则返回 ‘n’。
$(ld-option,flag):
检测链接器LD是否支持某个命令行标志 如果支持则返回 ‘y’不支持则返回 ‘n’。
gcc-version:
使用 scripts/gcc-version.sh 脚本来获得 GCC 编译器的版本信息包括次要修订号。使用 sed 来移除版本号前的任何零。
scripts/gcc-version.sh
if [ $1 -p ] ; thenwith_patchlevel1;shift;
ficompiler$*if [ ${#compiler} -eq 0 ]; thenecho Error: No compiler specified.printf Usage:\n\t$0 gcc-command\nexit 1
fiMAJOR$(echo __GNUC__ | $compiler -E -x c - | tail -n 1)
MINOR$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1)
if [ x$with_patchlevel ! x ] ; thenPATCHLEVEL$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)printf %02d%02d%02d\\n $MAJOR $MINOR $PATCHLEVEL
elseprintf %02d%02d\\n $MAJOR $MINOR
fi这个脚本用于确定 GCC 编译器的版本号。它接收一个或多个参数第一个参数可以是 -p 选项用于决定是否输出 patchlevel修订版号剩余的参数应该是编译器的命令如 gcc 或 arm-none-eabi-gcc。
处理 -p 选项:
脚本首先检查第一个参数是否为 -p如果是设置 with_patchlevel 变量的值为 1这表示用户要求输出 patchlevel然后通过 shift 命令移除这个参数。
验证编译器参数:
脚本接着检查是否提供了编译器命令如果没有提供打印错误信息并退出。
获取版本号:
使用 $compiler编译器命令执行预处理操作 -E处理伪代码中的宏定义 GNUC 和 GNUC_MINOR以便提取 GCC 的主要和次要版本号。 如果用户使用了 -p 参数则同样提取 GNUC_PATCHLEVEL 宏定义以获取 patchlevel。
格式化输出:
使用 printf 格式化输出版本号。它保证主要和次要版本号都是两位数字。如果用户请求 patchlevel则以同样的方式保证它也是两位数字。 格式化的结果是一个六位数例如 “049801” 表示 GCC 4.9.1 或四位数 “0409” 表示 GCC 4.9。 5. 输出版本号:
格式化后的版本号被打印到标准输出。 都看到这里了可以给个点赞或者评论吗达瓦里希(^)ゞ