【嵌入式】Makefile 学习笔记记录 | 嵌入式Linux

news2024/11/16 8:48:28

文章目录

  • 前言
  • 一、Makefile的引入——最简单的gcc编译过程
  • 二、Makefile的规则
  • 三、Makefile的语法
    • 3.1、通配符
    • 3.2、假想目标 .phony
    • 3.3、即时变量 延时变量
  • 四、Makefile的函数
    • 4.1、foreach
    • 4.2、filter
    • 4.3、wildcard
    • 4.4、patsubst
  • 五、Makefile升级
    • 5.1、包含头文件在内的依赖关系(自动生成依赖文件)
    • 5.2、添加CFLAGS
  • 六、通用Makefile模板


前言

开发板平台:飞凌嵌入式ElfBoard ELF-1
参考视频和资料:飞凌嵌入式ElfBoard ELF-1软件学习书册
韦东山:https://www.bilibili.com/video/BV1kk4y117Tu?p=6&vd_source=3018264d4331e8fc267f9d68c24ee20f

一、Makefile的引入——最简单的gcc编译过程

keil,mdk,avr这些工具全自动编译的内部机制依然是makefile

这里我们先随便写两个C文件(a.c 和b.c),用最传统的gcc编译一下:

a.c:

#include <stdio.h>
void funB();
int main() {
	funB();
	return 0;
}

b.c:

#include <stdio.h>
void funB() {
	printf("hello B!\n");
}

然后我们上传到虚拟机上进行编译:

gcc -o test a.c  b.c

然后执行

./test

在这里插入图片描述
从a.c b.c到可执行文件test经历了什么?:
总的来说就是四步:预处理,编译,汇编,链接(一般来说前三步统称为编译)
a.c ->a.s->a.o
b.c ->b.s->b.o
最后两个.o链接在一起生成可执行文件test

我们可以在gcc命令后加上 -v看到编译链接的完整过程:

gcc -o test a.c  b.c -v

具体内容很多,就不一一截图了:
在这里插入图片描述
这样gcc有个很明显的缺点:
不论a.c b.c有没有被更改过,每次gcc都会重新编译链接所有的C文件。有的时候我们只修改了很小一部分的C文件,但此时我们gcc会全部重新编译,这很耽误时间。

makefile就能解决这个问题。
它可以把刚刚gcc这个过程解构成一系列小的编译过程:

gcc -c -o a.o a.c
gcc -c -o b.o b.c
gcc -o test  a.o b.o

这三句命令的含义如下:

gcc -c -o a.o a.c:这个命令使用 GCC 编译器将源文件 a.c 编译成目标文件 a.o。具体解释如下:
-c 选项表示只进行编译,而不进行链接,生成目标文件。
-o a.o 选项指定输出文件的名称为 a.o。
a.c 是源文件的名称。

gcc -c -o b.o b.c:这个命令与第一条类似,将源文件 b.c 编译成目标文件 b.o。

gcc -o test a.o b.o:这个命令使用 GCC 编译器将目标文件 a.o 和 b.o 进行链接,生成一个名为 test 的可执行文件。
-o test 选项指定输出文件的名称为 test。
a.o b.o 是链接的目标文件。

综合起来,这三条命令用于分别编译两个源文件 a.c 和 b.c,然后将生成的目标文件 a.o 和 b.o 链接在一起,形成一个名为 test 的可执行文件。
makefile如何自己的这些文件被修改了?:
在第一行 判断到a.c比a.o新,就说明a.c被更新过了,就可以重新编译
在第二行 判断到b.c比b.o新,就说明b.c被更新过了,就可以重新编译
在第三行 判断到a.o b.o比test新,就说明a.o b.o被更新过了,就可以重新编译

二、Makefile的规则

makefile的基本语法格式为:


目标文件:依赖文件
TAB 命令


当依赖比目标的时候 or 该目标文件直接不存在的时候,就会执行命令

我们在刚刚的文件夹中新建一个makefile:
在这里插入图片描述
然后执行make两此看一下效果:

make
make

在这里插入图片描述
第一次Make正确得运行了我们makefile里面写的所有语句
第二次make因为没有检测到依赖项更新,所以并没有重新编译

我们再做一个小实验,即只修改a.c ,只修改b.c 以及同时修改a.c和b.c再分别执行make的效果:
在这里插入图片描述
可以看到,我们修改了啥,make时也只会重新执行依赖项变动的语句,没有修改的部分不会重新执行命令。
(touch 命令是用来更新文件的访问和修改时间戳的工具,如果文件不存在,则会创建一个空白文件。它不会修改文件的内容,只是更新文件的元数据。所以,touch 命令不会改变文件的内容,只是改变文件的时间戳相当于变相修改了文件

三、Makefile的语法

3.1、通配符

我们再增加一个c.c文件,里面有一个函数func():

#include <stdio.h>
void funC() {
	printf("hello C!\n");
}

再把a.c里的内容改一下,把函数func加上去:

#include <stdio.h>
void funB();
void funC();
int main() {
	funB();
	funC();
	return 0;
}

再使用通配符对makefile里面的语句进行一定的修改:
在这里插入图片描述
1)$^表示所有的依赖文件
2)使用 $< 表示第一个依赖文件(源文件),使用 $@ 表示目标文件
这样就可以把gcc -o -c a.o a.c 和gcc -o -c b.o b.c合并成一句话了

我们在虚拟机上看一下效果:

在这里插入图片描述
这里make没啥问题,正常工作了。

3.2、假想目标 .phony

phony,英语单词,主要用作形容词、名词,作形容词时译为"假的,欺骗的"
我们首先补一下make clean的内容 我们修改一下makefile中的内容:
在这里插入图片描述
增加了一句话:

clean:
	rm *.o test

Makefile 中还包含了一个 clean 目标,用于清理生成的目标文件和可执行文件:
当执行 make clean 时,它将删除当前目录下的所有 .o 文件和 test 可执行文件

我们上虚拟机实验一下:
在这里插入图片描述
发现所有的.o文件和可执行文件test均被清除了,这就是make clean的作用

在讲完clean之后,正式引出我们的makefile的一个语法:


make [目标]
比如说make clean,就会寻找makefile里面名为clean的目标,执行其tab后的命令
如果make后没有加东西(直接就是make),那么系统会默认自动执行第一个目标的命令,在上文中,就会自动执行test目标的命令。


在这个规则下有一个bug,就是遇到同名文件的情况(这里以clean同名文件为例子),**因为在makefile里并没有clean的依赖项文件。**之前是因为没有clean这个东西,所以执行会很顺利。
在这里插入图片描述

我们在虚拟机上新建一个名为clean的文件,我们先make,再执行make clean。此时根据makefile的规则,系统没有检测到clean发生改变(因为存在同名文件clean),那么执行make clean时就不会正确执行:
在这里插入图片描述
解决办法:我们把clean设置为假想目标就能解决这个问题
我们稍微改一下makefile:
在这里插入图片描述
这里使用了 .PHONY 目标,它告诉 Make 这个目标不对应真实的文件名。这样做的目的是防止与同名的实际文件冲突,同时确保即使存在同名文件,make clean 也能正常执行。
这回我们再实验一下就对了:
在这里插入图片描述

3.3、即时变量 延时变量

我们写一个新的makefile:
在这里插入图片描述
这个 Makefile 定义了两个变量 A 和 B,然后在 all 目标中使用了这两个变量。以下是中文解释:

A := abc 表示定义了一个变量 A,其值为 “abc”。:= 是一种赋值方式,表示覆盖先前的值。(即刻确定)
B = 123 表示定义了一个变量 B,其值为 “123”。= 也是一种赋值方式,但是它是延迟赋值,即在使用变量时才会展开。(延迟确定

all 目标中使用了 echo $(A) 和 echo $ (B) 分别输出变量 A 和 B 的值。在 Makefile 中,$() 用于引用变量的值echo 是一个在命令行中常用的命令,用于将文本输出到标准输出设备(通常是终端)。在类Unix系统(如Linux)和类似的命令行环境中,echo 命令通常用于显示文本。

我们make一下看看效果:
在这里插入图片描述
我们可以在echo前面加上@ :
在这里插入图片描述
这样就不会打印命令本身了:
在这里插入图片描述
到这里我们还看不出即时变量和延时变量的区别,我们再makefile添一些代码:
在这里插入图片描述
A是即可确定,但此时C还并没被赋值,所以这时会打印空
B是使用时才确定,所以不会为空
我们实验一下:
在这里插入图片描述
我们如果更改C=abc的位置呢:
在这里插入图片描述
最后结果还是不影响:(即C位置不影响B,系统会对makefile整体进行分析)

在这里插入图片描述
最后我们再介绍两种符号:+= ?=
在makefile里我们做如下更改:
在这里插入图片描述
make一下看看效果:
在这里插入图片描述
1)+= 运算符:用于追加值到变量。使用 += 时,它会将右侧的值追加到已经存在的变量值的末尾。如果变量之前未定义,则行为类似于简单的赋值。
2)?= 运算符:用于给变量赋值,但仅在该变量之前未定义时才赋值。使用 ?= 时,它会检查变量是否已经定义,如果已定义则不进行赋值,否则将变量赋予指定的默认值。

总结:
1):= 即时变量
2)= 延时变量
3)?=延时变量 是第一次定义才起效果
4)+= 附加 它是即时变量还是延时变量 取决于前面

四、Makefile的函数

4.1、foreach

foreach 是GNU Make中的一个函数,用于进行循环迭代。其基本语法如下:

$(foreach var, list, text)

var: 循环中的临时变量,表示每次迭代中的当前元素。

list: 要迭代的列表,可以是以空格分隔的多个元素。

text: 在每次迭代中对var进行操作的文本块。

我们写一个新的makefile:
在这里插入图片描述
A=a b c: 定义了一个变量A,包含三个元素a、b和c。
B=$(foreach f, $(A), $(f).o): 使用foreach循环,将A中的每个元素加上.o后缀,并将结果存储到变量B中。
all:: 定义了一个目标规则名为all。@echo B = $(B): 在执行all目标时,打印出变量B的值。
最后结果:
在这里插入图片描述

4.2、filter

filter 是GNU Make中的一个函数,用于从列表中筛选出符合指定条件的元素。其基本语法如下:

$(filter pattern..., text)

pattern…: 一个或多个模式,用于指定筛选条件。可以包含通配符 %。
text: 要进行筛选的文本块,通常是一个以空格分隔的元素列表。
filter函数会返回text中符合给定模式的元素列表。模式之间使用空格分隔。

filter函数还支持反向操作,使用filter-out可以筛选出不符合指定条件的元素。例如:

C = $(filter-out a%, $(A))

在这个例子中,匹配A中不以字母’a’开头的元素。

我们写一个新的Makefile:
在这里插入图片描述

C = a b c d/: 定义了一个变量C,包含四个元素a、b、c和d/。
D = $(filter %/, $©): 使用filter函数,从C中筛选出以’/'结尾的元素,存储到变量D中。在这个例子中,D的值为d/。
E = $(filter-out %/, $©): 使用filter-out函数,从C中筛选出不以’/'结尾的元素,存储到变量E中。在这个例子中,E的值为a b c。

最后结果:

在这里插入图片描述

4.3、wildcard

wildcard 是 GNU Make 中的一个函数,用于匹配文件名模式,返回匹配到的文件列表。其基本语法如下:

$(wildcard pattern)

pattern: 文件名模式,可以包含通配符 * 和 ?。
wildcard 函数会返回符合指定文件名模式的文件列表。通常,这个函数用于获取文件列表并将其赋值给一个变量,以便在 Makefile 中进一步处理这些文件。
我们写一个新的makefile:
请添加图片描述
files=$(wildcard *.c):使用 wildcard 函数匹配当前目录下所有以 .c 结尾的文件,并将结果存储到变量 files 中。
最后结果:
在这里插入图片描述

扩展应用:可以用检查目录下面哪些文件是真实存在的
请添加图片描述
定义了一个变量 files2 包含了一组源文件名,然后使用 wildcard 函数来获取这些文件的实际存在的文件列表并存储在变量 files3 中。(注意d.c e.c是不存在的)
最后结果:
在这里插入图片描述

4.4、patsubst

patsubst 是在 Makefile 中用来替换模式的函数之一。它用于将一个字符串中符合指定模式的部分替换成另一个模式。基本语法是:

$(patsubst pattern,replacement,text)

pattern 是要匹配的模式,可以包含 % 通配符,表示零个或多个字符。
replacement 是替换的模式。
text 是要进行替换操作的原始文本。

我们改一下makefile:
在这里插入图片描述
Makefile 中,定义了一个变量 files2 包含了一组源文件名,其中包含一个不是以 .c 结尾的文件 abc。接着,使用 patsubst 函数将每个源文件名的扩展名从 .c 替换为 .d,并将结果存储在变量 dep_files 中。

最后结果:
在这里插入图片描述

五、Makefile升级

5.1、包含头文件在内的依赖关系(自动生成依赖文件)

我们使用前面一样的程序来进行实验:
a.c:

#include <stdio.h>
void funB();
void funC();
int main() {
	funB();
	funC();
	return 0;
}

b.c:

#include <stdio.h>
void funB() {
	printf("hello B!\n");

}

c.c:(进行了一点点修改)

#include <stdio.h>
#include "c.h"
void funC() {
	printf("This is C=%d\n",C);
}

新建一个c.h

#define C 1 

然后我们make加执行一下:
在这里插入图片描述
在这里插入图片描述
我们这里做一个小小的改动,把头文件中define的数从1改为2:

#define C 2 

然后我们再make一下看看效果:
在这里插入图片描述
我们可以看到make并没有顺利执行,而且C依然为1 ,说明还是有点小问题

那这是因为什么原因导致的呢:?
因为我们的c.c是依赖于c.h的,但是makefile中并没有把这种依赖关系写出来,所以makefile也不知道c.h更新了。

我们再makefile中重新添加了:

c.o:c.c c.h

在这里插入图片描述
然后我们再make一下就对了:
请添加图片描述
但是这样做是不可能的,在大型项目里面,我们每一个C文件几乎都有头文件,我们不可能手动把这些头文件的依赖关系一行行在makefile全部都写出来,我们需要自动去生成这些规则。


在讲解今天的正式内容前,我们先介绍三个查看依赖关系的命令:

gcc -M c.c

上述命令会使用 gcc 编译器并使用 -M 选项来生成 c.c 源文件的依赖关系,是立刻打印出来

请添加图片描述

gcc -M -MF c.d c.c

这个命令也会生成 c.c 源文件的依赖关系,但是通过 -MF c.d 选项指定了输出文件为 c.d。这意味着生成的依赖关系将被保存到 c.d 文件中,而不是输出到标准输出流。
在这里插入图片描述

gcc -c -o c.o c.c -MD -MF c.d

这个命令用于编译 c.c 源文件为目标文件 c.o。参数 -c 表示编译成目标文件,-o c.o 指定输出文件为 c.o。-MD 选项用于生成 .d 文件,-MF c.d 则指定生成的依赖关系文件为 c.d。这意味着除了生成目标文件 c.o 外,还会生成一个描述依赖关系的文件 c.d。
在这里插入图片描述
按照我们刚刚介绍的gcc依赖关系规则,我们修改一下makefile:
在这里插入图片描述
在这里插入图片描述
(ls 命令用于列出目录中的文件和子目录。而 ls -a 命令也会列出目录中所有的文件和子目录,包括以 . 开头的隐藏文件或隐藏目录,这些文件或目录在普通的 ls 命令中是不可见的。)

从这里我们可以看到这些依赖关系被自动生成出来了
刚刚makefile里的这句话就可以不用写了:

c.o:c.c c.h

我们再改一下makefile:
在这里插入图片描述
这一行使用了 Makefile 中的函数 patsubst,它用于替换模式。具体来说,% 是一个通配符,表示每个目标文件名。 ( p a t s u b s t (patsubst %,.%.d, (patsubst(objs)) 的作用是将目标文件列表中的每个目标文件名(a.o, b.o, c.o)替换成相应的依赖关系文件名(.a.o.d, .b.o.d, .c.o.d)。
在这里插入图片描述
可以看到我们的依赖文件已经被生成出来了。

接下来我们再改一改,把这些检测到的依赖文件包含进去:
在这里插入图片描述

objs=a.o b.o c.o
dep_files:=$(patsubst %,.%.d,$(objs))
dep_files:=$(wildcard $(dep_files))

这里定义了目标文件列表 objs 和依赖关系文件列表 dep_files。使用 patsubst 函数将目标文件列表转换为相应的依赖关系文件列表,然后通过 wildcard 函数获取实际存在的依赖关系文件。

ifneq ($(dep_files),)
include $(dep_files)
endif

这里使用条件语句检查是否存在依赖关系文件列表 dep_files,如果存在,则通过 include 关键字包含这些依赖关系文件。这样,Make 就能够了解源文件之间的依赖关系,从而在需要重新编译时执行相应的规则。

我们这时候试一下修改c.h里的宏定义如下:

#define C 3 

这时候我们再make就不会再出现之前的情况了:即宏定义改了make之后打印出来依然不变的情况
最后结果:
在这里插入图片描述
我们可以看到改为了3,make后就自动识别了头文件的依赖关系,打印出来了3,实现了我们最初的目标:自动识别依赖关系(自动生成依赖文件)。

5.2、添加CFLAGS

我们在makefile里添加几条命令:
在这里插入图片描述
CFLAGS=-Werror 设置了一个编译选项,即启用了 -Werror。这个选项的含义是将所有警告视为错误,即编译过程中如果产生了任何警告,就会导致编译失败。这样做的目的是强制要求代码中不允许存在任何警告,以确保代码的质量和稳定性。

CFLAGS 是一个用于存储传递给 C 编译器的额外参数和标志的 Makefile 变量。这些参数和标志可以影响编译的行为,例如警告级别、优化选项、头文件路径等 在 Makefile 中使用 CFLAGS 变量有助于集中管理编译选项,使得构建过程更加灵活和易于维护。

当你设置 CFLAGS 时,可以包含各种编译器选项,这些选项会影响代码的编译和生成。以下是一些常见的 CFLAGS 选项的例子:

启用调试信息:

CFLAGS = -g

这个选项启用了编译器生成的调试信息,有助于在调试阶段中进行源代码级别的调试。

优化级别:

CFLAGS = -O2

这个选项启用了优化级别 2,以提高生成代码的运行性能。可选的优化级别包括 -O0(无优化)、-O1、-O2、-O3 等。

指定头文件搜索路径:

CFLAGS = -I/path/to/include

这个选项指定了编译器在搜索头文件时要查找的路径。

定义宏:

CFLAGS = -DDEBUG

这个选项定义了一个名为 DEBUG 的宏,可以在源代码中使用条件编译。

关闭某些警告:

CFLAGS = -Wno-unused-variable

这个选项关闭了关于未使用变量的警告。

启用全部警告:

CFLAGS = -Wall -Wextra

这个选项启用了大多数可用的警告,帮助开发者发现潜在的问题。

指定目标架构:

CFLAGS = -march=native

这个选项根据编译运行代码的计算机的架构进行优化。

来个实际点的makefile例子:

CC = gcc
CFLAGS = -g

# 目标文件
TARGET = my_program

# 源文件
SRC = main.c

all: $(TARGET)

$(TARGET): $(SRC)
    $(CC) $(CFLAGS) -o $(TARGET) $(SRC)

clean:
    rm -f $(TARGET)

在这个例子中:

CC 定义了编译器的可执行文件(gcc)。
CFLAGS 包含了编译器选项 -g,表示启用调试信息。
TARGET 定义了目标文件的名称为 my_program。
SRC 定义了源文件的名称为 main.c。

Makefile 中的规则:
all 是默认目标,它依赖于 $(TARGET),当你运行 make 时,它将编译生成目标文件。
$(TARGET) 的规则指定了如何生成目标文件。在这里,它使用 gcc 编译器,传递了 CFLAGS 和源文件,生成可执行文件 my_program。
clean 规则用于清理生成的文件,执行 make clean 将删除可执行文件。

六、通用Makefile模板

这个意思就是找一个经典的makefile模板 以后要写自己的makefile就在这个基础上改就行了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1364394.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

商品期货交易中的强行平仓:交易所的规定和风险控制

在商品期货交易中&#xff0c;保证金充足的情况下&#xff0c;一般不会被强行平仓。然而&#xff0c;有几种情况可能会导致强行平仓的发生&#xff1a; 1 持仓超过交易所限仓规定&#xff1a;交易所会设定限仓规定&#xff0c;限制每位投资者的持仓数量。如果超过限仓规定&…

如何使用 CMake 来构建一个共享库(动态库)

tutorial_4/CMakeLists.txt # 声明要求的 cmake 最低版本 cmake_minimum_required( VERSION 2.8 )# 声明一个 cmake 工程 project( HelloSLAM )add_subdirectory(src)tutorial_4/src/CMakeLists.txt #工程添加多个特定的头文件搜索路径 include_directories(include)set(LIBR…

静态路由、代理ARP

目录 静态路由静态路由指明下一跳和指明端口的区别代理ARP 我们知道&#xff0c;跨网络通信需要路由 路由有三种类型&#xff1a; 1.直连路由。 自动产生的路由&#xff0c;当网络设备连接到同一网络时&#xff0c;他们可以自动学习到对方的存在。自动学习相邻网络设备的直连信…

python编程从入门到实践(3+4)操作列表+if语句

文章目录 第四章 列表操作4.1遍历整个列表&#xff1a;可能会发生变化的数值&#xff0c;列表可修改4.1.2遍历中的缩进 4.3创建数值列表4.3.1 使用range&#xff08;&#xff09;函数range&#xff08;i&#xff0c;m&#xff09;输出从i到m-1range(m) 打印从0到m-1 4.3.1 使用…

Java集合框架概念详解

目录 1. 什么是Java集合框架&#xff1f;2. 常用接口介绍3. 常用实现类介绍4. 集合框架的应用场景 前言&#xff1a; Java集合框架是Java编程中最重要的工具之一。它提供了一套强大而灵活的数据结构和算法&#xff0c;用于存储和操作数据。本文将详细介绍Java集合框架的概念、常…

数据结构—环形缓冲区

写在前面&#xff0c;2023年11月开始进入岗位&#xff0c;工作岗位是嵌入式软件工程师。2024年是上班的第一年的&#xff0c;希望今年收获满满&#xff0c;增长见闻。 数据结构—环形缓冲区 为什么要使用环形数组&#xff0c;环形数组比起原来的常规数组的优势是什么&#xf…

CLIP is Also an Efficient Segmenter

表1 复现结果–Seed&#xff1a;70.7245673447014&#xff0c;dCRF&#xff1a;74.85437742935268 误差小于0.5个点&#xff0c;可以接受 表4 复现结果–训练300轮&#xff0c;Val&#xff1a;58.76741354153312&#xff0c;Test&#xff1a;59.18210 感想 VOC全部复现完成&…

spring事务默认传播机制REQUIRED的试验(手动开启事务代码+feign远程调用)

transactional注解&#xff0c;默认啥都不指定的时候&#xff0c;我们使用的就是PROPAGATION_REQUIRED这种方式。 PROPAGATION_REQUIRED:业务方法需要在一个事务中运行&#xff0c;如果方法运行时&#xff0c;已处在一个事务中&#xff0c;那么就加入该事务&#xff0c;否则自…

Linux操作系统基础(12):Linux的Shell解释器

1. Shell的介绍 在Linux中&#xff0c;Shell 是一种命令行解释器&#xff0c;它是用户与操作系统内核之间的接口&#xff0c;它负责解释用户输入的命令&#xff0c;并将其转换成系统调用或其他操作系统能够执行的指令。 Shell 提供了一种交互式的方式来与操作系统进行通信&am…

关于使用统一服务器,vscode和网页版jupyter notebook的交互问题

autodl 查看虚拟环境 在antodl上租借了一个服务器&#xff0c;通过在网页上运行jupyter notebook和在vscode中运行&#xff0c;发现环境都默认的是miniconda3。 conda info --envs 当然环境中所有的包都是一样的。 要查看当前虚拟环境中安装的所有包&#xff0c;可以使用以…

C++流媒体服务器 ZLMediaKit框架ZLToolKit源码解读

ZLMediaKit是国人开发的开源C流媒体服务器&#xff0c;同SRS一样是主流的流媒体服务器。 ZLToolKit是基于C11的高性能服务器框架&#xff0c;和ZLMediaKit是同一个作者&#xff0c;ZLMediaKit正是使用该框架开发的。 ZLMediaKit开源地址&#xff1a;https://github.com/ZLMedi…

CP_AutoSar目录

目录 一、RTE二、模式和状态管理三、BSW四、工具链相关五、杂项六、优化相关 一些笔记和日常记录。有部分未包含在此目录中。 一、RTE [AutoSar]基础部分 RTE 01 介绍 [AutoSar]基础部分 RTE 02 S/R Port 显式/隐式 [AutoSar]基础部分 RTE 03 C/S Port 同步/异步 [AutoSar]基…

VELO维乐携手【晓饰记】创始人胡晓,引领潮流新饰界!

不知道大家还记不记得2023年维乐带着自己满满的诚意闪现英伦时尚之都为全世界带来了一场无与伦比的视觉盛宴&#xff01;而依照维乐固有的执念&#xff0c;从不会让自己止步的精神&#xff0c;维乐又带着自己的维乐坐垫找到了CoCo胡晓&#xff0c;【晓饰记】的首饰品牌创始人、…

Spanner on a modern columnar storage engine 中文翻译

文章目录 0. 摘要1. 存储引擎2. 存储引擎迁移的挑战2.1 可靠性、可用性和数据完整性2.2 性能和成本2.3 复杂性 3. 迁移可靠性的系统原则方法3.1 可靠性原则和自动化架构3.2 迁移方案和按周迁移3.3 客户 部署感知 调度3.4 管理可靠性、可用性和性能 4. 项目管理和驱动指标概括 0…

FastDFS安装与测试

目录 目标 版本 环境 官方文档 相关概念 安装FastDFS 启动FastDFS 关闭FastDFS 重启FastDFS 用命令测试上传文件 用命令测试下载文件 用命令测试删除文件 用HTTP的方式访问FastDFS中的文件 用HTTP的方式访问FastDFS中的文件整体流程 目标 在Linux服务器上搭建单…

brpc之接口Protocol

简介 brpc主要是通过Protocol这个接口来支持多协议的。其提供了解析&#xff0c;序列化&#xff0c;处理请求与响应的函数指针&#xff0c;通过函数指针以达到多态的效果 Protocol 结构体定义如下 struct Protocol {typedef ParseResult (*Parse)(butil::IOBuf* source, So…

Django(六)

员工管理系统(用户管理&#xff09; {% extends layout.html %}{% block content %}<div class"container"><div style"margin-bottom: 10px"><a class"btn btn-success" href"#"><span class"glyphicon gl…

【Unity美术】如何用3DsMax做一个水桶模型

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

《GreenPlum系列》GreenPlum详细入门教程01-GreenPlum介绍

文章目录 第一章 GreenPlum介绍1.MPP架构介绍2.GreenPlum介绍3.GreenPlum数据库架构4.GreenPlum数据库优缺点 GreenPlum&#xff1a;https://cn.greenplum.org/ 第一章 GreenPlum介绍 1.MPP架构介绍 MPP是Massively Parallel Processing的缩写&#xff0c;也就是大规模并行处…

大数据 - Doris系列《一》- Doris简介

目录 &#x1f436;1.1 Doris 概述 &#x1f436;1.2 OLAP和OLTP&#xff08;面试&#xff09; 1. 应用场景 &#x1f959;联机事务处理OLTP(On-Line Transaction Processing) &#x1f959;联机分析处理OLAP(On-Line Analytical Processing) 2. OLAP和OLTP比较--“用户行…