7. 交叉开发环境设置

news2025/6/17 13:24:25

嵌入式交叉编译工具

​ 交叉编译工具是为了使在上位机中编译的文件能够在不同平台的目标机中执行,搭建交叉编译环境是嵌入式开发的第一步,也是关键的一步。不同的体系结构、不同的操作系统,甚至是不同版本的内核,都会用到不同的交叉编译器。选择交叉编译器非常重要, 有些交叉编译器经常会有部分的 BUG,都会导致最后的代码无法正常运行。

1. 交叉编译工具安装

  • 交叉编译器完整的安装一般涉及多个软件的安装(读者可以从 ftp://gcc.gnu.org/pub/下 载),包括 GNU binutils、gcc、glibc、glibc-linuxthreads 等软件,以及获得Linux内核头文件、安装Glibc头文件。
    • binutils 主要用于生成一些 辅助工具,如 readelf、objcopy、objdump、as、ld 等;
    • gcc 是用来生成交叉编译器的,主要 生成 arm-linux-gcc 交叉编译工具(应该说,生成此工具后已经搭建起交叉编译环境,可以 编译 Linux 内核了,但由于没有提供标准用户函数库,用户程序还无法编译);
    • glibc 主要是 提供用户程序所使用的一些基本的函数库;
    • glibc-linuxthreads 是线程相关函数库。
  • 最初,交叉环境的搭建是需要手动一步步进行搭建的,搭建方法复杂,很多步骤都涉及对硬件平台的选择一次成功安装的过程需要长达数小时的时间。现在嵌入式平台社区或厂商一般会提供在各种平台上测试通过的交叉编译器,或把以上安装步骤全部写入脚本文件或者以发行包的形式提供,这样就大大方便了用户的使用。因此, 常见的交叉编译工具下载网站有:
    • ARM官方:developer.arm.com
    • linaro社区:www.linaro.org
  • 为了大家理解,下面分别从手工自己搭建和直接下载安装现成发行包两种方法进行阐述:

1.1 自己手工搭建交叉编译工具链

  1. 建立存放工具、源码目录和设置相关的环境变量

    mkdir /usr/local/arm 				//建立工作目录
    cd /usr/local/arm 					//进入工作目录
    mkdir -p /usr/local/arm/src 		//建立安装文件的目录
    mkdir -p /usr/local/arm/sysroot 	//建立系统根目录
    mkdir -p /usr/local/arm/bin 		//建立生成工具存放的目录
    mkdir -p /usr/local/arm/build 		//建立编译目录
    
    export HOST=i686-pc-linux-gnu 			//设置 HOST 环境变量
    export TARGET=arm-linux-gnueabi 		//设置 TARGET 环境变量
    export PREFIX=/usr/local/arm 			//设置 PREFIX 环境变量
    export SYSROOT=/usr/local/arm/sysroot 	//设置 SYSROOT 环境变量
    export PATH=$PATH:${PREFIX}/bin 		//添加生成工具目录到 PATH
  2. 从网站下载安装的源码包,并将获得的源码放到/usr/local/arm/src 目录下,需要下载的源码包如下表所示:

    软件包名称下 载 地 址
    binutils-2.23.tar.bz2http://ftp.gnu.org/gnu/binutils/
    linux-2.6.33.3.tar.bz2http://www.kernel.org/pub/linux/kernel/v2.6/
    gcc-4.6.0.tar.bz2http://ftp.gnu.org/gnu/gcc/gcc-4.6.0/
    glibc-2.17.tar.gzhttp://ftp.gnu.org/gnu/glibc/
    glibc-linuxthreads-2.3.6.tar.gzhttp://ftp.gnu.org/gnu/glibc/
  3. 编译 GNU binutils

    • Binutils 是 GNU 工具之一,包括连接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具,安装 Binutils 工具包含的程序有 addr2line、 ar、 as、 c++ filt、gprof、 ld、 nm、 objcopy、 objdump、 ranlib、 readelf、 size、 strings、 strip、 libiberty、 libbfd和 libopcodes。
    • 编译步骤
    cd ${PREFIX}/src
    tar xvfj binutils-2.23.tar.bz2
    mkdir -p /usr/local/arm/build/binutils-2.23
    cd /usr/local/arm/build/binutils-2.23
    ../../src/binutils-2.23/configure --prefix=${PREFIX} --target=${TARGET} --with-sysroot=${SYSROOT} 2>&1 | tee configure.out
    make 2>&1 | tee make.out
    make install 2>&1 | tee -a make.out
    
    • –target=${TARGET} :这个选项跟–host 一起表示编译生成的可执行文件运行在 HOST 上面,但服务的对象是 TARGET,也就是说,用这些可执行文件连接和汇编出来的程序运行在 TARGET 上面。因为这里默认使用主机的 GCC 编译器,因此省略了–host 选项。

    • –prefix=${PREFIX} :告诉配置脚本当运行 make install 时,把编译好的东西安装在 PREFIX目录下;

    • –with-sysroot=${SYSROOT} :表示SYSROOT 为系统根目录,生成的相应库放在 SYSROOT/lib 目录下,可执行文件放在SYSROOT/sbin 下,配置文件放在 SYSROOT/etc 下,用户文件放在 SYSROOT/usr 下。

    • 在上面的编译过程中如果出现问题,最好的方法就是,删除编译目录下的所有文件,删除 Binutils 目录, 重新解压 Binutils, 再重新开始安装。 安装成功后就会在/usr/local/arm/bin目录下生成下面的工具:

      arm-linux-addr2line	#把程序地址转换为文件名和行号。在命令行中给它一个地址和一个可执行文件名,它就会使用这个可执行文件的调试信息指出给出的地址上是哪个文件及行号。
      arm-linux-c++filt	#连接器使用它来过滤 C++ 和 Java 符号,防止发生重载函数冲突。
      arm-linux-nm 		#列出目标文件中的符号。
      arm-linux-ranlib	#产生归档文件索引,并将其保存到这个归档文件中。在索引中列出了归档文件各成员所定义的可重分配目标文件
      arm-linux-strings	#打印某个文件的可打印字符串,这些字符串最少4个字符长,也可以使用选项-n设置字符串的最小长度。默认情况下,它只打印目标文件初始化和可加载段中的可打印字符;对于其他类型的文件它打印整个文件的可打印字符。这个程序对于了解非文本文件的内容很有帮助。
      arm-linux-ar		#用来建立、修改和提取归档文件。归档文件是包括了其他多个文件的一个较大的文件,从该文件中可以恢复其他文件内容。
      arm-linux-gprof		#显示程序调用段的各种数据。
      arm-linux-objcopy	#把一种目标文件中的内容复制到另一种类型的目标文件中
      arm-linux-readelf	#显示 elf 格式可执行文件的信息
      arm-linux-strip		#丢弃目标文件中的全部或者特定符号
      arm-linux-as		#用来编译gcc 输出的汇编文件,编译产生的目标文件再由连接器 ld 进行连接操作。
      arm-linux-ld		#把所有编译产生的目标文件和归档文件结合在一起,重新定位数据,并连接符号引用。
      arm-linux-objdump	#显示一个或者更多目标文件的信息。使用选项来控制其显示的信息
      arm-linux-size		#列出目标文件每一段的大小及总体的大小
      arm-linux-libiberty	#包含许多 GNU 程序都会用到的函数, 这些程序有 getopt、obstack、trerror、strtol 和 strtoul
      arm-linux-libbfd	#二进制文件描述库
      arm-linux-libopcode	#用来处理 opcodes 的库,在生成一些应用程序的时候也会用到它。
      
  4. 获得 Linux 内核头文件,并将头文件安装在${SYSROOT}/usr/include 目录下

    cd ${PREFIX}/src
    tar xvfj linux-2.6.33.3.tar.bz2
    cd linux-2.6.33.3/
    make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig	#选择一个对应 CPU 的类型。
    make include/linux/version.h
    mkdir -p ${SYSROOT}/usr/include
    cp -a ${PREFIX}/src/ linux-2.6.33.3/include/linux ${SYSROOT}/usr/include/linux
    cp -a ${PREFIX}/src/linux-2.6.33.3/arch/arm/include/asm ${SYSROOT}/usr/include/asm
    cp -a ${PREFIX}/src/linux-2.6.33.3/include/asm-generic ${SYSROOT}/usr/include/asm-generic
    
    • 第4布主要用来选择一个CPU类型,如图所示

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  5. 安装 Glibc 头文件

    • Glibc 是 GUN C 库,它是编译 Linux 系统程序的重要组成部分。在安装 GNU C 库前需要先安装其头文件。

      cd ${PREFIX}/src
      tar xvfz glibc-2.17.tar.gz
      cd glibc-2.17
      tar xvfz ../glibc-linuxthreads-2.3.6.tar.gz
      cd ..
      mkdir -p /usr/local/arm/build/glibc-2.17-headers
      cd /usr/local/arm/build/glibc-2.17-headers
      ../../src/glibc-2.17/configure --prefix=/usr --host=${TARGET} --enable-add-ons --with-headers=${SYSROOT}/usr/include 2>&1 | tee configure.out
      make cross-compiling=yes install_root=${SYSROOT} install-headers 2>&1 | tee make.out
      touch ${SYSROOT}/usr/include/gnu/stubs.h
      touch ${SYSROOT}/usr/include/bits/stdio_lim.h
      
  6. 安装 GCC 第一阶段

    • 安装 GCC 共分为两个阶段,第一阶段是为了安装 ARM 交叉编译工具没有支持 libc 库的头文件。

      cd ${PREFIX}/src
      tar xvfj gcc-4.6.0.tar.bz2
      mkdir -p mkdir /usr/local/arm/build/gcc-4.6.0
      cd /usr/local/arm/build/gcc-4.6.0
      ../../src/gcc-4.6.0/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c --with-sysroot=${SYSROOT} 2>&1 | tee configure.out
      make 2>&1 | tee make.out
      make install 2>&1 | tee -a make.out
      
  7. 安装 GNU C 库 (安装了 Glibc 后才能对 GCC 进行完全安装 )

    cd ${PREFIX}/src
    mkdir -p /usr/local/arm/build/glibc-2.17
    cd /usr/local/arm/build/glibc-2.17
    BUILD_CC=gcc CC=${TARGET}-gcc AR=${TARGET}-ar RANLIB=${TARGET}-ranlib AS=${TARGET}-as LD=${TARGET}-ld ../../src/glibc-2.3.5/configure --prefix=/usr --build=i386-redhat-linux --host=arm-unknown-linux-gnu --target=armunknown-linux-gnu --without-__thread --enable-add-ons=linuxthreads --with-headers=${SYSROOT}/usr/include 2>&1 | tee configure.out
    
    make 2>&1 | tee make.out
    BUILD_CC=gcc CC=${TARGET}-gcc AR=${TARGET}-ar RANLIB=${TARGET}-ranlib AS=${TARGET}-as LD=${TARGET}-ld ../../src/glibc-2.17/configure --prefix=/usr build=${HOST} --host=${TARGET} –target=${TARGET} --without-__thread --enable-add-ons=linuxthreads --with-headers=${SYSROOT}/usr/include 2>&1 | tee make.out
    
  8. 完全安装 GCC

    cd ${PREFIX}/src
    mkdir -p /usr/local/arm/build/gcc-4.6.0
    cd /usr/local/arm/build/gcc-4.6.0
    ../../src/gcc-4.6.0/configure --prefix=${PREFIX} --target=${TARGET} --enable-languages=c --with-sysroot=${SYSROOT} 2>&1 | tee configure.out
    
    make 2>&1 | tee make.out
    make install 2>&1 | tee -a make.out
    
  9. 删除源码目录、临时目录和一些中间目录,得到 arm-linux、 bin、 lib、 libexec 和share 目录。

  • 编译交叉编译器是一个很耗时的工作,对于实际项目的作用并不大。除非在某些应用程序或者驱动模块已经通过测试进入成品库,而这些应用程序或驱动模块依赖某个版本 GCC 或 glibc,同时修改和测试应用程序或驱动模块的工作量相对非常复杂,此时可以选择需要的版本进行建立交叉编译环境。一般情况下,建议直接使用开发板厂商提供的交叉编译器,或者在网上下载稳定的交叉编译器。目前针对 2.4 内核的稳定版本为 2.95.3,针对 2.6 内核的稳定版本为 3.4.1。本文使用开发商提供的 4.4.3 版本,在后面的内核移植和驱动移植过程中使用的就是 4.4.3 版本。

1.2 安装现成交叉编译工具发行包

  • 假设我们从网站已经下载好交叉编译工具链cross-4.3.2.bar.bz2了,如何安装使用呢?

    • 1)解压缩到指定目录

      $ mkdir –p /usr/local/arm /* 这是交叉编译器安装目录*/
      $ cp cross-4.3.2.bar.bz2 /usr/local/arm
      $ cd /usr/local/arm
      $ tar jxvf cross-4.3.2.tar.g
      $ ls
      4.3.2
      $ ls 4.3.2/bin
      arm-none-linux-gnueabi-addr2line 	arm-none-linux-gnueabi-gfortran
      arm-none-linux-gnueabi-ar 			arm-none-linux-gnueabi-gprof
      arm-none-linux-gnueabi-as 			arm-none-linux-gnueabi-ld
      arm-none-linux-gnueabi-c++ 			arm-none-linux-gnueabi-ldd
      arm-none-linux-gnueabi-cc 			arm-none-linux-gnueabi-nm
      arm-none-linux-gnueabi-c++filt 		arm-none-linux-gnueabi-objcopy
      arm-none-linux-gnueabi-cpp 			arm-none-linux-gnueabi-objdump
      arm-none-linux-gnueabi-ct-ng.config arm-none-linux-gnueabi-populate
      arm-none-linux-gnueabi-g++ 			arm-none-linux-gnueabi-ranlib
      arm-none-linux-gnueabi-gcc 			arm-none-linux-gnueabi-readelf
      arm-none-linux-gnueabi-gcc-4.3.2 	arm-none-linux-gnueabi-run
      arm-none-linux-gnueabi-gccbug 		arm-none-linux-gnueabi-size
      arm-none-linux-gnueabi-gcov 		arm-none-linux-gnueabi-sstrip
      arm-none-linux-gnueabi-gdb 			arm-none-linux-gnueabi-strings
      arm-none-linux-gnueabi-gdbtui 		arm-none-linux-gnueabi-stri
      
    • 2)把交叉开发工具链的路径添加到环境变量 PATH 中

      $ export PATH=$PATH:/usr/local/arm/4.3.2/bin
      
      • 环境变量的配置文件有如下2个,随便添加到其中一个文件中即可
        • profile 类文件:用户第一次登录时仅运行一次,profile 类文件包括每个用户主目录 下的.profile 文件和/etc/profile 等。用户再次登录时就会运行主目录下的.profile 文件的脚本。
        • bashrc 类文件:每当打开 bash shell 时(如当打开一个虚拟终端时)运行该脚本文 件。bash 类文件包括每个用户主目录下的.bashrc 文件和/etc/bash.bashrc 等
    • 3)确认配置交叉编译工具链成功

      $ arm-linux-gcc –v 			/*查看交叉编译器的版本信息*/
      arm-none-linux-gnueabi-gcc -v
      Using built-in specs.
      Target: arm-none-linux-gnueabi
      Configured with: /home/linux/crosstooll/toolchain_build/targets/src/gcc-4.3.2/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-none-linux-gnueabi --prefix=/usr/local/arm/4.3.2 --with-sysroot = /home/linux/toolchain/arm-none-linux-gnueabi//sys-root --enable-languages=c,c++,fortran --disable-multilib --with-arch=armv4t --with-cpu=arm9tdmi --with-tune=arm920t --with-float=soft --with-pkgversion=crosstool-NG-1.8.1-farsight --disable-sjlj-exceptions --enable-__cxa_atexit --disable-libmudflap --with-gmp=/home/linux/crosstooll/toolchain_build/
      targets/arm-none-linux-gnueabi/build/static--with-mpfr=/home/linux/crosstooll/toolchain_build/targets/arm-none-linux-gnueabi/build/static--enable-threads=posix--enable-target-optspace--with-local-prefix=/home/linux/toolchain/arm-none-linux-gnueabi//sys-root --disable-nls --enable-symvers=gnu--enable-c99 --enable-long-long
      Thread model: posix
      gcc version 4.3.2
      
      • 从上面打印的版本信息中可以看到==“–prefix=/usr/local/arm/ 4.3.2”==,这就是交叉编译器 安装的路径。它是在编译前通过 prefix 选项配置的,所以,这个工具链安装的路径必须是/usr/local/arm/4.3.2。

1.3 交叉编译器测试

  • 在使用新建立的交叉编译器前需要对其进行简单的测试,查看其生成的文件是否可以移植到 ARM 平台的开发板上运行。其步骤如下:

    1. 将 arm-linux-gcc 添加到环境变量中(打开/etc/profile文件,找到”#Path manipulation“部分,添加 arm-linux-gcc 所在目录 ),修改后保存配置重启系统配置生效 。

      # Path manipulation
      if [ "$EUID" = "0" ]; then
          pathmunge /sbin
          pathmunge /usr/sbin
          pathmunge /usr/local/sbin
          pathmunge /usr/local/arm/bin	#修改添加的
      fi
      
    2. 编写简单的测试程序,查看程序适应的体系结构。

      #include <stdio.h>
      int main()
      {
          printf("test arm-linux-gcc");
          return 0;
      }
      
      • 对上面的程序进行交叉编译, 并查看其头文件信息, 看其运行属于哪种平台体系结构

        arm-linux-gcc –o test test.c 	#交叉编译 test.c,生成 test
        readelf test –h 				#使用 readelf 命令查看头文件信息ELF 头:
            Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
            Class: ELF32
            Data: 2 s complement, little endian
            Version: 1 (current)
            OS/ABI: UNIX - System V
            ABI Version: 0
            Type: EXEC (可执行文件)
            Machine: ARM			#可以看出该文件运行的环境为ARM
            Version: 0x1
            入口点地址: 0x8338
            程序头起点: 52 (bytes into file)
            Start of section headers: 4464 (bytes into file)
            标志: 0x5000002, has entry point, Version5 EABI
            本头的大小: 52 (字节)
            程序头大小: 32 (字节)
            Number of program headers: 10
            节头大小: 40 (字节)
            节头数量: 30
            字符串表索引节头: 27
        

        标志: 0x5000002, has entry point, Version5 EABI
        本头的大小: 52 (字节)
        程序头大小: 32 (字节)
        Number of program headers: 10
        节头大小: 40 (字节)
        节头数量: 30
        字符串表索引节头: 27

        
        
        
        

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

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

相关文章

差距拉开了!量化大厂最新业绩排行曝光!

经历了一月份的失落和二月份绝地反攻&#xff0c;量化大厂们的整体业绩备受关注。 而今年2月份的量化战绩&#xff0c;甚为关键&#xff01; 毕竟市场指数“前低后高”&#xff0c;基金经理与投资人开年以来&#xff0c;共同经历了“惊心动魄”的考验。 量化大厂&#xff0c…

帮管客CRM jiliyu接口存在SQL漏洞 附POC软件

免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 帮管客CRM简介 微信公众号搜索:南风漏洞复现文库…

分类算法入门:以鸢尾花数据集为例

近两年人工智能技术蓬勃发展&#xff0c;OpenAI连续放出ChatGPT、Sora等“王炸”产品&#xff0c;大模型、AIGC等技术带来了革命性的提升&#xff0c;很多人认为人工智能将引领第四次工业革命。国内各大互联网公司也是重点投资布局&#xff0c;从个人角度来说要尽快跟上时代的潮…

12. 建立用户表并使用雪花算法生成用户ID

文章目录 一、建立用户表二、雪花算法生成唯一ID三、将雪花算法整合到我们的项目中 一、建立用户表 上一节我们搭建完了脚手架&#xff0c;从这一节开始&#xff0c;就正式进入到业务逻辑的开发了。首先要开发的就是博客系统的用户注册与登录功能。 既然涉及到用户&#xff0…

深入浅出计算机网络 day.1 概论④ 计算机网络的定义和分类

不要退却&#xff0c;要绽放魅力 我的心会共鸣 和你 —— 24.3.9 一、计算机网络的定义 计算机网络早期的一个最简单定义 现阶段计算机网络的一个较好的定义 二、计算机网络的分类 按交换方式分类 按使用者分类 按传输介质分类 按覆盖范围分类 按拓扑结构分类&#xff0c;可…

数据结构之deque双端队列

一、概念&#xff1a; 众所周知&#xff0c;数据结构是用来存储数据&#xff0c;deque也不例外&#xff0c;他是集结了队列和栈的性质而成的结构&#xff0c;他几乎拥有所有数据结构能有的操作&#xff0c;看似已经大杀四方&#xff0c;可实际情况如何呢&#xff0c;那就带者这…

markdown页面宽度放宽

变成以上样式 ------------------------------------------------ 然后最后一行加上 #write{ max-width: 90%; } /* 调整源码正文宽度 */ #typora-source .CodeMirror-lines { max-width: 90%; } /* 调整输出 PDF 文件宽度 */ media print { #write{ max-w…

C++字符串操作【超详细】

零.前言 本文将重点围绕C的字符串来展开描述。 其中&#xff0c;对于C/C中字符串的一些区别也做出了回答&#xff0c;并对于C的&#xff08;string库&#xff09;进行了讲解&#xff0c;最后我们给出字符串的不同表达形式。 开发环境&#xff1a; VS2022 一.字符串常量跟字…

UE4.27_ParticleSystem(没写完的材料)

UE4.27_ParticleSystem&#xff08;没写完的材料&#xff09; 参考实例&#xff1a; UE4[蓝图]下雪效果及雪的材质的实现

docker学习入门

1、docker简介 docker官网&#xff1a; www.docker.com dockerhub官网&#xff1a; hub.docker.com docker文档官网&#xff1a;docs.docker.com Docker是基于Go语言实现的云开源项目。 Docker的主要目标是&#xff1a;Build, Ship and Run Any App, Anywhere(构建&…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Image)

Image为图片组件&#xff0c;常用于在应用中显示图片。Image支持加载PixelMap、ResourceStr和DrawableDescriptor类型的数据源&#xff0c;支持png、jpg、jpeg、bmp、svg、webp和gif类型的图片格式。 说明&#xff1a; 该组件从API Version 7开始支持。后续版本如有新增内容&am…

数据库系统概论(超详解!!!) 第三节 关系数据库

1.基本概念 1. 域&#xff08;Domain&#xff09; 域是一组具有相同数据类型的值的集合。 2. 笛卡尔积&#xff08;Cartesian Product&#xff09; 给定一组域D1&#xff0c;D2&#xff0c;…&#xff0c;Dn&#xff0c;允许其中某些域是相同的。 D1&#xff0c;D2…

phpStudy,自定义php版本

新版phpStudy&#xff0c;支持自定义php版本&#xff0c;只支持php5.3.0以后的任意版本。 一定要下载win版php&#xff0c;不是下载源码&#xff0c;win版php下载地址&#xff1a;http://windows.php.net/ 也就是地址&#xff1a; https://windows.php.net/downloads/releases…

使用Julia语言和R语言实现K-均值

K-均值算法基础 K-均值聚类算法属于一种无监督学习的方法&#xff0c;通过迭代的方式将数据划分为K个不重叠的子集&#xff08;簇&#xff09;&#xff0c;每个子集由其内部数据点的平均值来表示。计算方法大体如下&#xff1a; 1.初始化簇中心 选择K个数据点作为初始的簇中心…

A5自媒体wordpress主题模板

一个简洁的wordpress个人博客主题&#xff0c;适合做个人博客&#xff0c;SEO优化效果挺不错的。 https://www.wpniu.com/themes/204.html

数据分析-Pandas最简单的方法画矩阵散点图

数据分析-Pandas直接画矩阵散点图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&…

添加路障-蓝桥杯-DFS

自己另辟蹊径想的新思路 果然好像还是不太行呀 import java.util.Scanner;public class Main {static int T;//样例组数static int n;//矩阵大小static int[] X {0,1,0,-1};static int[] Y {1,0,-1,0};static int[] X1 {1,0,-1,0};static int[] Y1 {0,-1,0,1};static int …

Harbor二次开发前端环境搭建

1 前端开发环境搭建 &#xff08;1&#xff09;拉取分支代码 &#xff08;2&#xff09;前端开发推荐使用VsCode编辑器打开项目 打开 harbor\src\portal 文件夹&#xff0c;该文件夹为Harbor对应的前端代码所在位置 &#xff08;3&#xff09;在portal文件夹下创建名为 pro…

macOS上实现「灵动岛」效果

自从Apple iPhone推出了「灵动岛」功能后&#xff0c;用户们就被其优雅的设计和强大的功能所吸引。然而&#xff0c;作为macOS用户&#xff0c;我们一直在等待这一功能能够在我们的设备上实现。现在&#xff0c;随着新的应用程序的推出&#xff0c;我们终于可以在我们的Mac上体…

物流分拣漫LiDAR反射板

激光雷达漫反射板是物流分拣中不可或缺的一种设备&#xff0c;它在物流分拣过程中发挥着重要的作用。漫反射板的主要功能是反射光线&#xff0c;使得光线能够在分拣区域内均匀分布&#xff0c;从而提高分拣设备的识别精度和效率。 物流分拣是现代物流系统中非常关键的一环&…