Makefile学习笔记15|u-boot顶层Makefile01
Makefile学习笔记15|u-boot顶层Makefile01
希望看到这篇文章的朋友能在评论区留下宝贵的建议来让我们共同成长,谢谢。
这里是目录
版本号信息
# SPDX-License-Identifier: GPL-2.0+VERSION = 2024
PATCHLEVEL = 01
SUBLEVEL =
EXTRAVERSION = -rc4
NAME =
这里定义了u-boot的版本信息。
make行为控制
# *DOCUMENTATION*
# To see a list of typical targets execute "make help"
# More info can be located in ./README
# Comments in this file are targeted only to the developer, do not
# expect to learn how to build the kernel reading this file.# Do not use make's built-in rules and variables
# (this increases performance and avoids hard-to-debug behaviour)
MAKEFLAGS += -rR
前面的注释中说:该文件中的注释仅针对开发人员,不要指望通过阅读该文件来学习如何构建内核。那我们学一下Makefile不过分吧。
在 Makefile 中设置 MAKEFLAGS += -rR 是控制 make 工具行为的一种方式。具体来说,-r 和 -R 这两个标志的含义如下:
- -r(或 --no-builtin-rules):
这个选项会禁止 make 使用内置的隐含规则。隐含规则是 make 用来构建文件但未在 Makefile 中明确定义的一组默认规则。例如,make 有一个隐含规则知道如何将 .c 文件编译成 .o 文件。禁用内置规则可以避免一些意外的构建行为,并且可以在某些情况下提高 make 的执行性能。 - -R(或 --no-builtin-variables):
这个选项禁止 make 使用内置的变量集合,这些变量可能会影响那些依赖隐含规则的命令。例如,CFLAGS 是 make 中一个影响 C 编译器行为的内置变量。在 Makefile 中禁用内置变量是为了确保构建环境的清晰和可控性,并避免 Makefile 行为的不确定性。
将这两个选项合在一起使用可以确保 Makefile 中的构建规则和变量不受 make 内置规则和变量的任何潜在干扰。这在大型、复杂的构建系统中可能很有用,其中你希望对构建过程有完全的控制,同时减少构建过程的不必要干预和潜在的性能影响。
确切的说,MAKEFLAGS 是一个环境变量,它允许你为 make 设置多个启动选项。在Makefile文件中通过 MAKEFLAGS 变量追加 -rR 选项,可以使这些选项在调用 make 时自动应用于当前构建。
在你自己的项目中使用时,请确保你完全理解了禁止这些内置规则和变量的含义,以及它们对你的构建系统可能产生的影响。如果你依赖了默认的规则或变量,禁用它们可能会导致构建失败,因此在某些项目中可能需要保留这些内置规则和变量。
确定目标架构
# Determine target architecture for the sandbox
include include/host_arch.h
ifeq ("", "$(CROSS_COMPILE)")MK_ARCH="${shell uname -m}"
elseMK_ARCH="${shell echo $(CROSS_COMPILE) | sed -n 's/^[[:space:]]*\([^\/]*\/\)*\([^-]*\)-[^[:space:]]*/\2/p'}"
endif
unexport HOST_ARCH
ifeq ("x86_64", $(MK_ARCH))export HOST_ARCH=$(HOST_ARCH_X86_64)
else ifneq (,$(findstring $(MK_ARCH), "i386" "i486" "i586" "i686"))export HOST_ARCH=$(HOST_ARCH_X86)
else ifneq (,$(findstring $(MK_ARCH), "aarch64" "armv8l"))export HOST_ARCH=$(HOST_ARCH_AARCH64)
else ifneq (,$(findstring $(MK_ARCH), "arm" "armv7" "armv7a" "armv7l"))export HOST_ARCH=$(HOST_ARCH_ARM)
else ifeq ("riscv32", $(MK_ARCH))export HOST_ARCH=$(HOST_ARCH_RISCV32)
else ifeq ("riscv64", $(MK_ARCH))export HOST_ARCH=$(HOST_ARCH_RISCV64)
endif
undefine MK_ARCH
在交叉编译环境中,CROSS_COMPILE 是一个常用的变量,它指定了编译器的前缀,使得我们能够为不同于编译宿主机的目标架构构建软件。这在嵌入式系统开发中很常见,因为编译的代码需要在如 ARM、MIPS 或 AVR 这样的架构上运行,而开发者通常在 x86 或 x86-64 架构的机器上进行开发。
例如,如果你的开发系统是基于 x86 架构的,而你的目标系统是基于 ARM 架构的,那么你需要使用 ARM 架构的交叉编译器来编译你的代码。这样生成的可执行文件才能在 ARM 目标机上运行。
CROSS_COMPILE 变量通常用于 Makefile 中。它是编译器命令的前缀,所有必要的工具(如编译器 gcc、链接器 ld、汇编器 as 和其他工具)都使用这个前缀。
例如,如果 ARM 交叉编译器的命令是 arm-none-eabi-gcc,那么 CROSS_COMPILE 应该设置为 arm-none-eabi-,以此类推。下面是 CROSS_COMPILE 在Makefile中的常见用法:
# 设置交叉编译器前缀
CROSS_COMPILE=arm-linux-gnueabihf-# 之后使用变量时:
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
AS=$(CROSS_COMPILE)as# 其他编译规则和目标...
字符集设置
# Avoid funny character set dependencies
unexport LC_ALL
LC_COLLATE=C
LC_NUMERIC=C
export LC_COLLATE LC_NUMERIC# Avoid interference with shell env settings
unexport GREP_OPTIONS
这段脚本通常出现在 Unix-like 系统的 Makefile 中,它的目的是确保 Makefile 中的操作对于本地化设置及字符集是独立的。本地化设置可能会影响字符串的比较,排序和数字的表示方式。为了避免这些依赖,通常在 Makefile 或构建脚本中设置特定的环境变量,使得这些操作更可预测,具有一致性,避免构建过程中由于不同的本地化设置引起的问题。
- LC_ALL 是一个强制性的环境变量,用于设置 C 库的本地化配置,它会覆盖所有其他本地化设置,包括 LC_COLLATE, LC_NUMERIC, 以及其他 LC_* 类型的变量。
- LC_COLLATE 定义了字符串比较和排序的规则。设置为 C 可确保文件名和字符串的比较是基于字节值进行的,而不受根据地区的字母顺序影响。
- LC_NUMERIC 影响数字的格式化方式,比如数字分隔符。例如,在某些本地化设置中,小数点用逗号 ‘,’ 表示。设置为 C 可以确保小数点始终使用点 ‘.’,以符合大多数编程语言和脚本的期望。
当我们确保 LC_COLLATE 和 LC_NUMERIC 是 C(或 POSIX,它们是等效的)时,您可以让构建过程在所有环境中提供一致的行为,避免由于不同的语言或地区设置而造成的问题。这可以提高 Makefile 的可移植性和健壮性。
对于最后一行,当在脚本或者 Makefile 中使用 grep,不同用户的不同 GREP_OPTIONS 设置可能会结果不一致,尤其是当这个脚本依赖于 grep 输出特定格式时。为了确保 grep 的行为是预期并且一致的,开发者通常会选择清除 GREP_OPTIONS 环境变量。
美化输出
# Beautify output
# ---------------------------------------------------------------------------
#
# Normally, we echo the whole command before executing it. By making
# that echo $($(quiet)$(cmd)), we now have the possibility to set
# $(quiet) to choose other forms of output instead, e.g.
#
# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@
# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
#
# If $(quiet) is empty, the whole command will be printed.
# If it is set to "quiet_", only the short version will be printed.
# If it is set to "silent_", nothing will be printed at all, since
# the variable $(silent_cmd_cc_o_c) doesn't exist.
#
# A simple variant is to prefix commands with $(Q) - that's useful
# for commands that shall be hidden in non-verbose mode.
#
# $(Q)ln $@ :<
#
# If KBUILD_VERBOSE equals 0 then the above command will be hidden.
# If KBUILD_VERBOSE equals 1 then the above command is displayed.
#
# To put more focus on warnings, be less verbose as default
# Use 'make V=1' to see the full commandsifeq ("$(origin V)", "command line")KBUILD_VERBOSE = $(V)
endif
ifndef KBUILD_VERBOSEKBUILD_VERBOSE = 0
endififeq ($(KBUILD_VERBOSE),1)quiet =Q =
elsequiet=quiet_Q = @
endif# If the user is running make -s (silent mode), suppress echoing of
# commandsifneq ($(filter 4.%,$(MAKE_VERSION)),) # make-4
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)quiet=silent_
endif
else # make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)quiet=silent_
endif
endifexport quiet Q KBUILD_VERBOSE
它提供了一种灵活的机制,用于控制命令执行时输出信息的格式。这种机制让构建系统(如内核)能够以不同的详细级别显示或隐藏命令的输出。
- 设置输出参数
- 命令行变量 V:允许你通过在 make 命令后添加 V=1 参数来开启详细模式(例如,make V=1)。
- 设置 KBUILD_VERBOSE:根据 V 变量的值设置 KBUILD_VERBOSE,用于决定输出模式是详细 (1) 还是简洁 (0)。
- 定义 quiet 和 Q:利用 KBUILD_VERBOSE 变量,这段设置定义了两个控制输出的变量 quiet 和 Q。当 KBUILD_VERBOSE 是 1(详细模式),Q 是空字符串,这意味着所有命令都会显示。如果是 0(简洁模式),Q 被设置为 @,这表示 Makefile 中以 $(Q) 开头的命令将不显示。
- 控制命令输出
- 命令输出前缀:使用 $(quiet) 作为前缀可以使得 make 在执行命令时不显示整个命令,而是显示一个简短的描述,例如“Compiling foo/bar.o”。
- 静默模式检测:根据 Make 的版本,脚本检查 MAKEFLAGS 是否包含静默模式标志 s。如果用户使用了 make -s,则所有命令执行将不输出任何信息,因为 quiet 变量将被设置为 silent_。
这个复杂的控制机制最终目的是为开发者提供一个在需要时能够详细打印每一个命令执行的构建过程(有助于调试),而在常规构建时则显示简化或没有输出。这使得构建输出更易于阅读,并能在需要解决问题时提供足够的信息。
都看到这里了,可以给个点赞或者评论吗?达瓦里希( ̄^ ̄)ゞ
相关文章:
Makefile学习笔记15|u-boot顶层Makefile01
Makefile学习笔记15|u-boot顶层Makefile01 希望看到这篇文章的朋友能在评论区留下宝贵的建议来让我们共同成长,谢谢。 这里是目录 版本号信息 # SPDX-License-Identifier: GPL-2.0VERSION 2024 PATCHLEVEL 01 SUBLEVEL EXTRAVERSION -rc4 NAME 这里定义了u-bo…...
C++笔记之Unix时间戳、UTC、TSN、系统时间戳、时区转换、local时间笔记
C++笔记之Unix时间戳、UTC、TSN、系统时间戳、时区转换、local时间笔记 ——2024-05-26 夜 code review! 参考博文 C++笔记之获取当前本地时间以及utc时间...
leetcode338-Counting Bits
题目 给你一个整数 n ,对于 0 < i < n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n 1 的数组 ans 作为答案。 示例 1: 输入:n 2 输出:[0,1,1] 解释: 0 --> 0 1 --&…...
sql server怎么存储图片
sql server怎么存储图片 在SQL Server中,可以使用VARBINARY数据类型来存储图片。以下是一个简单的例子,展示了如何将图片存储到数据库中,并从数据库中检索出来。 首先,创建一个表来存储图片数据: CREATE TABLE Image…...
大模型提示词Prompt学习
引言 关于chatGPT的Prompt Engineer,大家肯定耳朵都听起茧了。但是它的来由?,怎么能用好?很多人可能并不觉得并不是一个问题,或者说认定是一个很快会过时的概念。但其实也不能说得非常清楚(因为觉得没必要深…...
蓝桥杯python组备赛指南
文章目录 前言刷题网站idle操作常用标准库mathdatetime 常见Q&A 前言 最近结束了比赛,我对比赛的过程进行了详细的复盘,并计划撰写一篇文章。这篇文章旨在为准备参加蓝桥杯的学弟学妹们提供帮助,我希望我的文章和笔记能对你们有所裨益。…...
架构师系列-定时任务解决方案
定时任务概述 在很多应用中我们都是需要执行一些定时任务的,比如定时发送短信,定时统计数据,在实际使用中我们使用什么定时任务框架来实现我们的业务,定时任务使用中会遇到哪些坑,如何最大化的提高定时任务的性能。 我…...
新计划,不断变更!做自己,接受不美好!猪肝移植——早读(逆天打工人爬取热门微信文章解读)
时间不等人 引言Python 代码第一篇 做自己,没有很好也没关系第二篇结尾 引言 新计划: 早上一次性发几个视频不现实 所以更改一下 待后面有比较稳定的框架再优化 每天早上更新 早到8点 晚到10点 你刚刚好上班或者上课 然后偷瞄的看两眼 学习一下 补充知…...
【数据结构】二叉树-堆(上)
个人主页~ 二叉树-堆 一、树的概念及结构1、概念2、相关概念3、树的表示4、树的实际应用 二、二叉树的概念和结构1、概念2、特殊二叉树3、二叉树的性质4、二叉树的存储结构(1)顺序存储(2)链式存储 三、二叉树的顺序结构以及实现1、…...
【Spring Boot】在项目中使用Spring AI
Spring AI是Spring框架中用于集成和使用人工智能和机器学习功能的组件。它提供了一种简化的方式来与AI模型进行交互。下面是一个简单的示例,展示了如何在Spring Boot项目中使用Spring AI。 步骤 1: 添加依赖 首先,在pom.xml文件中添加Spring AI的依赖&…...
【java程序设计期末复习】chapter3 运算符、表达式和语句
运算符、表达式和语句 Java提供了丰富的运算符,如算术运算符、关系运算符、逻辑运算符、位运算符等。 Java语言中的绝大多数运算符和C语言相同,基本语句,如条件分支语句、循环语句等也和C语言类似,因此,本章就主要知识…...
【建议收藏】30个较难Python脚本,纯干货分享
本篇较难,建议优先学习上篇 ;20个硬核Python脚本-CSDN博客 接上篇文章,对于Pyhon的学习,上篇学习的结束相信大家对于Pyhon有了一定的理解和经验,学习完上篇文章之后再研究研究剩下的30个脚本你将会有所成就&…...
01-05.Vue自定义过滤器
目录 前言过滤器的概念过滤器的基本使用给过滤器添加多个参数 前言 我们接着上一篇文章01-04.Vue的使用示例:列表功能 来讲。 下一篇文章 02-Vue实例的生命周期函数 过滤器的概念 概念:Vue.js 允许我们自定义过滤器,可被用作一些常见的文本…...
C++系列-static成员
🌈个人主页:羽晨同学 💫个人格言:“成为自己未来的主人~” 概念 声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量,用static修饰的成员函数,称之为静态成…...
Git | 创建和管理Pull Request总结
如是我闻: 在使用 GitHub 进行项目协作时,掌握如何创建、更新和合并(squash)pull request 是非常有帮助的。本文将详细介绍这些操作,帮助我们更好地管理项目代码,并解释每个操作的原因和解决的问题。 1. 什…...
电机控制系列模块解析(23)—— 同步机初始位置辨识
一、两个常见问题 为什么感应电机(异步机)不需要初始位置辨识?(因此感应电机转子磁场在定子侧进行励磁,其初始位置可以始终人为定义为0) 为什么同步磁阻电机需要初始位置辨识?(因为…...
【数据库基础-mysql详解之索引的魅力(N叉树)】
索引的魅力目录 🌈索引的概念🌈使用场景🌈索引的使用🌞🌞🌞查看MySQL中的默认索引🌞🌞🌞创建索引🌞🌞🌞删除索引 站在索引背后的那个男…...
力扣739. 每日温度
Problem: 739. 每日温度 文章目录 题目描述思路复杂度Code 题目描述 思路 若本题目使用暴力法则会超时,故而使用单调栈解决: 1.创建结果数组res,和单调栈stack; 2.循环遍历数组temperatures: 2.1.若当stack不为空同时…...
KDE6桌面于2024年2月发布
原文:KDE MegaRelease 6 - KDE 社区 1. **Plasma 6 桌面环境**:KDE Plasma 是一个现代化、功能丰富的 Linux 操作系统桌面环境,以其时尚设计、可定制界面和广泛的应用程序而闻名。Plasma 6 带来了两项重大技术升级:过渡到最新的应…...
「TypeScript系列」TypeScript 对象及对象的使用场景
文章目录 一、TypeScript 对象1. 对象字面量2. 类实例化3. 使用接口定义对象形状4. 使用类型别名定义对象类型5. 使用工厂函数创建对象 二、TypeScript 对象属性及方法1. 对象属性2. 对象方法3. 访问器和修改器(Getters 和 Setters) 三、TypeScript 对象…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
