OpenHarmony下musl编译工具链普法

OpenHarmony下musl编译工具链普法



引言

欠的债总是要还的,这不前面欠的关于OpenHarmony下musl相关的还是要还的。这里我对其中的相关知识点,梳理,归纳重新消化下!



一.GCC/Clang/LLVM的区别与联系

说实话,这块我现在都木有搞清楚,GCC/Clang/LLVM之间的区别与联系!这里只能硬着头皮,捡一捡网上各路大神的总结,先理解一波有个基本概念!

先了解,后面再深入吗!先搞个普法,对概念先有个基本的认识!


1.1 GCC的简介

传统的编译器譬如gcc设计是分为三个部分,如下图所示:

  • 前端, front end:解析源码,检查错误(词法分析(lexical analysis), 语法分析(syntax analysis), 语义分析(semantic analysis)),所以前端又称为分析阶段。并且构建一个特定于语言的抽象语法树(Abstract Syntax Tree,AST)来代表输入的代码。

  • 优化器,optimizer :负责进行各种转换尝试,改善代码的执行时间,比如消除冗余计算。通常或多或少与语言及目标无关。

  • 后端,back end:代码产生器,将代码映射到目标指令集,除了编写正确的代码外,它还负责生成利用所支持体系结构的不寻常特性的良好代码。一个编译器后端的通用部分包含指令选择,寄存器分配,及指令调度(instruction selection, register allocation, and instruction scheduling)

image


1.2 GCC架构的优点

GCC架构的优点总结为如下几点:

  • 使用通用的中间代码,新增支持语言只需要新增一个前端,新增支持目标机器只需要新增一个后端
  • 针对前后端,开发人员技术栈不同,开发人员只需要关注自身的技术栈,有利于让更多人员参与进来

总结来说,前端+优化器+后端的结构有三大好处:灵活程度高,组件复用率高,维护成本低


1.3 GCC架构的缺点

  • GCC的三段式模块必须配套使用,很难做到部分重用
  • 不能将 GCC 部分功能作为库重用的原因有很多,包括滥用全局变量、不可变变量不能更改限制不严、设计不良的数据结构、庞大的代码库、以及使用宏来防止代码库一次编译可以支持多个编译前端-目标机对。不过,最难解决的问题是其早期设计和那个时代所固有的架构设计。具体来说,GCC 饱受分层问题和抽象漏洞的困扰:编译后端遍历编译前端抽象语法树(AST)来生成调试信息(debug info),编译前端生成编译后端数据的结构,整个编译器依赖命令行设置的全局数据结构。

上面的这些优缺点,不是专业人士基本是体会不到相关差异的。我是木有体会到!


1.4 LLVM介绍

LLVM是开源的编译器(compiler)架构,以cpp编写而成,用于优化以随意程序语言编写的程序的编译时间(compile-time)、链接时间(link-time)、执行时间(run-time)以及空暇时间(idle-time),对开发人员保持开放,并兼容已有脚本。LLVM的设计就采用了上述前端+优化器+后端的设计。如下图所示:

image

基于这个认知,我们可以认为 LLVM 包括了两个概念:一个广义的 LLVM 和一个狭义的 LLVM 。广义的 LLVM 指的是一个完整的 LLVM 编译器框架系统,包括了前端、优化器、后端、众多的库函数以及很多的模块;而狭义的 LLVM 则是聚焦于编译器后端功能的一系列模块和库,包括代码优化、代码生成、JIT 等。

整体的编译器架构就是 LLVM 架构:

  • Clang 大致可以对应到编译器的前端,主要处理一些和具体机器无关的针对语言的分析操作;
  • 编译器的优化器和后端部分就是之前提到的 LLVM 后端,即狭义的 LLVM。

此外,由于 LLVM 的命名最早源自于底层虚拟机(Low Level Virtual Machine) 的首字母缩写,但这个项目的范围并不局限于创建一个虚拟机,这个缩写导致了大量的疑惑。LLVM 成长之后已成为众多编译工具及低级工具技术的统称,使得这个名字变得更不贴切,所以开发者决定放弃这个缩写的涵义,现在 LLVM 已独立成为一个品牌,适用于 LLVM 下的所有项目,包括 LLVM 中介码、LLVM 除错工具、LLVM cpp 标准库等。

image


1.5 clang介绍

Clang 是一个 C、cpp、Objective-C 和Objective-cpp编程语言的编译器前端,采用底层虚拟机(LLVM)作为后端。

  • Clang 采用的是 BSD 协议的许可证,而 GCC 采用的是 GPL 协议,显然前者更为宽松;
  • Clang 是一个高度模块化开发的轻量级编译器,编译速度快、占用内存小、有着友好的出错提示
  • Clang项目包括Clang前端和Clang静态分析器等,目的是输出代码对应的抽象语法树并将代码编译成LLVM bitcode
  • 接着后端使用LLVM编译成平台相关的机器语言

1.6 gcc和clang的交叉编译

gcc和clang都支持交叉编译链,gcc这个就比较常见了像后面章节2.2所描述的就是gcc的一个交叉编译工具链!clang通过–target=基本选项是定义目标体系结构,triple 的一般格式为<sub>---,其中:

  • arch = x86_64、i386、arm、thumb、mips等。
  • sub = v5, v6m, v7a, v7m等。
  • vendor = pc, apple, nvidia, ibm,等。
  • sys = none, linux, win32, darwin, cuda等。
  • abi = eabi, gnu, android, macho, elf等。

譬如:

--target=arm-linux-gnueabihf

并且通常一个大型的编译工程,不会是上面这么直接裸写的,一般会通过环境变量进行控制的。

export LINUX_ROOT="$HOME/OH_V3.2_BETA2/code-v3.2-Beta2"
export SYSROOT="${LINUX_ROOT}/OpenHarmony/out/rk3568/obj/third_party/musl"
export LLVM_BUILD_DIR="${LINUX_ROOT}/llvm"
export PATH=${LINUX_ROOT}/OpenHarmony/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-ohos-
export HOSTCC=clang
export BUILD=debug

1.使用Clang作为编译器 —— 使用 Clang 交叉编译
2. 使用 Clang 交叉编译
3. How To Cross-Compile Clang/LLVM using Clang/LLVM
4. LLVM cross-compiled Linux From Scratch: C & cpp libraries


1.7 小结

前面说了这么多,其实我也还还不是很清楚!先不管吗,先把参考的链接放上!

这里我对gcc,clang和llvm的理解可以用一句话来概括就是: gcc = clang(前端) + 狭义的llvm后端

1.经典编译器组成(前端+优化器+后端)以及LLVM和Clang简介
2.【编译原理】GCC/Clang/LLVM的区别与联系
3.请问LLVM与GCC之间的关系
4.GCC和clang/LLVM
5.详解三大编译器:gcc、llvm 和 clang




二.musl你究竟是个啥

musl你是个啥,还得从它的的出生,发展历程出发一一道来。这里我们就从各个方面来捋一捋它!musl 是基于 Linux 系统调用 API 之上实现的 C 语言标准库(libc),历史可以追溯到 2005 年,但在 2011 年才正式确定了 MUSL 这个名称,开始对标 glibc、uClibc,从 2012 年开始,musl 开始使用 MIT License。

musl 致力于简单、高效,凭借 libc 优秀的松耦合性,做到了静态版本最小10kB,即使添加了线程等高级特性,也可以控制到 50kB,所以特别适合嵌入式设备。为了控制资源的使用, musl自己竟然不做动态内存分配。


2.1 glibc和musl-libc

这个我们分别来介绍下:

  • glibc: glibc是GNU C Library 是GNU项目(GNU Project),所实现的 C语言标准库(C standard library)。 目前,常见的桌面和服务器中的GNU/Linux类的系统中,都是用的这套C语言标准库。 其实现了常见的C库的函数,支持很多种系统平台,功能很全,但是也相对比较臃肿和庞大

  • musl-libc:C语言标准库Musl-libc项目发布了1.0版。Musl是一个轻量级的C标准库,设计作为GNU C library (glibc)、 uClibc或Android Bionic的替代用于嵌入式操作系统和移动设备。它遵循POSIX 2008规格和 C99 标准,采用MIT许可证授权,使用Musl的Linux发行版和项目包括sabotage,bootstrap-linux,LightCube OS等等

musl libc 和 glibc 是两个常见的 C 标准库实现,它们有一些差异。下面列出了其中一些主要的差异:

  • 大小和速度:musl libc 要小得多,因为它没有像 glibc 那样提供大量的额外功能。相反,musl libc 专注于尽可能减少代码大小和函数调用开销,以提高性能。

  • 兼容性:glibc 是 Linux 系统上最常见的 C 标准库,并且具有广泛的兼容性,支持许多架构和操作系统。相比之下,musl libc 对其他平台和操作系统的移植性较差。

  • 实现方法:musl libc 是使用静态链接编译的,这使得它更易于构建和管理,并且不需要动态链接器。相反,glibc 使用动态链接器,这也使得它更灵活,因为它可以动态加载所需的库。

  • POSIX 标准:musl libc 更加严格地遵循 POSIX 标准,而glibc 则添加了一些扩展,以提供更多的功能和兼容性。

  • 错误处理:musl libc 实现的错误处理更严格和更规范,而 glibc 则有更多的错误处理选项,并且支持不同的语言环境。

  • 版权问题:由于采用了 BSD 许可证,musl libc 比 glibc 更容易以开源、商业和专有软件的形式使用。

综上所述,选择使用 musl libc 还是 glibc 取决于您的具体需求。如果您需要一个小巧且速度较快的 C 标准库,在 Linux 系统上使用,则可以考虑使用 musl libc。如果您需要更广泛的兼容性和功能,则可以使用 glibc。

  • 额外补充:两个都是C++标准库。libc++是针对clang编译器特别重写的cpp标准库,那libstdc++自然就是gcc的事儿了。

  • 无关的科普: libc.so.6是c运行时库glibc的软链接,而系统几乎所有程序都依赖C运行时库。程序启动和运行时,是根据libc.so.6软链接找到glibc库。删除libc.so.6将导致系统的几乎所有程序不能工作。如果程序编译的时候链接的libc库版本不在程序运行环境下的glibc库支持的libc版本之内,也会报错。于是,系统的所有命令 IS,cp,cd等等都无法使用了。

1.Musl libc:为什么我们会需要另一个 libc?
2.musl和glibc,性能区别到底有多大
3.理清gcc、glibc、libstdc++的关系
4.uclibc、eglibc、glibc、Musl-libc之间的区别和联系
5.如何紧急修复,当你在linux中干穿了libc丢了libc.so.6,ld-linux-x86-64.so.2其中一个

干穿了,我就提桶跑路,还修复个啥!

6.musl简介
7.glibc和musl libc的区别
8.在同一个进程中加载​​ musl libc.so 和 gcc libc.so?
9.musl 的 GCC 包装器与 musl 的交叉编译器有何不同?
10.gcc编译静态库到自己的程序 解决在不同linux下因libc版本问题而不能运行 版本兼容问题
11.glib和glibc的联系区别
12.libc、glibc 和 glib 的关系
13.glibc所包含的各个库


2.2 aarch64-linux-musl-xxx

前面搞完了一个musl-libc库,这里又来了一个aarch64-linux-musl-xxx。你们是逗比吗,来这么多。真的逗比,今天又联系补上!

这里我们对aarch64-linux-musl其简单介绍下:

  • aarch64 是随 ARMv8 ISA 一起引入的 64 位架构,用于执行 A64 指令的计算机。而且在 aarch64 状态下执行的代码只能使用 A64 指令集。,而不能执行 A32 或 T32 指令。但是,与 AArch32 中不同,在64位状态下,指令可以访问 64 位和 32 位寄存器。

  • aarch64-linux-musl 是一个交叉编译工具链,可以在其他架构的系统中,编译安装 64 位 arm 架构的程序。常用在嵌入式代码的移植中。aarch64-linux-musl 是由musl官网基于 GCC 推出的的 ARM 交叉编译工具。可用于交叉编译 ARMv8 64 位目标中的裸机程序、u-boot、Linux kernel、filesystem 和 App 应用程序。aarch64-linux-musl 交叉编译器必须安装在 64 位主机上,才能编译目标代码。

aarch64-linux-musl-xxx如下所示:

$/opt/musl/bin$ ls
aarch64-linux-musl-addr2line  aarch64-linux-musl-gcc-9.4.0   aarch64-linux-musl-nm
aarch64-linux-musl-ar         aarch64-linux-musl-gcc-ar      aarch64-linux-musl-objcopy
aarch64-linux-musl-as         aarch64-linux-musl-gcc-nm      aarch64-linux-musl-objdump
aarch64-linux-musl-c++        aarch64-linux-musl-gcc-ranlib  aarch64-linux-musl-ranlib
aarch64-linux-musl-cc         aarch64-linux-musl-gcov        aarch64-linux-musl-readelf
aarch64-linux-musl-c++filt    aarch64-linux-musl-gcov-dump   aarch64-linux-musl-size
aarch64-linux-musl-cpp        aarch64-linux-musl-gcov-tool   aarch64-linux-musl-strings
aarch64-linux-musl-elfedit    aarch64-linux-musl-gprof       aarch64-linux-musl-strip
aarch64-linux-musl-g++        aarch64-linux-musl-ld
aarch64-linux-musl-gcc        aarch64-linux-musl-ld.bfd

这里我们可以把 aarch64-linux-musl-xxx和aarch64-linux-gnu-gcc做对比。它是一个gcc交叉编译工具链。

XXX:/opt/musl$ tree -L 1
.
├── aarch64-linux-musl
├── bin
├── include
├── lib
├── libexec
└── share

#其中git仓库地址如下,对应的

https://github.com/richfelker/musl-cross-make.git
https://gitee.com/stesen/musl-cross-make_for_openharmony.git



三.其它关于工具链知识的一些普法

工具链的知识真多,搞了一个又是一个!搞不完,记不住。但是还是木的办法,只能硬着头皮上!我不入地狱谁入地狱。我是超人!


3.1 什么是sysroot

sysroot 被称为逻辑根目录,只在链接过程中起作用,作为交叉编译工具链搜索库文件的根路径,如配置–sysroot=dir,则dir作为逻辑根目录,链接器将在dir/usr/lib中搜索库文件。

export LINUX_ROOT="$HOME/xxx/linux"
export SYSROOT="${LINUX_ROOT}/sysroot-ubuntu-20.04-arm64"


export LINUX_ROOT="$HOME/OH_V3.2_BETA2/code-v3.2-Beta2"
export SYSROOT="${LINUX_ROOT}/OpenHarmony/out/rk3568/obj/third_party/musl"

只有链接器开启了–with-sysroot选项,–sysroot=director才生效

1.编译链接实战(4)–sysroot和-isysroot选项对编译的影响
2.GCC编译选项和环境变量
3.sysroot位何物


3.2 pkg-config是个什么东东?

pkg-config的功能主要是在编译应用程序和库的时候作为一个工具来使用。pkg-config可以使用第三方库编译程序,指定库文件和头文件的位置。pkg-config就是通过.pc文件获取库的各种必要信息,包括版本信息、编译和链接需要的参数等。不同的系统的库文件的路径不同,用户也可以把库安装到不同的目录下

对于一个比较大第三方库,其头文件和库文件的数量是比较多的。如果我们一个个手动地写,那将是相当麻烦的。所以,pkg-config就应运而生了。大家应该都知道一般用第三方库的时候,就少不了要使用到第三方的头文件和库文件。我们在编译、链接的时候,必须要指定这些头文件和库文件的位置。对于一个比较大的第三方库,其头文件和库文件的数量是比较多的,如果我们一个个手动地写,那将是相当的麻烦的。因此,pkg-config就应运而生了。pkg-config能够把这些头文件和库文件的位置指出来,给编译器使用。pkg-config主要提供了下面几个功能:

  • 检查库的版本号。 如果所需要的库的版本不满足要求,它会打印出错误信息,避免链接错误版本的库文件
  • 获得编译预处理参数,如宏定义、头文件的位置
  • 获得链接参数,如库及依赖的其他库的位置,文件名及其他一些链接参数
  • 自动加入所依赖的其他库的设置

pkg-config能够把这些头文件和库文件的位置指出来,给编译器使用。如果你的系统装有libdrm,可以尝试一下下面的命令$pkg-config --cflags libdrm。可以看到其输出是gtk的头文件的路径。

我们平常都是这样用pkg-config的。

$gcc main.c `pkg-config --cflags --libs libdrm` -o main

$pkg-config --cflags --libs libdrm
-I/usr/local/include -I/usr/local/include/libdrm -L/usr/local/lib -ldrm

上面的编译命令中,`pkg-config --cflags --libs libdrm`的作用就如前面所说的,把gtk的头文件路径和库文件列出来,让编译去获取。–cflags和–libs分别指定头文件和库文件。

命令中的`不是引号,而是数字1左边那个键位的那个符号。

其实,pkg-config同其他命令一样,有很多选项,不过我们一般只会用到–libs和–cflags选项。

$pkg-config --help
Usage:
  pkg-config [OPTION?]

Help Options:
  -h, --help                              Show help options

Application Options:
  --version                               output version of pkg-config
  --modversion                            output version for package
  --atleast-pkgconfig-version=VERSION     require given version of pkg-config
  --libs                                  output all linker flags
  --static                                output linker flags for static linking
  --short-errors                          print short errors
  --libs-only-l                           output -l flags
  --libs-only-other                       output other libs (e.g. -pthread)
  --libs-only-L                           output -L flags
  --cflags                                output all pre-processor and compiler flags
  --cflags-only-I                         output -I flags
  --cflags-only-other                     output cflags not covered by the cflags-only-I option
  --variable=NAME                         get the value of variable named NAME
  --define-variable=NAME=VALUE            set variable NAME to VALUE
  --exists                                return 0 if the module(s) exist
  --print-variables                       output list of variables defined by the module
  --uninstalled                           return 0 if the uninstalled version of one or more module(s) or their dependencies will be used
  --atleast-version=VERSION               return 0 if the module is at least version VERSION
  --exact-version=VERSION                 return 0 if the module is at exactly version VERSION
  --max-version=VERSION                   return 0 if the module is at no newer than version VERSION
  --list-all                              list all known packages
  --debug                                 show verbose debug information
  --print-errors                          show verbose information about missing or conflicting packages (default unless --exists or --atleast/exact/max-version given on the command line)
  --silence-errors                        be silent about errors (default when --exists or --atleast/exact/max-version given on the command line)
  --errors-to-stdout                      print errors from --print-errors to stdout not stderr
  --print-provides                        print which packages the package provides
  --print-requires                        print which packages the package requires
  --print-requires-private                print which packages the package requires for static linking
  --validate                              validate a package's .pc file
  --define-prefix                         try to override the value of prefix for each .pc file found with a guesstimated value based on the location of the .pc file
  --dont-define-prefix                    don't try to override the value of prefix for each .pc file found with a guesstimated value based on the location of the .pc file
  --prefix-variable=PREFIX                set the name of the variable that pkg-config automatically sets

3.2.1 pkg-config配置环境变量

事实上,pkg-config只是一个工具,所以不是你安装了一个第三方库,pkg-config就能知道第三方库的头文件和库文件的位置的。为了让pkg-config可以得到一个库的信息,就要求库的提供者提供一个.pc文件。默认情况下,比如执行如下命令:

# pkg-config --libs --cflags glib-2.0
-I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lglib-2.0

pkg-config会到/usr/lib/pkconfig/目录下去寻找glib-2.0.pc文件。也就是说在此目录下的.pc文件,pkg-config是可以自动找到的。然而假如我们安装了一个库,其生成的.pc文件并不在这个默认目录中的话,pkg-config就找不到了。此时我们需要通过PKG_CONFIG_PATH环境变量来指定pkg-config还应该在哪些地方去寻找.pc文件。

我们可以通过如下命令来设置PKG_CONFIG_PATH环境变量:

# export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig/

这样pkg-config就会在/usr/local/lib/pkgconfig/目录下寻找.pc文件了。另外还需要注意的是,上述环境变量的设置只对当前的终端窗口有效。为了让其永久生效,我们可以将上述命令写入到/etc/bash.bashrc等文件中(配置环境变量有很多方法,不止这一种),以方便后续使用。


3.3 pc文件是个什么东东?

pc文件是个什么东东,这里我用一句话来概括就是pkg-config用来在PKG_CONFIG_PATH查找库相关依赖的,一种特殊格式文件!既然是OpenHarmony系统,这里我们就以OpenHarmony下开源mesa3d里面的pc文件为例来举例说明:

$pwd
/home/xxx/xxx/third_party/mesa3d
$cat ohos/pkgconfig_template/zlib.pc 
prefix=ohos_project_directory_stub
exec_prefix=${prefix}
libdir=${prefix}/out/ohos-arm-release/obj/third_party/zlib
sharedlibdir=${libdir}
includedir=${prefix}/third_party/zlib

Name: zlib
Description: zlib compression library
Version: 1.2.12

Requires:
Libs: -L${libdir} -L${sharedlibdir} -lz

下面我们简单描述一下pc文件中的用到的一些关键词:

  • Name: 一个针对library或package的便于人阅读的名称。这个名称可以是任意的,它并不会影响到pkg-config的使用,pkg-config是采用pc文件名的方式来工作的。

  • Description: 对package的简短描述

  • URL: 人们可以通过该URL地址来获取package的更多信息或者package的下载地址

  • Version: 指定package版本号的字符串

  • Requires: 本库所依赖的其他库文件。所依赖的库文件的版本号可以通过使用如下比较操作符指定:=,<,>,<=,>=

  • Requires.private: 本库所依赖的一些私有库文件,但是这些私有库文件并不需要暴露给应用程序。这些私有库文件的版本指定方式与Requires中描述的类似。

  • Conflicts: 是一个可选字段,其主要用于描述与本package所冲突的其他package。版本号的描述也与Requires中的描述类似。本字段也可以取值为同一个package的多个不同版本实例。例如: Conflicts: bar < 1.2.3, bar >= 1.3.0

  • Cflags: 编译器编译本package时所指定的编译选项,和其他并不支持pkg-config的library的一些编译选项值。假如所需要的library支持pkg-config,则它们应该被添加到Requires或者Requires.private中

  • Libs: 链接本库时所需要的一些链接选项,和其他一些并不支持pkg-config的library的链接选项值。与Cflags类似

  • Libs.private: 本库所需要的一些私有库的链接选项



1.pkg-config 与.pc文件
2.pkgconfig和环境变量PKG_CONFIG_PATH和PKG_CONFIG_LIBDIR
3.Linux中pkg-config的使用
4.Linux修改环境变量的4种方法


3.4 怎么通过OpenHarmony源码编译ohos-sdk

很简单,如下:

./build/prebuilts_download.sh
./build.sh --product-name ohos-sdk –ccache  --target-cpu arm64


1.Musl-libc库编译

该博客,简单介绍了怎么编译生成musl libc库!
2.OpenHarmony富设备移植指南—开源GPU驱动编译
这篇博客我们并不是学习怎么编译GPU,而是学习musl + clang配置编译

3.aarch64-linux-ohos交叉编译rust
4.ohos_cross_tools交叉编译工具链
5.一文带你读懂如何移植三方库到OpenHarmony

++参考价值不大,已经完全过时了!主要描述了,如何移植第三方库到OH平台,这个可以为后续vivante GPU移植到OH参考使用++

6.基于OpenHarmony的第三方库编译移植环境(arm-linux-ohos平台)
7.交叉编译 Arm64 OHOS(鸿蒙系统)版本
8.OpenHarmony musl交叉编译

这篇博客可以参考,可以怎么使用musl + gcc编译

9.clang交叉编译Android clang交叉编译使用musl库
10.Building Linux with Clang/LLVM

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot的月度员工绩效考核管理系统论文

摘 要 科学时代的发展改变了人类的生活&#xff0c;促使网络与计算机技术深入人类的各个角落&#xff0c;得以普及到人类的具体生活中&#xff0c;为人类的时代文明掀开新的篇章。本系统为月度员工绩效考核管理系统&#xff0c;是专为企业开发的对员工考核的协助软件。可以帮助…

video视频播放

1.列表页面 <template><div><ul><li class"item" v-for"(item,index) in list" :key"index" click"turnPlay(item.videoUrl)"><img :src"item.img" alt""><div class"btn…

教资截流,值得一做的项目

从去年9月份开始&#xff0c;教资这个类目基本上就成熟了&#xff0c;所以截流就出来了。 有流量的地方&#xff0c;就有截流。 12月教资截流&#xff0c;值得一做的项目 截流万变不离其宗&#xff0c;就是去别人有流量的文章或者视频下面截流。 我记得今年7月的时候&#xff…

K线实战分析系列之二十一:三星形态——罕见的反转信号

K线实战分析系列之二十一&#xff1a;三星形态——罕见的反转信号 一、三星形态二、三星形态总结 一、三星形态 二、三星形态总结 三星形态由三根十字线组成&#xff0c;是反转信号&#xff0c;在行情阶段性的顶部或者是底部出现典型的三星形态中间的十字线收盘价高于前一根和…

Docker实战——使用 Docker Compose 进行服务编排

目录 安装配置 Docker Compose方法一&#xff1a;方法二&#xff1a; 进行服务编排使用手动方式部署应用1、使用 Python 创建 Web 应用&#xff08;创建文件“app.py”&#xff09;&#xff0c;文件内容如下&#xff1a;2、创建 “requirements.txt” 文件&#xff0c;由于在应…

根据关键词过滤内容

package com.example.test.utils;import java.util.*;/*** Author leo* Date 2024/3/6 10:41* description: 敏感词工具类* Title: MgcUtils* Package org.jeecg.modules.yygl.dbwgl*/ public class MgcUtils {private static Map<String, Object> dictionaryMap null;p…

EasyX的学习2

消息处理——漂亮的按钮(鼠标) 用到的函数 1.消息结构体变量类型&#xff1a;使用ExMessage ExMessage msg{ 0 }; 定义一个变量名为msg的ExMessage结构体变量并初始化为0 2.获取消息函数&#xff1a;peekmessage函数 //获取消息 peekmessage(&msg, EX_MOUSE); 两个参…

阿里云几核服务器够用?内存多少合适?

阿里云服务器配置怎么选择&#xff1f;CPU内存、公网带宽和系统盘怎么选择&#xff1f;个人开发者或中小企业选择轻量应用服务器、ECS经济型e实例&#xff0c;企业用户选择ECS通用算力型u1云服务器、ECS计算型c7、通用型g7云服务器&#xff0c;阿里云服务器网aliyunfuwuqi.com整…

Git分布式管理-头歌实验远程版本库

Git的一大特点就是&#xff0c;能为不同系统下的开发者提供了一个协作开发的平台。而团队如果要基于Git进行协同开发&#xff0c;就必须依赖远程版本库。远程版本库允许&#xff0c;我们将本地版本库保存在远端服务器&#xff0c;而且&#xff0c;不同的开发者也是基于远程版本…

算法Day04_203.移除链表元素

推荐阅读 算法day01_ 27. 移除元素、977.有序数组的平方 算法day02_209.长度最小的子数组 算法day03_ 59.螺旋矩阵II 目录 推荐阅读203.移除链表元素题目思路解法暴力解法虚拟头结点解法 203.移除链表元素 题目 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删…

Python爬虫实战第三例【三】【上】

零.实现目标 爬取视频网站视频 视频网站你们随意&#xff0c;在这里我选择飞某速&#xff08;狗头保命&#xff09;。 例如&#xff0c;作者上半年看过的“铃芽之旅”&#xff0c;突然想看了&#xff0c;但是在正版网站看要VIP&#xff0c;在盗版网站看又太卡了&#xff0c;…

大模型快速实现python3+html内容在线渲染

需求&#xff1a; 有一份数据需要通过前端在线展示给用户&#xff0c;不需要复杂的样式交互&#xff0c;后端服务是基于Python3实现的API接口&#xff0c;对前端技术不是很了解&#xff0c;需要快速实现该需求。类似样式即可&#xff1a; 思路&#xff1a; 如果页面不复杂&am…

【MySQL】深入解析日志系统:undo log、redo log、bin log

文章目录 前言1、undo log1.1、undo log 是什么1.2、事务回滚 2、redo log2.1、redo log 是什么2.2、redo log 刷盘2.3、redo log 硬盘文件 3、bin log3.1、bin log 是什么3.2、bin log 和 redo log 区别3.3、bin log 刷盘3.4、两阶段提交 前言 MySQL数据库提供了功能强大的日…

一文了解74HCT14D的引脚图、符号、封装、数据手册及应用

74HCT14D 是一款采用硅栅 C2MOS 技术制造的高速 CMOS 施密特逆变器。它实现了类似于等效 LSTTL 的高速操作&#xff0c;同时保持 CMOS 的低功耗。该器件可用作电平转换器&#xff0c;用于将 TTL 或 NMOS 连接到高速 CMOS。 输入与 TTL、NMOS 和 CMOS 输出电压电平兼容。所有输入…

CSS实现选中卡片样式操作

图一默认自动选中&#xff0c;并且不可取消选中&#xff0c;当选择其他卡片才可点击下一步 在 “ src/assets ” 路径下存放 save.png&#xff0c;代表选中的状态 <div class"cards"><ul class"container"><li v-for"image in image…

今天BOSS约了个面试,HR直接发我一道面试题

前言 在电商、外卖、预约服务等场景中&#xff0c;订单超时自动取消是一个常见的业务需求。这一功能不仅提高了系统的自动化程度&#xff0c;还为用户提供了更好的体验。需求如下&#xff1a; TODO如果用户在生成订单后一定时间未支付&#xff0c;则系统自动取消订单。接下来…

大路灯哪个品牌好用?5款超火大路灯推荐,帮你全面了解大路灯!

大路灯是一种用于提供良好照明环境的电器&#xff0c;通过专业的技术&#xff0c;将光线用过折射、反射、过滤&#xff0c;最终呈现柔和明亮的光线。但市面上的大路灯琳琅满目&#xff0c;有些大路灯存在虚标数据和配置的问题&#xff0c;夸大宣传过后导致很多人入手&#xff0…

Android中的传感器类型和接口名称

本文将介绍传感器坐标轴、基础传感器和复合传感器&#xff08;动作传感器、姿势传感器、未校准传感器和互动传感器&#xff09;。 1. 传感器坐标轴 许多传感器的传感器事件值在相对于设备静止的特定坐标系中表示。 1.1 移动设备坐标轴 Sensor API 仅与屏幕的自然方向相关&a…

leetcode:88. 合并两个有序数组

原题地址&#xff1a;https://leetcode.cn/problems/merge-sorted-array/description/ 题目描述 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&a…

VSCode安装

前言 Visual Studio Code 是一个轻量级功能强大的源代码编辑器&#xff0c;支持语法高亮、代码自动补全&#xff08;又称 IntelliSense&#xff09;、代码重构、查看定义功能&#xff0c;并且内置了命令行工具和 Git 版本控制系统。适用于 Windows、macOS 和 Linux。它内置了对…