当前位置: 首页 > news >正文

linux下Qt程序部署教程

文章目录

    • @[toc]
    • 1、概述
    • 2、静态编译安装Qt
      • 1.1 安装依赖
      • 1.2 静态编译
      • 1.3 报错
      • 1.4 添加环境变量
      • 1.5 下载安装QtCreator
    • 3、配置linuxdeployqt环境
      • 1.1 在线安装依赖
      • 1.2 使用linuxdeployqt提供的程序
      • 1.3 编译安装linuxdeployqt
    • 4、使用linuxdeployqt打包依赖
      • 1.1 linuxdeployqt使用选项
      • 1.2 patchelf修改动态库搜索路径
      • 1.3 验证
      • 1.4 修改linuxdeployqt源码
    • 5、使用appimagetool打包生成AppImage程序
      • 特点
      • 工作原理
      • 1.1 安装appimagetool
      • 1.2 appimagetool选项
      • 1.3 打包AppImage工程
    • 6、错误记录
    • 7、参考
      • 1.1 Qt
      • 1.2 linuxdeployqt
      • 1.3 appimage
    • 8、视频


更多精彩内容
👉内容导航 👈
👉Qt开发经验 👈

1、概述

linux下打包部署Qt编译的程序主要有3种方法:

  • 方法1:安装Qt时编译生成静态库,这样编译生成的程序就不会依赖于Qt库了,如果用到第三方动态库另说;
  • 方法2:使用linuxdeployqt打包程序的依赖库;
  • 方法3:使用linuxdeploy打包程序。

注意:

  • 最好在低版本的LTS(长期支持)系统编译打包程序,这样打包的程序可以支持在低版本和高版本的系统运行,如果在高版本的系统编译打包,在低版本的系统可能不兼容。

测试环境

环境版本
系统ubuntu22.04
QtQt5.14.2
linuxdeployqt2024-9-8版本
appimagetool3.10.5

2、静态编译安装Qt

如果已经通过Qt官方提供的安装包进行安装了动态版本的可以选择跳过这一节。

官方说明:

从Git构建Qt 5 - Qt Wiki

从Git构建Qt 6 - Qt Wiki

1.1 安装依赖

qt5.14.2

sudo apt-get install build-essential perl python3 git
# Libxcb 的sudo apt-get install '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev
# Qt WebKit(Qt WebKit)
sudo apt-get install flex bison gperf libicu-dev libxslt-dev ruby
# Qt Web引擎
sudo apt-get install libxcursor-dev libxcomposite-dev libxdamage-dev libxrandr-dev libxtst-dev libxss-dev libdbus-1-dev libevent-dev libfontconfig1-dev libcap-dev libpulse-dev libudev-dev libpci-dev libnss3-dev libasound2-dev libegl1-mesa-dev gperf bison nodejs
#Qt多媒体
sudo apt-get install libasound2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgstreamer-plugins-bad1.0-dev

Qt6

sudo apt install libxcb-image0-dev libxcb-shm0-dev libxcb-icccm4-dev libxcb-sync-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-randr0-dev libxcb-render-util0-dev libxcb-util-dev libxcb-xinerama0-dev libxcb-xkb-dev libxkbcommon-dev libxkbcommon-x11-dev libfontconfig1-dev libfreetype-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxi-dev libxrender-dev libxcb1-dev libxcb-cursor-dev libxcb-glx0-dev libxcb-keysyms1-dev git cmake g++ gcc perl python libclang-dev libgl-dev libegl-dev libfontconfig1-dev libinput-dev

1.2 静态编译

Qt5

cd qtbase
mkdir build
cd build
# 编译静态库
../configure -developer-build -opensource -nomake examples -nomake tests --prefix=/opt/qt5.14.2/ -static  -release
make -j8
make install

Qt6

mkdir build 
cd build 
../configure -developer-build -opensource -nomake examples -nomake tests --prefix=/opt/qt6.2.9/ -static -releasecmake --build . --parallel 8
cmake --install .

1.3 报错

  • 错误
class numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> : public numeric_limits<float>
5.14.2/qtbase/include/QtCore/../../src/corelib/global/qfloat16.h:295:7: error: ‘numeric_limits’ is not a class template
295 | class numeric_limits<QT_PREPEND_NAMESPACE(qfloat16)> : public numeric_limits<float>
|       ^~~~~~~~~~~~~~
  • 解决办法:打开qtbase/src/corelib/global/qglobal.h,添加#include <limits>
#ifdef __cplusplus
#  include <type_traits>
#  include <cstddef>
#  include <utility>
#  include <limits>
#endif

1.4 添加环境变量

export PATH=/opt/qt5/bin:$PATH                            # 可执行程序环境变量
export LD_LIBRARY_PATH=/opt/qt5/lib:$LD_LIBRARY_PATH      # 链接库环境变量

1.5 下载安装QtCreator

  1. 下载最新版本的Qt Creator安装包,也可以下载源码编译;

    在这里插入图片描述

  2. 下载后使用sudo chmod 777 ./qt-creator*.run设置文件权限,然后使用sudo ./qt-creator-opensource-linux-x86_64-14.0.2.run命令运行安装。

  3. 安装完成后配置编译器;

  4. 点击【工具】->【外部】->【配置】,打开【首选项】;

    在这里插入图片描述

  5. 点击【Kit】->【Qt版本】->【添加】,找到自己编译安装的Qt安装路径下编译器中的QMake;

    • /opt/qt5/bin/qmake

    在这里插入图片描述

  6. 然后选择【构建套件Kit】,点击【添加】;

    • 编译器选择gcc/g++,调试器选择GDB,Qt版本选择刚才添加的qmake名称;

    在这里插入图片描述

  7. 配置完成后创建一个工程,选择QMake,刚才添加的编译器就可以编译代码了。

3、配置linuxdeployqt环境

1.1 在线安装依赖

sudo apt install patchelf libfuse2
  • patchelf用于修改现有的ELF可执行文件和库(修改可执行程序去寻找动态库的路径,默认是从环境变量找);

  • libfuse2 Linux FUSE(用户空间中的文件系统)接口的参考实现。(可以不安装,如果linuxdeployqt运行提示缺失再安装)

1.2 使用linuxdeployqt提供的程序

  • 下载linuxdeployqt可执行程序linuxdeployqt-continuous-x86_64.AppImage
  • 使用sudo chmod 777 linuxdeployqt-continuous-x86_64.AppImage设置文件权限;
  • 然后使用linuxdeployqt-continuous-x86_64.AppImage -version 命令检查程序是否可以运行,在高版本的ubuntu或者不支持的系统需要自己编译源码;
  • 注意:
    • linux只提供了x86-64架构的可执行程序。
    • 如果显示找不到Qt库则需要将Qt库的lib路径添加环境变量

1.3 编译安装linuxdeployqt

  • 下载linuxdeployqt源码;
  • 解压后使用qt creator打开linuxdeployqt.pro文件;

在这里插入图片描述

  • 注意: 如果ubuntu版本大于20.04则需要打开main.cpp文件,将if (strverscmp (glcv, "2.32") >= 0)判断功能注释掉;

在这里插入图片描述

  • 注意: linuxdeployqt中调用appimagetool打包程序需要联网,appimagetool打包程序时会依赖于type2-runtime程序,如果没有安装runtime则使用linuxdeployqt每次运行都会从github下载runtime,速度慢,并且需要联网,如果没有联网或者无法访问github则打包第三步会失败,后续给出解决办法。

  • 直接开始编译,然后在编译生成的build文件夹中的bin文件夹内找到linuxdeployqt

在这里插入图片描述

  • 使用命令sudo cp linuxdeployqt /usr/local/bin/将linuxdeployqt添加到环境变量可以找到的路径下;
  • 使用linuxdeployqt -version命令验证是否安装成功;

在这里插入图片描述

  • 如果找不到显示错误如下:
    • 使用命令gedit ~/.bashrc打开文件..bashrc文件;
    • 添加Qt环境变量;export LD_LIBRARY_PATH=/opt/Qt5.14.2/5.14.2/gcc_64/lib:$LD_LIBRARY_PATH
    • 然后保存关闭文件,使用source .bashrc使配置生效。
linuxdeployqt: error while loading shared libraries: libQt5Core.so.5: cannot open shared object file: No such file or directory

在这里插入图片描述

4、使用linuxdeployqt打包依赖

linuxdeployqt工作流程:

  1. 将依赖库文件打包到当前路径下;
  2. 使用patchelf修改可执行程序查找动态库的路径;
  3. 使用appimagetool将打包好的可执行程序和依赖库制作为AppImage程序。

这三个步骤可以一步全部执行,也可以单独执行;

  • 如果使用-appimage全部执行可能会报错,导致步骤中断;

  • 如果执行第一步失败,则打包的依赖库不全,无法使用;

  • 如果第一步执行完成,第二步失败,则依赖库打包完成,但是拷贝到其它电脑上后还是无法找到动态库,因为这时可执行程序是从系统环境变量去找动态库,可以单独使用patchelf命令修改查找路径;

  • 如果前两步执行完成,就可以将整个文件夹复制到其它电脑上使用了;

  • 第三步是将整个文件夹制作为一个单独可以运行的AppImage程序。

1.1 linuxdeployqt使用选项

选项说明
-always-overwrite复制文件,即使目标文件存在。
-appimage创建一个AppImage(默认包含-bundle-non-qt-lib)
-bundle-non-qt-libs打包非Qt库
-exclude-libs= ⟨ \langle list ⟩ \rangle 应排除的库列表,以逗号分隔。
-ignore-glob=在搜索库时忽略相对于appdir的glob模式。
-executable= 让给定的可执行文件也使用部署的库
-executable-dir= 让文件夹中的所有可执行文件(递归)也使用部署的库
-extra-plugins=需要部署的额外插件列表,以逗号分隔。
-no-copy-copyright-files不部署版权文件。
-no-plugins跳过插件部署。
-no-strip不要在二进制文件上运行‘strip’。
-no-translations跳过翻译的部署。
-qmake= 要使用的qmake可执行文件。
-qmldir= 扫描指定路径中的QML导入。
-qmlimport= 添加给定的路径到QML模块搜索位置。
-show-exclude-libs打印排除库列表。
-verbose=<0-3>0 =无输出,1 =错误/警告(默认),2 =正常,3 =调试。
-updateinformation=嵌入更新信息string;如果安装了zsyncmake,生成zsync文件
-version打印版本语句并退出。

示例:

linuxdeployqt 可执行程序 -appimage
  • 注意:可执行程序所在的根文件夹不应该时bin,否则打包的文件会跑到文件夹外。

1.2 patchelf修改动态库搜索路径

如果打包第二步执行失败,则可以手动使用patchelf修改动态库搜索路径。

  • patchelf基本用法:

    • $ORIGIN是一个特殊的占位符,它表示当前可执行文件所在的目录
    • RPATH 是一个嵌入到 ELF 文件中的路径列表,用于告诉动态链接器在运行时去哪里查找共享库。
patchelf --set-rpath '$ORIGIN/lib/' ./RadarServer     # 设置程序动态库链接路径
patchelf --print-rpath ./RadarServer   # 打印链接路径

1.3 验证

打包完成后需要验证依赖库是否打包完整,可执行程序是否能从当前路径下找到动态库。

  • 使用下列命令临时清除动态库环境变量:
export LD_LIBRARY_PATH=""
  • 然后再使用ldd命令查看链接动态库是否指向相对路径
ldd ./可执行程序
  • 再运行可执行程序看是否能成功运行。

在这里插入图片描述

1.4 修改linuxdeployqt源码

注意: 如果离线想通过linuxdeployqt直接生成appimage包,就需要修改源码,否则可用跳过。

  • 由于linuxdeployqt调用appimagetool命令没有指定运行时,所以名称使用-appimage打包时都会从github下载runtime,离线环境或者网络差的环境无法使用;
  • 需要离线使用linuxdeployqt指定运行时就需要修改linuxdeployqt源码。
  1. 下载安装runtime,放到/usr/local/bin路径下;
  2. 打开linuxdeployqt源码,找到shared.cpp文件,搜索appimagetool
  3. 在下图中位置添加指定运行时runtime的路径;
  4. 然后编译生成linuxdeployqt就可以使用了。

在这里插入图片描述

5、使用appimagetool打包生成AppImage程序

AppImage是一种将应用程序及其所有依赖项打包成一个单一可执行文件的格式。这种格式使得分发和运行应用程序变得非常简单,因为用户无需担心安装过程中可能出现的各种问题,如权限不足、缺少依赖库等。以下是关于AppImage程序的一些详细说明:

特点

  1. 独立性:AppImage包含应用程序的所有依赖项,因此可以在任何支持的Linux发行版上运行,而不需要额外的安装步骤。
  2. 便携性:AppImage是一个单一的可执行文件,可以方便地复制、移动和分享。
  3. 安全性:由于AppImage是自包含的,它不会对系统进行任何更改,因此减少了潜在的安全风险。
  4. 更新简便:用户可以简单地下载新版本的AppImage并替换旧版本,而无需卸载或重新安装。

工作原理

  1. 打包:开发者使用工具(如appimagetool)将应用程序及其所有依赖项打包成一个AppImage文件。
  2. 运行:用户下载AppImage文件后,只需赋予其执行权限(例如通过命令chmod +x your-app.AppImage),然后直接运行即可。
  3. 集成桌面环境:AppImage通常会自动集成到用户的桌面环境中,使其在应用菜单中可见。

https://doc.appimage.cn/docs/home/

https://appimage.org/

https://specifications.freedesktop.org/menu-spec/latest/category-registry.html

1.1 安装appimagetool

  • 下载runtime可执行程序;runtime-x86_64
  • 下载appimagetool可执行程序appimagetool-x86_64.AppImage;
  • https://appimage.github.io/appimagetool/
  • 使用下面命令安装
sudo chmod 777 runtime-x86_64 appimagetool-x86_64.AppImage   # 设置权限
sudo cp runtime /usr/local/bin/runtime
sudo cp appimagetool-x86_64.AppImage /usr/local/bin/appimagetool

1.2 appimagetool选项

appimagetool [选项… ] 可执行程序文件夹 [生成文件名]

[]中是可选

例如:

appimagetool ./untitled4.App --runtime-file /usr/local/bin/runtime-x86_64

将untitled4.App文件夹打包

指定运行时文件路径--runtime-file /usr/local/bin/runtime-x86_64

选项说明
-h帮助
-l, --list列出SOURCE AppImage中的文件
-u, --updateinformation嵌入更新信息字符串;如果安装了zsyncmake,生成zsync文件
-g, --guess基于常用CI系统(GitHub actions, GitLab CI)设置的环境变量猜测更新信息
–version显示版本号
-v, --verbose输出详细信息
-s, --sign用gpg[2]签名
–comp压缩
-n, --no-appstream不检查AppStream元数据
–exclude-file除了.appimageignore之外,还使用指定文件作为mksquash的排除文件。
–runtime-file指定runtime文件路径
–sign-key用于gpg[2]签名的密钥ID
–sign-args使用gpg[2]签名时使用的额外参数

1.3 打包AppImage工程

创建AppImage

文件夹结构规范

  • 不按照文件夹规范也可以,最简单的是创建一个文件夹,文件夹中包含可执行程序可执行程序.desktop可执行程序.png三个文件;
  • 然后使用linuxdeployqt打包依赖库,如果没有desktop和图标,则在使用linuxdeployqt打包时会生成默认的文件,但是需要修改文件内容;
  • 使用appimagetool打包成appimage程序;

在这里插入图片描述

desktop规范

.desktop基本文件格式

可用的键值对

[Desktop Entry]
Name=应用程序的具体名称
Exec=可执行程序路径
Icon=图片名称(不包含后缀)
Type=Application # 类型, Application (类型1); Link (类型2) Directory (3型)
Categories=Utilities # 注册类别,必须项

注册类别主要分类

主要类别描述Notes
AudioVideo用于呈现、创建或处理多媒体(音频/视频)的应用程序
Audio音频应用程序Desktop entry must include AudioVideo as well
Video视频应用Desktop entry must include AudioVideo as well
Development开发应用程序
Education教学软件
Game游戏
Graphics用于查看、创建或处理图形的应用程序
Network网络应用程序,如web浏览器
Office办公室类型的应用程序
Science科学软件
Settings设置应用程序条目可以出现在单独的菜单中,也可以作为“控制中心”的一部分。
System系统应用程序,“系统工具”,例如日志查看器或网络监视器
Utility小型公用事业应用,“辅助程序”

示例:

在这里插入图片描述

6、错误记录

  • 执行linuxdeployqt时报错,需要安装sudo apt install libfuse2
  • https://github.com/AppImage/AppImageKit/wiki/FUSE
dlopen(): error loading libfuse.so.2AppImages require FUSE to run. 
You might still be able to extract the contents of this AppImage 
if you run it with the --appimage-extract option. 
See https://github.com/AppImage/AppImageKit/wiki/FUSE 
for more information
  • 系统版本过新,需要自己编译linuxdeployqt;
linuxdeployqt  (commit b00a83d), build 70 built on 2024-09-08 11:56:56 UTC
ERROR: The host system is too new.
Please run on a system with a glibc version no newer than what comes with the oldest
currently supported mainstream distribution (Ubuntu Focal Fossa), which is glibc 2.31.
This is so that the resulting bundle will work on most still-supported Linux distributions.
For more information, please see
https://github.com/probonopd/linuxdeployqt/issues/340
  • linuxdeployqt找不到Qt动态库的环境变量
    • .bashrc中添加export LD_LIBRARY_PATH=/opt/Qt5.14.2/5.14.2/gcc_64/lib:$LD_LIBRARY_PATH
./linuxdeployqt: error while loading shared libraries: libQt5Core.so.5: cannot open shared object file: No such file or directory
  • linuxdeployqt从环境变量中找不到qt的qmake
    • .bashrc中添加export PATH=/opt/Qt5.14.2/5.14.2/gcc_64/bin:$PATH
ERROR: Desktop file missing, creating a default one (you will probably want to edit it)
ERROR: Icon file missing, creating a default one (you will probably want to edit it)
qmakePath 3= ""
ERROR: qmake not found on the $PATH
  • 需要安装sudo apt install patchelf
relativeBinPath: "untitled"
Keeping existing AppRun
qmakePath 3= ""
ERROR: Could not start patchelf.
ERROR: Make sure it is installed on your $PATH.
ERROR: Error reading rpath with patchelf "libQt5Widgets.so" : ""
ERROR: Error reading rpath with patchelf "libQt5Widgets.so" : ""
  • linuxdeployqt找不到appimagetool,打包的依赖库已经可以使用了,如果需要打包成appimage程序,就可以下载安装appimagetool和runtime;
relativeBinPath: "untitled"
Keeping existing AppRun
qmakePath 3= ""
sh: 1: appimagetool: not found
  • linuxdeployqt默认生成的default.desktop文件内缺少必须项Categories
WARNING: "/home/mhf/Code/test/qt.conf" already exists, will not overwrite.
fusermount3 version: 3.10.5
appimagetool, continuous build (git version feac857), build 185 built on 2024-11-24 19:31:44 UTC
WARNING: zsyncmake command is missing, please install it if you want to use binary delta updates
Desktop file: /home/mhf/Code/test/default.desktop
Categories entry not found in desktop file
.desktop file is missing a Categories= key
  • default.desktopCategories设置的值错误,必须是给出的固定值;
/home/mhf/Code/test/default.desktop: error: value "Utilities" for key "Categories" in group "Desktop Entry" contains an unregistered value "Utilities";  values extending the format should start with "X-"
  • linuxdeployqt中调用appimagetool需要依赖于runtime,每次都需要从github联网下载;解决办法:
    1. 下载runtime放到/usr/local/bin路径下,使用appimagetool去打包;
    2. 修改linuxdeployqt,增加指向runtime的路径。
Using app name extracted from desktop file: Application
/home/mhf/Code/test should be packaged as Application-x86_64.AppImage
Deleting pre-existing .DirIcon
Creating .DirIcon symlink based on information from desktop file
Generating squashfs...
Downloading runtime file from https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-x86_64
libcurl's default CA certificate bundle file /etc/ssl/certs/ca-certificates.crt was found on this system
libcurl's default CA certificate bundle directory /etc/ssl/certs was found on this system
* Host github.com:443 was resolved.
* IPv6: (none)
* IPv4: 20.205.243.166
*   Trying 20.205.243.166:443...
* Connected to github.com (20.205.243.166) port 443
* ALPN: curl offers h2,http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=github.com
*  start date: Mar  7 00:00:00 2024 GMT
*  expire date: Mar  7 23:59:59 2025 GMT
*  subjectAltName: host "github.com" matched cert's "github.com"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo ECC Domain Validation Secure Server CA
*  SSL certificate verify ok.
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256
*   Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 2: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using ecdsa-with-SHA384
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-x86_64
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: github.com]
* [HTTP/2] [1] [:path: /AppImage/type2-runtime/releases/download/continuous/runtime-x86_64]
* [HTTP/2] [1] [accept: */*]
> GET /AppImage/type2-runtime/releases/download/continuous/runtime-x86_64 HTTP/2
Host: github.com
Accept: */*
  • 需要安装sudo apt install zsync
WARNING: "/home/mhf/Code/RadarServer.AppDir/qt.conf" already exists, will not overwrite.
fusermount3 version: 3.10.5
appimagetool, continuous build (git version feac857), build 185 built on 2024-11-24 19:31:44 UTC
WARNING: zsyncmake command is missing, please install it if you want to use binary delta updates
fatal: 不是 git 仓库(或者任何父目录):.git
Failed to run 'git rev-parse --short HEAD: Child process exited with code 128 (code 128)
Desktop file: /home/mhf/Code/RadarServer.AppDir/default.desktop
/home/mhf/Code/RadarServer.AppDir/default.desktop: error: value "Network" for boolean key "Terminal" in group "Desktop Entry" contains invalid characters, boolean values must be "false" or "true"
ERROR: Desktop file contains errors. Please fix them. Please seehttps://standards.freedesktop.org/desktop-entry-spec/1.0/n       for more information.

7、参考

1.1 Qt

  • 从Git构建Qt 5 - Qt Wiki
  • 从Git构建Qt 6 - Qt Wiki
  • Qt Creator安装包

1.2 linuxdeployqt

  • patchelf

  • libfuse2

  • linuxdeployqt

  • linuxdeploy

  • Linuxdeploy用户指南

1.3 appimage

  • runtime下载
  • appimagetool下载
  • AppImage
  • appimage英文文档
  • appimage中文文档
  • AppImage-CN
  • appimagetool下载地址
  • appimagetool源码及下载地址
  • desktop规范
  • desktop可用键值对

8、视频

linux下QT程序打包

linux下使用linuxdeployqt工具打包Qt程序



相关文章:

linux下Qt程序部署教程

文章目录 [toc]1、概述2、静态编译安装Qt1.1 安装依赖1.2 静态编译1.3 报错1.4 添加环境变量1.5 下载安装QtCreator 3、配置linuxdeployqt环境1.1 在线安装依赖1.2 使用linuxdeployqt提供的程序1.3 编译安装linuxdeployqt 4、使用linuxdeployqt打包依赖1.1 linuxdeployqt使用选…...

tp6 合成两个pdf文件(附加pdf或者替换pdf)

最近在做项目有个需求&#xff0c;项目中需要根据设置的html合同模板自动生成PDF合同供客户下载签署&#xff0c;并根据回传的已签署合同尾页来替换原来未签署合同的尾页&#xff0c;合成新的已签署合同文本。 读取两个PDF文件并合成的 具体代码记录如下&#xff1a; use set…...

工作:三菱PLC防止程序存储器爆满方法

工作&#xff1a;三菱PLC防止程序存储器爆满方法 一、防止程序存储器爆满方法1、编程时&#xff0c;添加行注释时&#xff0c;记得要选“外围”&#xff0c;这样不会占用PLC程序存储器内存&#xff1b;2、选择“外围”的注释&#xff0c;前面会有个*星号&#xff0c;方便检查 二…...

jmeter 获取唯一全局变量及多线程读写的问题

一、jmeter 获取唯一ID号全局变量 在JMeter中获取唯一ID号并设置为全局变量&#xff0c;可以通过以下几种方法实现&#xff1a; 使用JMeter内置的UUID函数&#xff1a; JMeter提供了一个内置的函数__UUID&#xff0c;可以生成一个随机的UUID&#xff0c;这个UUID是全局唯一的。…...

掌握 Spring Boot 中的缓存:技术和最佳实践

缓存是一种用于将经常访问的数据临时存储在更快的存储层&#xff08;通常在内存中&#xff09;中的技术&#xff0c;以便可以更快地满足未来对该数据的请求&#xff0c;从而提高应用程序的性能和效率。在 Spring Boot 中&#xff0c;缓存是一种简单而强大的方法&#xff0c;可以…...

动手学深度学习10.5. 多头注意力-笔记练习(PyTorch)

本节课程地址&#xff1a;多头注意力代码_哔哩哔哩_bilibili 本节教材地址&#xff1a;10.5. 多头注意力 — 动手学深度学习 2.0.0 documentation 本节开源代码&#xff1a;...>d2l-zh>pytorch>chapter_multilayer-perceptrons>multihead-attention.ipynb 多头注…...

13 设计模式之外观模式(家庭影院案例)

一、什么是外观模式&#xff1f; 1.定义 在日常生活中&#xff0c;许多人喜欢通过遥控器来控制家中的电视、音响、DVD 播放器等设备。虽然这些设备各自独立工作&#xff0c;但遥控器提供了一个简洁的界面&#xff0c;让用户可以轻松地操作多个设备。而这一设计理念正是 外观模…...

单片机学习笔记 12. 定时/计数器_定时

更多单片机学习笔记&#xff1a;单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…...

Web安全基础实践

实践目标 &#xff08;1&#xff09;理解常用网络攻击技术的基本原理。&#xff08;2&#xff09;Webgoat实践下相关实验。 WebGoat WebGoat是由著名的OWASP负责维护的一个漏洞百出的J2EE Web应用程序&#xff0c;这些漏洞并非程序中的bug&#xff0c;而是故意设计用来讲授We…...

Zookeeper集群数据是如何同步的?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper集群数据是如何同步的?】面试题。希望对大家有帮助&#xff1b; Zookeeper集群数据是如何同步的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper集群中的数据同步是通过一种称为ZAB&#xff08;Zo…...

SpringCloud框架学习(第六部分:Sentinel实现熔断与限流)

目录 十四、SpringCloud Alibaba Sentinel实现熔断与限流 1.简介 2.作用 3.下载安装 4.微服务 8401 整合 Sentinel 入门案例 5.流控规则 &#xff08;1&#xff09;基本介绍 &#xff08;2&#xff09;流控模式 Ⅰ. 直接 Ⅱ. 关联 Ⅲ. 链路 &#xff08;3&#xff0…...

动态规划-----路径问题

动态规划-----路径问题 下降最小路径和1&#xff1a;状态表示2&#xff1a;状态转移方程3 初始化4 填表顺序5 返回值6 代码实现 总结&#xff1a; 下降最小路径和 1&#xff1a;状态表示 假设&#xff1a;用dp[i][j]表示&#xff1a;到达[i,j]的最小路径 2&#xff1a;状态转…...

Rust循环引用与多线程并发

循环引用与自引用 循环引用的概念 循环引用指的是两个或多个对象之间相互持有对方的引用。在 Rust 中&#xff0c;由于所有权和生命周期的严格约束&#xff0c;直接创建循环引用通常会导致编译失败。例如&#xff1a; // 错误的循环引用示例 struct Node {next: Option<B…...

东方隐侠网安瞭望台第8期

谷歌应用商店贷款应用中的 SpyLoan 恶意软件影响 800 万安卓用户 迈克菲实验室的新研究发现&#xff0c;谷歌应用商店中有十多个恶意安卓应用被下载量总计超过 800 万次&#xff0c;这些应用包含名为 SpyLoan 的恶意软件。安全研究员费尔南多・鲁伊斯上周发布的分析报告称&…...

底部导航栏新增功能按键

场景需求&#xff1a; 在底部导航栏添加power案件&#xff0c;单击息屏&#xff0c;长按 关机 如下实现图 借此需求&#xff0c;需要掌握技能&#xff1a; 底部导航栏如何实现新增、修改、删除底部导航栏流程对底部导航栏部分样式如何修改。 比如放不下、顺序排列、坑点如…...

C++ 之弦上舞:string 类与多样字符串操作的优雅旋律

string 类的重要性及与 C 语言字符串对比 在 C 语言中&#xff0c;字符串是以 \0 结尾的字符集合&#xff0c;操作字符串需借助 C 标准库的 str 系列函数&#xff0c;但这些函数与字符串分离&#xff0c;不符合 OOP 思想&#xff0c;且底层空间管理易出错。而在 C 中&#xff0…...

centos8:Could not resolve host: mirrorlist.centos.org

【1】错误消息&#xff1a; [rootcentos211 redis-7.0.15]# yum update CentOS Stream 8 - AppStream …...

Linux 定时任务 命令解释 定时任务格式详解

目录 时间命令 修改时间和日期 定时任务格式 定时任务执行 查看定时任务进程 重启定时任务 时间命令 #查看时间 [rootlocalhost ~]# date 2021年 07月 23日 星期五 14:38:19 CST --------------------------------------- [rootlocalhost ~]# date %F 2021-07-23 -----…...

aws(学习笔记第十五课) 如何从灾难中恢复(recover)

aws(学习笔记第十五课) 如何从灾难中恢复 学习内容&#xff1a; 使用CloudWatch对服务器进行监视与恢复区域(region)&#xff0c;可用区(available zone)和子网(subnet)使用自动扩展(AutoScalingGroup) 1. 使用CloudWatch对服务器进行监视与恢复 整体架构 这里模拟Jenkins Se…...

github webhooks 实现网站自动更新

本文目录 Github Webhooks 介绍Webhooks 工作原理配置与验证应用云服务器通过 Webhook 自动部署网站实现复制私钥编写 webhook 接口Github 仓库配置 webhook以服务的形式运行 app.py Github Webhooks 介绍 Webhooks是GitHub提供的一种通知方式&#xff0c;当GitHub上发生特定事…...

【C语言】递归的内存占用过程

递归 递归是函数调用自身的一种编程技术。在C语言中&#xff0c;递归的实现会占用内存栈&#xff08;Call Stack&#xff09;&#xff0c;每次递归调用都会在栈上分配一个新的 “栈帧&#xff08;Stack Frame&#xff09;”&#xff0c;用于存储本次调用的函数局部变量、返回地…...

365天深度学习训练营-第P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文为「365天深度学习训练营」内部文章 参考本文所写记录性文章&#xff0c;请在文章开头带上「&#x1f449;声明」 &#x1f37a;要求&#xff1a; 保存训练过…...

企业AI助理在数据分析与决策中扮演的角色

在当今这个数据驱动的时代&#xff0c;企业每天都需要处理和分析大量的数据&#xff0c;以支持其业务决策。然而&#xff0c;面对如此庞大的数据量&#xff0c;传统的数据分析方法已经显得力不从心。幸运的是&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的不断发展…...

洛谷 B2029:大象喝水 ← 圆柱体体积

【题目来源】https://www.luogu.com.cn/problem/B2029【题目描述】 一只大象口渴了&#xff0c;要喝 20 升水才能解渴&#xff0c;但现在只有一个深 h 厘米&#xff0c;底面半径为 r 厘米的小圆桶 &#xff08;h 和 r 都是整数&#xff09;。问大象至少要喝多少桶水才会解渴。 …...

go每日一题:mock打桩、defer、recovery、panic的调用顺序

题目一&#xff1a;单元测试中使用—打桩 打桩概念&#xff1a;使用A替换 原函数B&#xff0c;那么A就是打桩函数打桩原理&#xff1a;运行时&#xff0c;通过一个包&#xff0c;将内存中函数的地址替换为桩函数的地址打桩操作&#xff1a;利用Patch&#xff08;&#xff09;函…...

STM32F103 HSE时钟倍频以及设置频率函数(新手向,本人也是新手)

HSE_SetSysCLK是野火教程里的,不懂的去这 16-RCC&#xff08;第3节&#xff09;使用HSE配置系统时钟并使用MCO输出监控系统时钟_哔哩哔哩_bilibili HSE_AutoSetHSE的算法部分是自己写的,用了一个转接数组。C语言不支持bool所以自己定义了一个boolK代替bool。 AutoHSE.h: /**…...

renderExtraFooter 添加本周,本月,本年

在 Ant Design Vue 中&#xff0c;a-date-picker 组件提供了一个 renderExtraFooter 属性&#xff0c;可以用来渲染额外的页脚内容。你可以利用这个属性来添加“本周”、“本月”和“本年”的按钮。下面是如何在 Vue 2 项目中实现这一功能的具体步骤&#xff1a; 1.确保安装了…...

SprinBoot整合KafKa的使用(详解)

前言 1. 高吞吐量&#xff08;High Throughput&#xff09; Kafka 设计的一个核心特性是高吞吐量。它能够每秒处理百万级别的消息&#xff0c;适合需要高频次、低延迟消息传递的场景。即使在大规模分布式环境下&#xff0c;它也能保持很高的吞吐量和性能&#xff0c;支持低延…...

【机器学习】CatBoost 模型实践:回归与分类的全流程解析

一. 引言 本篇博客首发于掘金 https://juejin.cn/post/7441027173430018067。 PS&#xff1a;转载自己的文章也算原创吧。 在机器学习领域&#xff0c;CatBoost 是一款强大的梯度提升框架&#xff0c;特别适合处理带有类别特征的数据。本篇博客以脱敏后的保险数据集为例&#x…...

PyTorch 实现动态输入

使用 PyTorch 实现动态输入&#xff1a;支持训练和推理输入维度不一致的 CNN 和 LSTM/GRU 模型 在深度学习中&#xff0c;处理不同大小的输入数据是一个常见的挑战。许多实际应用需要模型能够灵活地处理可变长度的输入。本文将介绍如何使用 PyTorch 实现支持动态输入的 CNN 和…...