linux交叉编译学习过程中第一次遇到的玩意、学习前提悉知的知识点?
linux交叉编译实操——交叉编译wiringOP库
linux交叉编译wiringOP库学习过程中遇到的一些疑惑点?
linux交叉编译实操——交叉编译智能分类项目
aarch64-none-linux-gnu-gcc 是一个交叉编译工具链,用于在其他架构的系统(通常是 x86_64 架构的计算机)上编译 64 位 ARM 架构的程序。 例如在 x86 架构的 PC 上编译出能运行在 ARM 架构的嵌入式设备上的程序。它基于 GCC(GNU Compiler Collection)编译器。
为什么叫工具链?在计算机科学中,“工具链”一词通常指的是一组按照特定顺序执行的工具,它们共同完成一个复杂的任务。
对于编译过程来说,通常包括以下几个步骤:
预处理:对源代码进行文本替换,例如包含头文件、宏展开等。
编译:将预处理后的代码编译为汇编语言或中间代码。
汇编:将汇编语言或中间代码转换为机器语言的目标文件。
链接:将目标文件和所需的库链接在一起,生成最终的可执行文件。
这些步骤通常由不同的工具来完成,例如编译器、汇编器、链接器等。当这些工具按照正确的顺序和配置组合在一起时,就形成了一个“工具链”。
它被称为“交叉编译工具链”是因为它涉及了两种不同的平台:编译平台(宿主机)和目标平台(目标机)。
开发者在宿主机上使用这个工具链编译代码,生成的程序可以在目标机上运行。这个过程就像是在两个不同的平台之间“交叉”工作,因此得名为“交叉编译工具链”。
主要讲述了如何使用交叉编译工具链来编译 wiringOP 库,并将其安装到目标设备上。下面我会用通俗的语言解释每一步的作用,并做出相应的解释。
在 echo "WiringPi Library" 之前添加以下代码,用于创建一些目录:
mkdir $PWD/_INSTALL/usr/local/bin -p
mkdir $PWD/_INSTALL/usr/local/include -p
mkdir $PWD/_INSTALL/usr/local/lib -p
这些目录将用于存放编译后的库文件和头文件。
将所有 Makefile 中的 CC := gcc 改成 CC := aarch64-none-linux-gnu-gcc。
这是因为我们使用交叉编译工具链来编译库文件,而不是直接在目标设备上编译。
将 DESTDIR?=/usr 替换为 DESTDIR?= $(shell pwd)/../_INSTALL/usr。
这样可以指定编译后的库文件和头文件的安装路径。
修改库文件的符号链接,使其指向正确的路径。具体来说,就是将 $Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so
修改为
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPi.so。
同上,修改 devLib/Makefile 中的符号链接,使其指向正确的路径。
将 INCLUDE = -I. 修改为 INCLUDE = -I. -I$(DESTDIR)$(PREFIX)/include,
以确保在编译时包含正确的头文件路径。
执行 ./build 命令来编译库文件。在选择板子时,输入 26,选择 orangepizero2。
在 wiringOP-master 目录下会生成一个 _INSTALL 目录,里面包含了编译好的库文件和头文件。
将 _INSTALL 目录中的内容拷贝到目标设备(香橙派)的根目录下。
因为前面已经修改了几个文件的符号链接(软链),所以在目标设备(香橙派)上执行 sudo ldconfig 命令更新一下符号链接(软链)。
sudo ldconfig 是一个命令,用于更新系统的动态链接库缓存。在将编译好的库文件和头文件拷贝到香橙派的根目录后,需要运行这个命令来更新系统的动态链接库缓存(ldconfig 命令会扫描指定目录中的动态库文件,并将它们的信息添加到系统的动态链接库缓存中),这样,当其他程序需要使用这些库文件时,系统能够快速找到并加载它们。
在目标设备上执行 sudo gpio readall 命令,以测试库是否链接正常。
因为 gpio readall 命令就是 wiringPi 库提供的一个命令行工具,这个命令用来读取树莓派或其他单板计算机(香橙派)GPIO 引脚状态的,
那我们在安装和配置好 wiringPi 库后,运行 sudo gpio readall,如果命令能够正确输出每个引脚的状态,那么说明 wiringPi 库已经正确链接并能够正常工作。
通过以上步骤,我们就可以使用交叉编译工具链来编译 wiringOP 库,并将其安装到目标设备上,以便在目标设备上使用该库进行开发。
在嵌入式开发中,像香橙派这样的单板计算机,需要构建特定的库来提供对硬件的控制。wiringPi 和 devLib 是两个常用的库。
wiringPi 是一个用于树莓派的 GPIO(通用输入输出)访问库,也适用于其他类似的单板计算机,如香橙派。它提供了一组简单易用的函数,用于设置和读取 GPIO 引脚的状态,控制 LED、传感器和其他外设。
devLib 是一个与 wiringPi 相关的库,提供了额外的设备支持或特定的功能。它包含一些特定硬件或项目需求的自定义代码和函数。
INCLUDE 变量是一个在 Makefile 文件中定义的变量,用于指定编译时包含的头文件路径。它通常在编译命令中使用,以确保编译器能够找到所需的头文件。
build.sh 是一个 shell 脚本,用于自动化编译和构建库文件的过程。它会调用 Makefile 文件中的规则来执行具体的编译和构建任务。
devLib/Makefile 和 wiringPi/Makefile 是具体到 devLib 和 wiringPi 库的构建文件。它们是 Makefile 文件,包含了与 devLib 和 wiringPi 库相关的编译和构建规则。
INCLUDE 变量是一个在 Makefile 文件中定义的变量,用于指定编译时包含的头文件路径。它通常在编译命令中使用,以确保编译器能够找到所需的头文件。
INCLUDE 变量用于指定编译时包含的头文件路径。
在 Makefile 中,-I 选项用于指定头文件的搜索路径。
因此,-I 加一个. 表示在当前目录中搜索头文件,
而 -I$(DESTDIR)$(PREFIX)/include 表示在由 DESTDIR 和 PREFIX 变量指定的目录中搜索头文件。
将 INCLUDE = -I. 修改为 INCLUDE = -I. -I$(DESTDIR)$(PREFIX)/include。这一步多添加了一个新的头文件搜索路径
例如,将:
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so
修改为:
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPi.so
这个路径是我们创建出来的临时目录,在交叉编译项目的时候,临时放一些库文件和头文件。
修改后是:
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libwiringPi.so
为什么不直接写这一条:
$Q ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION)`
又或者只写这一条:
`$(DESTDIR)$(PREFIX)/lib/libwiringPi.so
而是要两条都写呢?
libwiringPi.so 实际上就是一个方便的引用,我们在很多其它程序中,可以直接写libwiringPi.so 。然后libwiringPi.so又指向libwiringPi.so.$(VERSION),而libwiringPi.so.$(VERSION)中的$(VERSION)是一个版本变量,这个变量我们只需要修改它一次,就可以让所有调用过libwiringPi.so的程序,指向libwiringPi.so.$(VERSION),从而指向最新的版本或某个特定版本的库文件。
所以只要在程序中调用libwiringPi.so,它都是指向libwiringPi.so.$(VERSION),它总是指向最新或者我们需要的某个特定版本的库文件。应用程序可以通过这个软链接找到并使用正确版本库文件。
下面这部分描述了如何在Linux环境下的宿主机进行交叉编译,以便在目标设备(例如香橙派)上运行智能分类工程代码。下面我将用通俗易懂的语言解释这段话,帮助我们理解。
原有项目的目录结构如下:
test@test:~/garbage$ tree
.
├── garbage.c
├── garbage.h
├── garbage.py
├── main.c
├── myoled.c
├── myoled.h
├── pwm.c
├── pwm.h
├── socket.c
├── socket.h
├── uartTool.c
└── uartTool.h
这里列出了项目中的所有文件,包括源代码文件(.c)、头文件(.h)和Python脚本文件(.py)。
为了更好地组织项目文件,我们将调整目录结构:
test@test:~/garbage$ tree -a
.
├── inc
│ ├── garbage.h
│ ├── myoled.h
│ ├── pwm.h
│ ├── socket.h
│ └── uartTool.h
├── src
│ ├── garbage.c
│ ├── garbage.py
│ ├── main.c
│ ├── myoled.c
│ ├── pwm.c
│ ├── socket.c
│ └── uartTool.c
我们创建了两个新的目录:
inc 用于存放头文件(这里放都是我们自己封装的头文件,就是上面那些.h结尾的,为了让我们的主程序main更加简洁,还有就是方便管理和开发程序),
src 用于存放源代码文件。这样可以使项目结构更清晰,便于管理和维护。
我们需要增加一个名为3rd的目录(这个3代表第三方的意思),用于存放第三方依赖库和头文件,例如wiringOP库和python3.10库。
wiringOP库 :
这里提到的wiringOP库就是(一、交叉编译wiringOP库的配置过程解释)这一节讲的编译的东西。
新增的宿主机的3rd目录就是用来存放编译wiringOP库出来的头文件和库文件。
因为我们已经编译过了,我们直接拷贝那一节(一、交叉编译wiringOP库的配置过程解释)讲的wiringOP库编译出来的头文件和库文件到宿主机的3rd目录下就好了。
当时编译完就放在了目录 wiringOP-master下的_INSTALL 中 。
①cd切换到该路径:
~$ cd test/wiringOP-master
~$ cd test/wiringOP-master
②cp复制 wiringOP-master 目录下的 _INSTALL 的全部文件到~/garbage/3rd 下:
~/test/wiringOP-master$ cp _INSTALL/* ~/garbage/3rd/ -af
~/test/wiringOP-master$ cp _INSTALL/* ~/garbage/3rd/ -af
①切换到香橙派系统的命令窗口,在香橙派的命令窗口使用apt download命令下载所需的依赖库包
apt download zlib1g zlib1g-dev libpython3.10 libpython3.10-dev libexpat1 libexpat1-dev libcrypt1 libcrypt-dev
②从香橙派上,scp复制刚刚下载的所有.deb包到宿主机上(例如你的开发电脑)。
scp *.deb test@192.168.1.10:/home/test #test为宿主机用户名, 192.168.1.10为宿主机ip
## cp命令用于本地复制
## scp命令用于在本地系统和远程服务器之间复制,需要远程服务器的密码
③然后,切换到宿主机上(例如你的开发电脑),使用dpkg -x命令将这些.deb包文件解压到garbage/3rd目录下。
下面这 libpython3.10 压缩包解压下来里面是库文件, libpython3.10-dev带dev后缀的压缩包解压下来是这些库文件的头文件,我们是通过头文件来引用这些库的。
dpkg -x libpython3.10_3.10.12-1~22.04.2_arm64.deb garbage/3rd
dpkg -x libpython3.10-dev_3.10.12-1~22.04.2_arm64.deb garbage/3rd/
原始是这样的:
dpkg -x libpython3.10_3.10.12-1~22.04.2_arm64.deb garbage/3rd
dpkg -x libpython3.10-dev_3.10.12-1~22.04.2_arm64.deb garbage/3rd/
dpkg -x libcrypt1_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x libexpat1_2.4.7-1ubuntu0.2_arm64.deb garbage/3rd/
dpkg -x libpython3.10-dev_3.10.12-1~22.04.2_arm64.deb garbage/3rd/
dpkg -x libpython3.10_3.10.12-1~22.04.2_arm64.deb garbage/3rd
dpkg -x libexpat1_2.4.7-1ubuntu0.2_arm64.deb garbage/3rd/
dpkg -x libexpat1-dev_2.4.7-1ubuntu0.2_arm64.deb garbage/3rd/
dpkg -x libcrypt1_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x zlib1g_1%3a1.2.11.dfsg-2ubuntu9.2_arm64.deb garbage/3rd/
dpkg -x libcrypt-dev_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu9.2_arm64.deb garbage/3rd/
下面是我把库文件和对应的库文件的头文件空行出来,发现有些重复:
dpkg -x libpython3.10_3.10.12-1~22.04.2_arm64.deb garbage/3rd
dpkg -x libpython3.10-dev_3.10.12-1~22.04.2_arm64.deb garbage/3rd/
dpkg -x libcrypt1_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x libcrypt1_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x libcrypt-dev_1%3a4.4.27-1_arm64.deb garbage/3rd/
dpkg -x libpython3.10_3.10.12-1~22.04.2_arm64.deb garbage/3rd
dpkg -x libpython3.10-dev_3.10.12-1~22.04.2_arm64.deb garbage/3rd/
dpkg -x libexpat1_2.4.7-1ubuntu0.2_arm64.deb garbage/3rd/
dpkg -x libexpat1_2.4.7-1ubuntu0.2_arm64.deb garbage/3rd/
dpkg -x libexpat1-dev_2.4.7-1ubuntu0.2_arm64.deb garbage/3rd/
dpkg -x zlib1g_1%3a1.2.11.dfsg-2ubuntu9.2_arm64.deb garbage/3rd/
dpkg -x zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu9.2_arm64.deb garbage/3rd/
由于默认提供的交叉编译工具版本(aarch64-none-linux-gnu-gcc 9.2.0)如果去加载上面的依赖库,会出现库版本的依赖问题。 因此,宿主机安装(aarch64-linux-gnu-gc 11.2)版本并使用该交叉编译工具:
sudo apt intall gcc-aarch64-linux-gnu
make运行时,发现报错,找到其中一条报错:前面有aarch64-none-linux-gnu相关字符,说明是编译器的问题,然后后面直接报错undefined reference to 'mknod@GLIBC_2.33。
再找到另外十几条报错都是前面一样,后面都是直接报这个undefined reference to '(只是这里不一样,都是不同的字符)@GLIBC_2.33。
所以报错都是前面一模一样,后面只有一个地方不一样,而且都是各种不同的变量或字符,说明就是编译器可能版本依赖问题,才导致编译的时候全部都是只有那个编译不了不同的变量出问题。
然后我们使用aarch64-none-linux-gnu --version命令查看一下宿主机这里的编译器版本,会发现是9.2.1版本,显示如果如下:
aarch64-none-linux-gnu-gcc (GCC) 9.2.1 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
因为之前在香橙派直接编译的时候是可以的,我们看看香橙派是什么版本的。
切换到香橙派命令窗口,使用dpkg -l | grep libc命令查找与libc相关的已安装软件包列出来,然后直接看到libc6:arm64的版本是2.35的,它的ibc的库是2.35版本的。而刚刚我们上面在(pc)宿主机报错是链接的2.33的libc。宿主机的libc版本是比较低的。
然后我们再用gcc --version命令看看香橙派默认的编译器版本,会发现是11.2.0版本,显示如果如下:
gcc(ubuntu 11.2.0-19ubuntu1)11.2.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
所以我们用9.2.1版本的编译器去编译的时候,宿主机上的lib c的版本是比较低比较老的,所以在链接一些库的时候会链接失败。
到软件源上看看官方有没有提供交叉编译工具,执行 apt-cache search gcc | grep aarch64,从APT数据库缓存中搜索所有描述中含有gcc关键字的软件包,并从中筛选出那些名称或描述中还含有aarch64字样的软件包(这可以找到适用于ARM 64位架构的GCC交叉编译器或其他相关工具)。
发现软件源里是有提供交叉编译工具的,输出里有条:gcc-aarch64-linux-gnu - GNU C compiler for the arm64 architecture,我们直接命令去安装这个软件源提供的交叉编译器:
sudo apt intall gcc-aarch64-linux-gnu
安装完后,用命令再查一下这个交叉编译器的版本,会发现是11.4.0版本的,然后就make执行,发现是可以的。:
aarch64-linux-gnu-gcc --version
APT是在Debian中使用的包管理系统。
软件源通常包括官方仓库和其他第三方仓库
我们需要编写一个Makefile文件,用于配置编译选项和依赖关系。Makefile文件的内容如下:
CC := aarch64-linux-gnu-gcc
SRC := $(shell find src -name "*.c")
INC := ./inc \
./3rd/usr/local/include \
./3rd/usr/include \
./3rd/usr/include/python3.10 \
./3rd/usr/include/aarch64-linux-gnu/python3.10 \
./3rd/usr/include/aarch64-linux-gnu
OBJ := $(subst src/,obj/,$(SRC:.c=.o))
TARGET=obj/garbage
CFLAGS := $(foreach item, $(INC),-I$(item)) # -I./inc -I./3rd/usr/local/include
LIBS_PATH := ./3rd/usr/local/lib \
./3rd/lib/aarch64-linux-gnu \
./3rd/usr/lib/aarch64-linux-gnu \
./3rd/usr/lib/python3.10
LDFLAGS := $(foreach item, $(LIBS_PATH),-L$(item)) # -L./3rd/usr/local/libs
LIBS := -lwiringPi -lpython3.10 -pthread -lexpat -lz -lcrypt
obj/%.o:src/%.c
mkdir -p obj
$(CC) -o $@ -c $< $(CFLAGS)
$(TARGET) :$(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)
compile : $(TARGET)
clean:
rm $(TARGET) obj $(OBJ) -rf
debug:
echo $(CC)
echo $(SRC)
echo $(INC)
echo $(OBJ)
echo $(TARGET)
echo $(CFLAGS)
echo $(LDFLAGS)
echo $(LIBS)
.PHONY: clean compile debug
这个Makefile文件定义了编译器gcc、源文件SRC、头文件INC、目标文件OBJ、编译选项CFLAGS 和链接选项LDFLAGS、LIBS等;
规定了临时目标文件 OBJ、最终目标可执行文件TARGET的生成规则;
以及伪目标clean、compile、debug的执行规则。
最后,我们在工程目录下执行make命令进行编译,会在garbage项目的obj目录下生成一堆.o文件和garbage可执行文件。然后scp命令将garbage可执行文件复制到香橙派:/home/orangepi目录上,就可以在香橙派上运行了:
:~/garbage/obj$ scp garbage orangepi@192.168.1.18:/home/orangepi #orangepi为宿主机用户名, 192.168.1.18为香橙派的ip
:~/garbage/obj$ scp garbage orangepi@192.168.1.18:/home/orangepi #orangepi为宿主机用户名, 192.168.1.18为香橙派的ip
最后可能也要把garbage项目的src目录下的garbage.py也复制到香橙派上
:~/garbage/src$ scp garbage.py orangepi@192.168.1.18:/home/orangepi #orangepi为宿主机用户名, 192.168.1.18为香橙派的ip
返回到香橙派上,用ls命令列出所有文件,看到garbage可执行文件,
使用命令执行garbage可执行文件,运行成功。
:~$ sudo -E ./garbage
sudo -E ./garbage
通过以上步骤,我们就可以在Linux环境下的宿主机进行交叉编译,并将智能分类的工程代码运行在目标设备(例如香橙派)上。
#—— —— —— —— —— 【一、定义】—— —— —— —— ——
CC := aarch64-linux-gnu-gcc #定义编译器
#———— 1.设置临时目标文件的名称。
#在生成(最终目标文件 TARGET )前,
#我们要生成(临时目标文件 OBJ ),这是生成目标文件所需要的依赖文件
#这里先把(临时目标文件 OBJ )路径名字都定义好,真正的实现在下面的目标(主程序),有实现的规则。
SRC := $(shell find src -name "*.c") #查找src所有.c文件名 (源文件列表)
OBJ := $(subst src/,obj/,$(SRC:.c=.o)) #把刚刚的查找到的SRC所有的.c文件名替换为.o文件名,
#并将路径从src/替换成obj/ (把源文件列表转换为目标文件列表)
#———— 2.设置最终生成的可执行文件的名称。
#本项目中想要生成的(最终目标文件 TARGET )
#这里也一样先把(最终目标文件 TARGET )路径名字都定义好,真正的实现在下面的目标(主程序),有实现的规则。
TARGET=obj/garbage
#———— 3.头文件的路径
INC := ./inc \ #原始我们自己封装的头文件路径
./3rd/usr/local/include \ #编译wiringOP库得到的库文件所在路径
./3rd/usr/include \ #这个包括下面这些都是步骤4解压出来的
./3rd/usr/include/python3.10 \
./3rd/usr/include/aarch64-linux-gnu/python3.10 \
./3rd/usr/include/aarch64-linux-gnu
#设置编译器的选项 —— 头文件的路径,全部加个-I
#在命令行中输入命令需要附加头文件路径时候要加-I
CFLAGS := $(foreach item, $(INC),-I$(item)) # -I./inc -I./3rd/usr/local/include
#———— 4.库文件的路径 (这个工程依赖的第三方头文件和库)
#在香橙派直接编译智能垃圾桶代码的时候,因为这些库 -lwiringPi -lpython3.10 香橙派本来就有,
#在香橙派系统的默认库路径下,所以直接在命令后面加具体的库就行 -lwiringPi -lpython3.10 ,
#( gcc -o garbagetest garbagetest.c garbage.c garbage.h -I /usr/include/python3.10 -lwiringPi -l python3.10 )
#但是在宿主机(PC X86)交叉编译项目的时候,这些库宿主机是没有的,
#所以需要把用到的库,它们的路径都写出来加上-L ,提供给编译器。
#在编译这些库的时候,可以让编辑器去这些库的路径下去找到这些库
# -L./3rd/usr/local/libs -L... -lwiringPi -lpython3.10 。
LIBS_PATH := ./3rd/usr/local/lib \ #编译wiringOP库得到的库文件路径
./3rd/lib/aarch64-linux-gnu \ #这个包括下面这些都是步骤4解压出来的
./3rd/usr/lib/aarch64-linux-gnu \
./3rd/usr/lib/python3.10
#设置链接器的选项 —— 库文件的路径,全部加个-L
#在命令行中输入命令需要附加库文件的路径时要加个-L
LDFLAGS := $(foreach item, $(LIBS_PATH),-L$(item)) # -L./3rd/usr/local/libs
#———— 5.设置需要用的具体的库 —— 链接器会从上面的库路径去找这几个库链接
LIBS := -lwiringPi -lpython3.10 -pthread -lexpat -lz -lcrypt
#—— —— —— —— —— 【二、目标(主程序)真正生成文件的地方】—— —— —— —— —
#规则 —— 从源文件生成目标文件(临时文件)
# obj文件的生成规则(OBJ变量下所有叫obj的文件)
obj/%.o:src/%.c
mkdir -p obj
$(CC) -o $@ -c $< $(CFLAGS)
#规则 —— 从目标文件生成最终可执行文件(最终文件)
$(TARGET) :$(OBJ)
$(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LIBS)
#—— —— —— —— ——【三、伪目标】—— —— —— —— ——
#伪目标 —— 编译项目。
compile : $(TARGET)
#伪目标 —— 清理项目。
clean:
rm $(TARGET) obj $(OBJ) -rf
#伪目标 —— 调试,定义一个伪目标来打印变量的值以进行调试。
debug:
echo $(CC)
echo $(SRC)
echo $(INC)
echo $(OBJ)
echo $(TARGET)
echo $(CFLAGS)
echo $(LDFLAGS)
echo $(LIBS)
#定义伪目标属性 —— 将上面的伪目标标记为伪目标,以防止Makefile将它们视为文件名。
.PHONY: clean compile debug
在香橙派中使用apt download命令下载依赖库文件,apt download命令会从香橙派的软件包仓库中下载指定的依赖库文件,这些文件通常以.deb格式存在。这些软件包可以被系统包管理器(如 apt)用来安装、更新或删除软件。
当你使用apt download命令下载软件包时,这些软件包并不是存储在香橙派本身的内存或存储空间中,而是从互联网上的软件包仓库服务器获取。
具体来说,软件包仓库通常是由香橙派所使用的Linux发行版维护者提供的一个远程服务器集合。例如,如果你的香橙派上安装的是Armbian或者Ubuntu等操作系统,那么软件包仓库会是Canonical、Debian项目或其他相关组织维护的服务器。这些服务器存放了大量的.deb格式的软件包文件,用户可以通过网络访问它们来下载和安装所需的软件。
在你的香橙派上,/etc/apt/sources.list文件以及 /etc/apt/sources.list.d/目录下的文件定义了哪些软件包仓库将被用来搜索和下载软件包。当你执行 apt update命令时,APT会读取这些配置文件,并且连接到指定的仓库更新本地的软件包索引。而当你使用apt download或apt-get install等命令时,APT将会根据这个索引来查找并下载相应的.deb文件。
总结一下,.deb格式的依赖库文件并不直接存放在香橙派的内存或存储设备里,而是存放在由操作系统提供商或第三方维护的远程服务器上。香橙派通过网络与这些仓库进行通信,以完成软件包的下载和安装。