C/C++嵌入式开发环境搭建,Qt交叉编译,cmake交叉编译,clion/vscode远程开发

目录

  • 交叉编译简介
  • cmake 交叉编译
  • clion 交叉编译
  • vscode 远程嵌入式开发
  • Qt交叉编译
    • 1.安装交叉编译工具
    • 2.交叉编译qt库
    • 3.将交叉编译的Qt库复制到板子上
    • 4.安装和配置 Qt Creator,支持交叉编译
    • 5.QT嵌入式开发
    • 6.QT嵌入式开发报错解决
      • QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed
      • cannot execute binary file: Exec format error
      • arm上报错找不到槽函数
  • 交叉编译gdb调试
    • 交叉编译 gdbserver
    • gdb远程调试
    • gdb调试core文件

交叉编译简介

交叉编译是在一个平台上编译生成另一个平台上的可执行代码,当我们开发目标是一个嵌入式设备时,便需要在PC机上编译出能在该嵌入式设备上运行的可执行文件,这里编译主机与目标运行主机不是同一个设备,该过程就称为交叉编译;
编译是指一个源代码文件,如C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和链接(linking)等步骤才能变成可执行文件,整个过程统称为编译。

常用的交叉编译环境是:在X86架构主机上编译生成可执行文件,放到ARM架构开发板上运行。
为什么需要交叉编译:目的平台上不允许或不能够安装所需的编译器;或目的平台上的资源贫乏,无法运行我们所需要编译器;或目的平台还没有建立,甚至没有操作系统等。

cmake 交叉编译

C/C++项目,可以使用cmake交叉编译。

使用cmake创建嵌入式开发项目,和创建普通的C/C++项目类似,区别在于不使用默认的gcc/g++编译器,而是使用交叉编译器。

cmake创建C/C++项目参考:https://blog.csdn.net/weixin_40355471/article/details/133200612?spm=1001.2014.3001.5502

1、创建普通cmake项目,包含CMakeLists.txt文件

mkdir build	#在CMakeLists.txt所在目录创建build文件夹
cd build	
vim rvgcc.cmake	#在build/目录创建rvgcc.cmake文件,手动指定交叉编译器路径。set(CMAKE_C_COMPILER /opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-g++)
set(CMAKE_ASM_COMPILER /opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-gcc)set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)

2、cmake,使用 -DCMAKE_TOOLCHAIN_FILE 选项指定工具链文件的路径
后面也可以带上其他自定义选项 -DUBUSYS=ON

cmake -DCMAKE_TOOLCHAIN_FILE="rvgcc.cmake" -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=debug -DUBUSYS=ON ..

3、交叉编译,生成可执行文件,拷贝到arm上运行

make -j

报错处理
unknown value ‘native’ for ‘-march’
删掉CMakeLists.txt文件中的-march=native
-march=native #march:指定目标架构名;native:允许编译器自动探测目标架构

clion 交叉编译

cmake创建项目后,可以使用传统的 clion 进行远程开发和交叉编译。

clion 可运行在windows系统,编译环境在 ubuntu20.04,交叉编译后在 arm 上运行(clion 远程开发,代码在windows和ubuntu都有,修改后clion会上传或下载进行代码同步)。

使用 clion 远程 linux 嵌入式开发,可以交叉编译,但交叉编译的可执行文件不能在clion运行和调试。

clion 远程开发配置参考:https://blog.csdn.net/weixin_40355471/article/details/127833119?spm=1001.2014.3001.5502

clion 加载 CMakeLists.txt 文件后,在 CMakeLists.txt 所在目录生成文件夹 cmake-build-debug ,把上面的 rvgcc.cmake 文件拷贝到该文件夹。

clion 交叉编译设置:
1、clion–Settings–Toolchains–选择创建的远程连接,C Comoiler 手动录入交叉编译器目录:/opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-gcc
C++ Comoiler 手动录入交叉编译器目录:/opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-g++
其他设置不变,CMake和Debugger均是自动检出。

2、clion–Settings–CMake–CMake options: 输入编译选项:

-DCMAKE_TOOLCHAIN_FILE="rvgcc.cmake" -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=debug -DUBUSYS=ON .

完成设置后,在clion编译即可生成可执行文件,拷贝到arm上运行。

vscode 远程嵌入式开发

嵌入式开发使用 clion 只能交叉编译,不能使用 clion 直接运行和调试交叉编译的可执行文件,如果想简单一点可以直接使用 vscode 远程开发编辑,命令行远程进行交叉编译。

Qt交叉编译

Qt交叉编译,在arm板上运行(比如RK3399)。
环境搭建
主机:win10
开发环境:虚拟机,ubuntu 20.04.2
Qt交叉编译库版本:Qt5.12.9
Qt开发版本:Qt5.14.1
arm板:RK3399

大致思路
1、要让程序在arm上运行,需要特殊的编译器,首先在ubuntu上安装这种编译器(交叉编译工具)。
2、ubuntu上,使用交叉编译工具,把QT源码编译成可以在arm上使用的QT依赖库。
3、编译好的QT依赖库拷贝到arm板子上,arm上可以执行QT交叉编译的程序。
4、ubuntu安装普通版本QT,配置构建套件,编译器使用交叉编译工具,QT版本配置交叉编译好的qmake路径。
5、至此可使用ubuntu的QT开发和交叉编译,编译的可执行文件拷贝到arm上运行。

硬件环境
RK3399 arm开发板通过USB转串口与win10主机相连,识别COM口,win10主机通过COM口使用MobaXterm等远程工具连接板子,给板子配置IP和网关后可以通过IP地址远程,使用SCP进行文件传输。

#一些常用命令
vi  /etc/eth0-setting	#改网卡IPifconfig eth2 down
ifconfig eth2 192.168.72.167 up
ifconfig eth2  192.168.72.165  netmask 255.255.255.0

1.安装交叉编译工具

下载地址:https://www.linaro.org/downloads/
下载压缩包:gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.gz。

#拷贝到/opt目录下
cd /opt
sudo tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.gz
sudo mv gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu gcc-aarch64-linux-gnu
sudo vim /etc/profile
export PATH="/opt/gcc-aarch64-linux-gnu/bin:$PATH"
source  /etc/profile
aarch64-none-linux-gnu-gcc -v

安装完成后获得交叉编译器(/opt/gcc-aarch64-linux-gnu/bin 目录下),配置环境变量后可以使用交叉编译命令,和直接使用gcc类似。

#查询版本,如果查询到版本信息则说明安装成功
aarch64-none-linux-gnu-gcc -v

交叉编译qt库时需要配置这个编译器,后续也要配置到Qt Creator的构建套件里。

2.交叉编译qt库

下载Qt5.12.9源码:https://download.qt.io/archive/qt/5.12/5.12.9/single/
下载版本:qt-everywhere-src-5.12.9.tar.xz
解压缩源码:

tar -xvf qt-everywhere-src-5.12.9.tar.xz
cd qt-everywhere-src-5.12.9/

2.1修改qmake.conf

vim qtbase/mkspecs/linux-arm-gnueabi-g++/qmake.conf
#
# qmake configuration for building with arm-linux-gnueabi-g++
#MAKEFILE_GENERATOR      = UNIX
CONFIG                 += incremental
QMAKE_INCREMENTAL_STYLE = sublib#添加
QT_QPA_DEFAULT_PLATFORM = linuxfb
QMAKE_CFLAGS_RELEASE += -O2 -march=armv8-a -lts
QMAKE_CXXFLAGS_RELEASE += -O2 -march=armv8-a -ltsinclude(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/g++-unix.conf)# modifications to g++.conf
# 修改交叉编译工具可执行文件
QMAKE_CC                = aarch64-none-linux-gnu-gcc
QMAKE_CXX               = aarch64-none-linux-gnu-g++
QMAKE_LINK              = aarch64-none-linux-gnu-g++
QMAKE_LINK_SHLIB        = aarch64-none-linux-gnu-g++# modifications to linux.conf
QMAKE_AR                = aarch64-none-linux-gnu-ar cqs
QMAKE_OBJCOPY           = aarch64-none-linux-gnu-objcopy
QMAKE_NM                = aarch64-none-linux-gnu-nm -P
QMAKE_STRIP             = aarch64-none-linux-gnu-strip
load(qt_config)

2.2创建交叉编译自动配置脚本,开始编译
-prefix /opt/qt5.12.9-arm,配置生成的依赖库保存路径。

vim auto.sh
#!/bin/sh
./configure \
-prefix /opt/qt5.12.9-arm \
-confirm-license \
-opensource \
-release \
-make libs \
-xplatform linux-arm-gnueabi-g++ \
-pch \
-qt-libjpeg \
-qt-libpng \
-qt-zlib \
-no-opengl \
-no-sse2 \
-no-openssl \
-no-cups \
-no-glib \
-no-dbus \
-no-xcb \
-no-separate-debug-info \sudo chmod u+x auto.sh 
./auto.sh
sudo make		#如果找不到 aarch64-none-linux-gnu-gcc 命令,可以切换到root下,不使用sudo
sudo make install
cd /opt/qt5.12.9-arm	#已安装到指定目录,查看(bin  doc  include  lib  mkspecs  plugins  qml  translations)

编译完成后获得交叉编译所依赖的Qt库(/opt/qt5.12.9-arm 目录下),编译好的库要拷贝到arm板子上,后续也要配置到Qt Creator的构建套件里。

错误处理
python: not found

type python python2 python3
#如果没有python,则安装
sudo apt install python3
#如果有 python3 ,没有 python,执行
sudo apt install python-is-python3

3.将交叉编译的Qt库复制到板子上

/opt/qt5.12.9-arm,把该目录拷贝到arm板子上,在arm上配置环境变量。
从ubuntu把QT依赖库拷贝到arm上。

scp -r qt5.12.9-arm root@192.168.72.165:/opt

在arm上执行,配置环境变量。

vi /etc/profile
export QTEDIR=/opt/qt5.12.9-arm
export LD_LIBRARY_PATH=/opt/qt5.9.0-arm/lib:$LD_LIBRARY_PATH
export QT_QPA_PLATFORM_PLUGIN_PATH=$QTEDIR/plugins
export QT_QPA_PLATFORM=linuxfb
export QT_QPA_FONTDIR=/usr/share/fonts/truetype/droid

4.安装和配置 Qt Creator,支持交叉编译

ubuntu上安装普通版本的QT,比如5.14.1,可以只安装Qt Creator,安装完成后运行。

构建套件配置
添加C/C++编译器
菜单栏,Tools,Options,Kits,Compilers,选择添加,ADD,GCC,C/C++。
Manual,C,GCC,Complier path:/opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-gcc
Manual,C++,GCC,Complier path:/opt/gcc-aarch64-linux-gnu/bin/aarch64-none-linux-gnu-g++

添加Qt版本
Qt Versions,Add…,选择交叉编译生成的qmake目录
Manual,Qt5.12.9(qt5.12.9-arm),/opt/qt5.12.9-arm/bin/qmake

添加构建套件
Kits,Add
Manual,生成自定义套件,包括名称、设备类型、编译工具、Qt版本等信息。
Name arm
Device Generic Linux Device
Compiler C: GCC
Compiler C++: GCC
Debugger System GDB at /usr/bin/gdb
Qt Version Qt5.12.9(qt5.12.9-arm)
CMake Tool System CMake at /usr/bin/cmake

5.QT嵌入式开发

新建QT项目,在选择构建套件时,选刚刚新建的arm,正常开发编译,把编译好的二进制可执行文件拷贝到3399板子上。

scp hellowd  root@192.168.72.165:/userdata/qt_pro
./hellowd	#板子上运行

6.QT嵌入式开发报错解决

QIconvCodec::convertToUnicode: using Latin-1 for conversion, iconv_open failed

在板子上运行时报错,原因是缺少iconv库。
下载源码:http://ftp.gnu.org/gnu/libiconv/libiconv-1.14.tar.gz
下载:libiconv-1.14.tar.gz

tar xvf libiconv-1.14.tar.gz
cd libiconv-1.14/# 创建自动配置脚本
vim autoconfig.sh
./configure \
#替换交叉编译器路径
CC=/opt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gcc \
CXX=/opt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-g++ \
#安装目录
--prefix=/opt/libiconv_install/ \
--host=arm-linux \
--enable-shared \
--enable-static \
#当前解压缩路径
--with-sysroot=/home/chw/arm/libiconv-1.14chmod +x autoconfig.sh
./autoconfig.sh
make -j	#编译
make install

‘gets’ undeclared here (not in a function); did you mean ‘fgets’? 报错解决

vim srclib/stdio.in.h_GL_WARN_ON_USE (gets, “gets is a security hole-use fgets instead”)
# 修改为:
#if defined(GLIBC) && !defined(UCLIBC) && !__GLIBC_PREREQ(2, 16)
_GL_WARN_ON_USE (gets, “gets is a security hole - use fgets instead”);
#endif

安装完成后,生成的库文件路径:/opt/libiconv_install。

# 拷贝到板子上
sudo scp -r libiconv_install/ root@192.168.72.111:/opt	
# 在板子上执行后,运行qt交叉编译的可执行文件即可
export LD_PRELOAD=/opt/libiconv_install/lib/preloadable_libiconv.so	

cannot execute binary file: Exec format error

在板子上运行时报错。
可能的原因:使用64位交叉编译器编译的可执行文件,放在32位arm上运行。
解决方法:更换交叉编译器。

arm上报错找不到槽函数

不使用SIGNAL(readyRead())写法,改为&QSerialPort::readyRead这种写法。

交叉编译gdb调试

本章介绍远程gdb调试方法:交叉编译调试时,主机ubuntu使用gdb,arm使用gdbserver。

交叉编译器自带gdb,一般不需要编译,例如:arm-linux-gnueabihf-gdb

arm-linux-gnueabihf-gdb --version	#查询gdb版本

交叉编译 gdbserver

下载gdb源码:https://www.sourceware.org/gdb/download/
gdb-8.3.tar.gz,拷贝到ubuntu目录

tar zxvf gdb-8.3.tar.gz
cd gdb-8.3/gdb/gdbserver/
./configure --host=arm-linux-gnueabihf --target=arm-linux-gnueabihf  --prefix=/opt/gdb/gdbserver-lib
# --host:该软件将运行的平台,填你的交叉编译器
# --target:该软件所处理的目标平台,填你的交叉编译器
# --prefix:目标文件生成路径
make
sudo make installcd /opt/gdb/gdbserver-lib/bin/	#生成的gdbserver目录:arm-linux-gnueabihf-gdbserver
#把gdbserver拷贝到arm上
sudo scp arm-linux-gnueabihf-gdbserver root@192.168.72.111:/home/chw

gdb远程调试

arm上执行

#1234是指定的端口号,qt_at3399是可执行程序,此时程序并未运行
./arm-linux-gnueabihf-gdbserver :1234 qt_at3399		
Process /home/chw/qt_at3399 created; pid = 2652
Listening on port 1234

ubuntu上执行

arm-linux-gnueabihf-gdb qt_at3399
#进入gdb
target remote 192.168.72.111:1234	#arm :Remote debugging from host ::ffff:192.168.72.55, port 56972
b 50	#在main.cpp的50行打断点
c		#运行
#Thread 1 "qt_at3399" hit Breakpoint 1,命中第一个断点
q		#退出gdb

在gdb远程调试时,arm只负责 gdbserver 启动远程端口,指定可执行程序;程序的运行由 ubuntu 的gdb负责启动、打断点、调试、关闭等。

error while loading shared libraries: libncursesw.so.5

sudo apt install libncursesw5-dev
ln -s /usr/lib/libncursesw.so.6 /usr/lib/libncursesw.so.5
#不行再运行
sudo apt install apt-file
sudo apt-file update
sudo apt-file find libncursesw.so.5
sudo apt install libncursesw5

gdb调试core文件

ulimit -c unlimited	#arm上执行
#运行程序生成core文件
#把core文件拷贝到ubuntu主机
arm-linux-gnueabihf-gdb qt_at3399 core
bt	#查询调用栈

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

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

相关文章

ASUS华硕天选5笔记本电脑FX607JV原装出厂Win11系统下载

ASUS TUF Gaming F16 FX607JV天选五原厂Windows11系统 适用型号: FX607JU、FX607JI、FX607JV、 FX607JIR、FX607JVR、FX607JUR 下载链接:https://pan.baidu.com/s/1l963wqxT0q1Idr98ACzynQ?pwd0d46 提取码:0d46 原厂系统自带所有驱动、…

TypeScript中 “ <> “ 语法 和 “ : “ 怎么使用

在 TypeScript 中&#xff0c;尖括号语法(<Type>)和as关键字(value as Type)都是用于类型断言&#xff0c;而冒号(:)用于类型注解。这三种语法在不同的场景下使用&#xff1a; 尖括号语法和as关键字&#xff1a; 尖括号语法(<Type>value)&#xff1a; 这种语法在…

[LeetBook]【学习日记】链表反转

来源于「Krahets」的《图解算法数据结构》 https://leetcode.cn/leetbook/detail/illustration-of-algorithm/ 链表反转的递归要点 递归终止条件为当前节点为空&#xff0c;表明遍历到了链表尾部递归函数传入参数为当前节点的下一个节点按照是否重新开辟存储空间分类下面只写…

python自动化学习--3.8python操作EXCEL文件python日志收集处理

1、Excel文件处理 安装 openpxl 第三方库 openpxl 模块三大组件: 1、工作簿 &#xff08;包含多个sheet工作表&#xff09; 2、工作表 &#xff08;某个数据包含在某个工作表&#xff09; 3、单元格 1、创建excel工作簿 import openpyxl"""Excel表格的创建…

【简说八股】Spring事务失效可能是哪些原因?

Spring事务介绍 Spring事务是指在Spring框架中对数据库操作进行管理的一种机制&#xff0c;它确保一组数据库操作要么完全执行成功&#xff08;提交&#xff09;&#xff0c;要么完全不执行&#xff08;回滚&#xff09;&#xff0c;从而保持数据一致性和完整性。 Spring框架…

GotoXy控制台光标的位置更新

光标控制解释 控制台的光标更新方法, 用于控制数据输出位置 void gotoXY(int x, int y)//新函数&#xff1a;更新光标 {COORD c;c.X x;c.Y y;SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c); }代码解释 这段代码定义了一个名为 gotoXY 的函数&#xff0c;…

设计模式-装饰者模式应用实践

装饰者模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许动态地向一个现有的对象添加新的功能&#xff0c;同时不改变其结构。这种模式通过创建一个装饰类来包装原有的类&#xff0c;提供额外的行为。 下面是一个使用 Java 实现装饰者模式…

【Spring Boot】实现全局异常处理

1.定义基础异常接口类 /*** description: 服务接口类* author: MrVK* date: 2021/4/19 21:39*/ public interface BaseErrorInfoInterface {/*** 错误码* return*/String getResultCode();/*** 错误描述* return*/String getResultMsg(); } 2.定义错误处理枚举类 /*** desc…

小伙伴询问AI该怎么学习?本人的一点总结,以思维导图呈现

如有需要思维导图的在后台请留邮箱&#xff0c;相关知识结构目录 部分导图

nn.Linear() 使用提醒

原本以为它是和nn.Conv2d()一样&#xff0c;就看第二个维度的数值&#xff0c;今天才知道&#xff0c;它是只看最后一个维度的数值&#xff01;&#xff01;&#xff01; 例子1 Descripttion: Result: Author: Philo Date: 2024-02-27 14:33:50 LastEditors: Philo LastEditT…

git使用merge命令把dev分支的mian.js文件和src下面的vuex文件夹以及config文件夹单独合并到master分支上

使用 git merge 命令来单独合并特定文件或文件夹到另一个分支通常不是最直接的方法&#xff0c;因为 merge 命令是用来合并两个分支的所有更改的。然而&#xff0c;你可以通过 git cherry-pick 命令或者通过创建临时补丁&#xff08;patch&#xff09;来实现这一点。 下面是一个…

秒杀的时候怎么使用Redis?

商品信息存储&#xff1a;在Redis中存储秒杀商品的库存信息。可以使用Redis的Hash数据类型&#xff0c;将商品ID作为字段&#xff0c;库存数量作为值存储在Hash中。例如&#xff0c;HSET seckill_goods stock_1 100表示商品ID为stock_1的商品库存数量为100。 秒杀订单存储&…

如何使用“Ubuntu 20.04桌面版,安装MariaDB数据库“?win10系统?

1、更新软件包 sudo apt update 2、 安装MariaDB服务器和客户端 sudo apt install mariadb-server mariadb-client 3、 查看MeriaDB是否运行 service mysql status :q"退回命令行状态 4、 设置MariaDB root用户的密码 sudo mysql_secure_installation 5、 MariaD…

斐波那契数列模型----三步问题

面试题 08.01. 三步问题 - 力扣&#xff08;LeetCode&#xff09; 1、状态表示&#xff1a; 题目要求&#xff1a;上到n阶台阶&#xff0c;有多少种方法。那么n逐渐简化&#xff0c;上1阶台阶有多少种方法&#xff1b;上2阶台阶有多少种方法……直到上n阶台阶有多少种方法。 …

c++ [[nodiscard]]关键字详解

如果一个函数声明了[[nodiscard]]&#xff0c;则该函数的返回值不能没有承接&#xff0c;如果没有承接&#xff0c;就会编译报warning [[nodiscard]]是c17新特性&#xff0c;但本地用c11标准编译也能编译过&#xff0c;尚不清楚原因&#xff0c;c20加入了warning后的额外文字描…

代码随想录第45天|● 70. 爬楼梯 (进阶) ● 322. 零钱兑换 ● 279.完全平方数

文章目录 ● 70. 爬楼梯 &#xff08;进阶&#xff09;思路&#xff1a;- 排列 先value后weight代码&#xff1a; ● 322. 零钱兑换思路&#xff1a;代码 ● 279.完全平方数思路&#xff1a;代码 ● 70. 爬楼梯 &#xff08;进阶&#xff09; 思路&#xff1a;- 排列 先value后…

如何提升计算机性能

04 穿越功耗墙&#xff0c;我们该从哪些方面提升“性能”&#xff1f; 上一讲&#xff0c;在讲 CPU 的性能时&#xff0c;我们提到了这样一个公式&#xff1a; 程序的 CPU 执行时间 指令数CPIClock Cycle Time 这么来看&#xff0c;如果要提升计算机的性能&#xff0c;我们可以…

zookeeper框架

事务ID Znode的创建删除&#xff0c;更改内容等都是作为zookeeper的事务进行执行的。 对于每一个事务请求&#xff0c;zookeeper都会为其分配一个全局唯一的事务ID&#xff0c;从ID可以识别出事务的全局顺序。 节点特性 czxid:create zxid,数据节点创建时的事务ID mzxid&…

基于ZYNQ的PCIE高速数据采集卡的设计(一)

作为信息处理的第一步&#xff0c;数据采集的作用越来越重要。目前&#xff0c;数据采集已经在航 空、民用、军事、医疗等领域得到广泛应用。随着相关技术的不断发展&#xff0c;信号频率越 来高&#xff0c;带宽越来越大&#xff0c;使得数据采集技术逐渐向高速大数据的方向…

【python】优化docker镜像体积

背景 测试脚本的最终所构成的镜像体积偏大&#xff0c;项目提出整改 实现思路 1.测试基础镜像&#xff0c;更换为更小的 参见&#xff1a;python 多阶段构建docker镜像&#xff0c;有效减少镜像大小 - 知乎 2.去掉实际未使用的依赖库