)
数据可视化桌面应用数据分析【免费下载链接】PlotJugglerThe Time Series Visualization Tool that you deserve.项目地址https://gitcode.com/gh_mirrors/pl/PlotJuggler点击查看免费下载本篇指南聚焦 PlotJuggler 4PJ4的发布版 AppImage 构建流程中一条特殊路径不依赖插件注册表registry下载而是从pj-official-plugins源码本地编译官方精选插件集并直接嵌入 AppImage。文章以仓库内 RELEASE_BUILD.md 为核心结合 build_release_appimage.sh、build_in_docker.sh、build_appimage.sh 及发布 CI linux-appimage-release.yml 的实现细节完整讲清两条构建流的串联方式、19ROS 2 的捆绑清单、全部命令行参数、ROS 2 多发行版运行机制与 glibc 可移植性底线。读完你将能够自主执行一次完整的本地/离线发布版 AppImage 构建并理解它与 release CI 的关系。背景发布版插件的两种来源PJ4 的插件不属于本仓库它们由pj-official-plugins仓库独立构建并发布为自包含的 marketplace zip每个 zip 插件.so 其manifest.json重依赖静态链接再由pj-plugin-registry建立索引供下载。因此发布版 AppImage 捆绑插件有两条路registry 下载模式release CI 默认build_appimage.sh --plugins-registry从pj-plugin-registry下载官方精选集 zip逐个校验sha256后解包进usr/lib/plotjuggler/plugins/id/。这是 Windows 安装器同款产物。本地编译嵌入模式本文主题从pj-official-plugins源码编译同一份精选集并嵌入由 build_release_appimage.sh 统筹执行。按 RELEASE_BUILD.md 的定位本地编译嵌入模式用于registry 不可用的场景离线构建、测试未发布的插件改动、或基于尚未发布的 SDK 版本构建。发布版完整捆绑清单19 个插件 ROS 2本地编译嵌入模式产出的 AppImage 与 registry 模式携带完全相同的精选集按类型划分如下Loaders加载器Parsers解析器Streams流Toolboxes工具箱csv、mcap、parquet、ulog、mp4、pointcloud-3dros、protobuf、json、data-tamer、arrowdummy-streamer、foxglove-bridge、plotjuggler-bridge、webrtc-client、ros2-topic-subscriberquaternion、transform-editor、mosaico、assistant-agent仅 LinuxPOSIX CLI 后端两个关键约束应要求排除toolbox-colormap、toolbox-reactive-scripts-editor不进入捆绑集。必须与BUNDLE_IDS保持同步registry 模式的精选清单定义在 build_appimage.sh 的BUNDLE_IDS数组中20 个 id含 Linux-only 的ros2-topic-subscriber与toolbox-assistant-agent本地编译模式则在 build_release_appimage.sh 中用RELEASE_FLAT_SOS按.so基名维护同一清单。两处列表必须 lockstep 同步否则两种模式产出的内容会漂移。脚本源码注释明确警告聚合构建aggregate build会额外产出mqtt、zmq、udp、lerobot、fft、colormap、reactive_script等.so它们有意不进入发布包——无论哪种模式都会被过滤掉docker 模式在打包后过滤host 模式在调用build_appimage.sh前只暂存精选文件。RELEASE_FLAT_SOS完整名单19 个.so基名libcsv_source_plugin.so libmcap_source_plugin.so libparquet_source_plugin.so libulog_source_plugin.so libmp4_source_plugin.so libdata_load_3d_plugin.so libdummy_stream_plugin.so libfoxglove_source_plugin.so libpj_bridge_source_plugin.so libwebrtc_source_plugin.so libparser_ros_plugin.so libparser_protobuf_plugin.so libparser_json_plugin.so libparser_data_tamer_plugin.so libparser_arrow_plugin.so libtoolbox_quaternion_plugin.so libtoolbox_transform_editor_plugin.so libtoolbox_mosaico_plugin.so libtoolbox_assistant_agent_plugin.so # Linux-onlyPOSIX CLI 后端ROS 2 部分以目录形式捆绑ROS2_EXTENSION_DIRros2-topic-subscriber即 AppImage 内插件树中的ros2-topic-subscriber/目录。两条构建流ROS 2 多发行版 App/非 ROS 2 插件/打包build_release_appimage.sh本质是两条构建流的编排器orchestrator而非独立构建系统流 1ROS 2 多发行版multi-distrodata_stream_ros2/docker/run-local.sh --bundle构建一个distro-agnostic 代理proxy 每个受支持 ROS 2 发行版各一个二进制humble、iron、jazzy、rolling每个发行版在自己的 Docker 镜像中编译。代理本身不链接任何 ROS 库运行时按用户机器上安装的 ROS 2 发行版分派dlopen到对应二进制。该流需要把plotjuggler_sdk仓库作为--core挂载点传入脚本以--core ${SDK_LOCAL}调用因为在每个发行版容器中都要对它执行conan export /core。流 2App 非 ROS 2 插件 打包默认调用packaging/appimage/build_in_docker.sh --plugins-dir sdk/pj_ported_plugins在Ubuntu 22.04 构建镜像glibc 2.35内同时编译 app 与聚合插件集拾取流 1 产出的 ROS 2 bundle打包出 AppImage。随后build_release_appimage.sh解包产物、丢弃精选 19 之外的所有.so、重新打包——于是最终 AppImage 既可移植又恰好携带 19 个插件外加 ROS 2 bundle。--host-build模式则只在宿主机执行同样的 19 插件过滤但 app 与插件在宿主上编译./build.shpj_ported_plugins/build.sh迭代更快产出的 AppImage不可移植glibc 底线取决于宿主机。两个模式docker 与 host最终都产出同样的精选 20 插件19 ros2 bundle。完整命令用法与参数详解RELEASE_BUILD.md 给出的五种典型调用packaging/appimage/build_release_appimage.sh # DEFAULT: docker可移植glibc 2.35 packaging/appimage/build_release_appimage.sh --host-build # opt-in: 宿主机构建不可移植 packaging/appimage/build_release_appimage.sh --skip-ros2 # 复用之前的 ROS 2 bundle packaging/appimage/build_release_appimage.sh --ros2-distros jazzy # 收窄 ROS 2 发行版矩阵 packaging/appimage/build_release_appimage.sh --fresh # (docker) 清空 Conanccache 卷脚本头部注释给出了完整签名见 build_release_appimage.shbuild_release_appimage.sh [--pj4 PJ4 root] [--plugins-dir dir] [--sdk-dir dir] [--out file.AppImage] [--host-build] [--fresh] [--skip-ros2] [--skip-app] [--skip-plugins] [--ros2-distros humble iron jazzy rolling]各参数语义参数含义--pj4 dirPJ4 app 仓库根目录缺省自动取packaging/appimage/上两级即本仓库根否则取当前工作目录--plugins-dir dirpj-official-plugins源码仓库路径等价环境变量PJ_PLUGINS_DIR再缺省取 PJ4 根目录的兄弟目录pj-official-plugins/--sdk-dir dirplotjuggler_sdk仓库路径等价环境变量PJ_SDK_DIR缺省取 PJ4 根目录的兄弟目录plotjuggler_sdk/。注意插件与 SDK 是兄弟仓库而非嵌套 checkout三个仓库的定位均按参数 → 环境变量 → 兄弟目录顺序解析缺失即报错退出--out file构建完成后把最新产物复制到指定路径--host-build选择宿主机构建流快速迭代不可移植--fresh仅 docker 模式生效删除持久化的 Conan ccache Docker 卷强制 app 与插件从头编译基础镜像不受影响重建镜像用REBUILD_IMAGE1--skip-ros2跳过 ROS 2 bundle 的重新编译复用先前产物--skip-app/--skip-plugins跳过 app / 插件编译要求对应产物已存在。docker 模式下两者会被折叠容器运行是原子的要么同时编译要么都不编译脚本会打印 warning--ros2-distros distros限制 ROS 2 矩阵默认humble iron jazzy rolling此外PJ_VERSION环境变量会作为版本戳被原样采纳release tag 或外部 CI 覆盖时使用未设置时脚本从 versions.env 读取PJ_APP_VERSION拼上 UTC 时间戳%Y%m%d-%H%M与 PJ4 仓库的 10 位短 commit工作树脏则追加-dirty例如4.0.0-20261002-0139-abc1234567。这样在共享投放目录Dropbox、Nextcloud、CI artifacts中同一基础版本不同源码快照构建出的 AppImage 不会互相覆盖。运行前提ROS 2 环境的运行时要求ros2-topic-subscriber的代理不链接任何 ROS 库它加载时dlopen对应发行版的二进制而该二进制才链接rclcpp等 ROS 库。因此ROS 2 主题订阅者仅在用户机器安装了受支持 ROS 2 发行版且其环境在进程上时才出现并工作——即启动 PlotJuggler 前先source /opt/ros/distro/setup.bash机器上没有 ROS 2 时该插件保持静默这是预期行为而非错误其余所有捆绑插件不受影响、照常工作。多发行版支持的内部布局registry 模式把 zip 原样解包到usr/lib/plotjuggler/plugins/id/保留代理相对自身解析的dist/distro/结构本地编译模式在 host 流程中把data_stream_ros2/docker/run-local.sh --bundle产出的dist_ros2/整树复制为ros2-topic-subscriber/子目录build_release_appimage.sh的 host 分支、以及build_in_docker.sh容器内脚本均如此代理在运行时按$ROS_DISTRO→/opt/ros/distro→$CONDA_PREFIX/share/distro探测用户发行版并dlopen匹配的 inner。glibc 底线与可移植性可移植性的核心原则AppImage 内所有 ELF 对 glibc 的需求不得超过 2.35。默认docker 模式build_release_appimage.sh在build_in_docker.shUbuntu 22.04 / glibc 2.35内执行 app 非 ROS 2 插件构建因此产物可在任何 glibc ≥ 2.35 的发行版运行Ubuntu 22.04 及更新版本以及其他发行版家族的等价版本。ROS 2 inner 二进制始终在各发行版自己的 Docker 中构建PlotJuggler 加载的代理则在 Ubuntu 22.04 中构建与 app 的 glibc 底线一致。--host-build在宿主机编译产物继承宿主机 glibc 底线例如 Ubuntu 24.04 → glibc 2.38只能在 glibc ≥ 宿主底线的机器上运行仅用于本地迭代。release CI 会对最终产物做glibc floor audit见 linux-appimage-release.yml解包后用readelf -V扫描每个 ELF 的.gnu.version_r版本需求凡GLIBC_2.x且x 35即判定失败。审计豁免plugins/ros2-topic-subscriber/dist/*下的 per-distro inner——它们在各自发行版容器中构建、只在该发行版机器上被dlopen而代理本身位于dist/之外仍在审计范围内。源码级原理脚本内部如何实现恰好 19 个插件docker 模式容器内预过滤docker 模式下build_release_appimage.sh 通过环境变量把精选名单交给build_in_docker.shPJ_INCLUDE_PLUGINS${RELEASE_FLAT_SOS[*]} ${ROS2_EXTENSION_DIR} \ ${PJ4_ROOT}/packaging/appimage/build_in_docker.sh --plugins-dir ${PLUGINS_REPO}容器内脚本在打包步骤之前就按PJ_INCLUDE_PLUGINS空白分隔的顶层条目名单过滤/out列出的条目缺失则构建失败exit 7未列出的条目逐一删除rm -rf。这样build_appimage.sh产出的 AppImage直接只携带精选条目无需事后解包再重打包。容器内编译流程依次为scripts/ensure_core.sh按SDK_VERSION以容器 glibc 构建plotjuggler_sdk→ 聚合./build.sh一次编译全部插件含toolbox_mosaicoArrow 以 Flight gRPC 只构建一次→toolbox_transform_editor独立构建它不在聚合的add_subdirectory列表内→ 折叠dist_ros2/。host 模式暂存目录精确收集host 分支把 19 个.so逐个从插件构建树${PLUGINS_REPO}/build下*Release/bin/*路径最新匹配优先find出来复制进临时暂存目录任一缺失即报MISSING并最终失败随后把dist_ros2/整树复制为ros2-topic-subscriber/子目录最后调用APPIMAGE_EXTRACT_AND_RUN1 ./packaging/appimage/build_appimage.sh --plugins-dir ${STAGING}。容器内插件编译会排除宿主机build/与.gittar --exclude保证宿主不被污染、容器内从零开始。插件为何必须在容器内编译build_in_docker.sh 明确指出宿主编译的插件链接的是更新的 glibc会静默dlopen失败——这是捆绑插件装不上silently fail to load的头号原因。因此--plugins-dir若指向pj-official-plugins源码仓库以存在SDK_VERSIONscripts/ensure_core.sh判定源码会被复制进 builder 并在容器内以 glibc 2.35 编译若指向预编译自包含插件目录则原样复制bind-mount verbatim copy。两种情况下宿主路径都可以在任意位置——脚本替你 bind-mount无需手动暂存。构建缓存与可复现性容器内插件编译的 Conan 缓存与 ccache 持久化在两个命名 Docker 卷中pj4-appimage-plugin-conan、pj4-appimage-plugin-ccache与宿主~/.conan2较新 glibc 构建刻意分离因此 Arrow Flight gRPC protobuf 这类重依赖只从源码编译一次后续命中缓存--fresh删除两卷强制全量重编。宿主侧*-appimage-docker/目录见 build_appimage_in_docker.sh同样跨运行持久化 Conan/ccache重建是增量的。builder 镜像Dockerfile.build 的默认 final 阶段则把 Qtversions.env钉定版本、Conan 依赖闭包与固定字节的 linuxdeploy/appimagetool 全部烘进镜像层容器运行期间不联网唯一例外是--plugins-registry下载插件 zip。构建产物与验证手段产物命名遵循 build_appimage.sh 的规则常规PlotJuggler-version-arch.AppImagearch 来自versions.env的PJ_APPIMAGE_ARCH默认x86_64带 commit hashPlotJuggler-version-arch.hash.AppImage--commit-hashrelease CI 的 workflow_dispatch/非 tag 构建使用ASanPlotJuggler-version.hash-asan-arch.AppImage。脚本结束时输出Done: 路径以及模式信息docker 模式Curated 20 plugins embedded ros2(...)。验证手段有两套与脚本配套smoke_test.sh在非构建机上运行成品 AppImage——--selftest-python显示无关在 QApplication 创建前短路证明 AppRun 的PYTHONHOME覆盖能到达捆绑的 CPython stdlib Xvfb 下的 GUI 启动xvfb-runtimeout 25正常存活 25 秒即 OK。release CI 在干净容器中与packaging/deb/smoke_test.sh相邻执行用.deb的Depends隐式证明 AppImage 共享的运行时库集合。run_in_docker.sh把 AppImage 放到干净的ubuntu:22.04运行时镜像只有基础 X/GL 库中运行经xhost把 GUI 转发到宿主显示器无显示环境则报错退出。另外AppImage 内的自定义 AppRun.sh 是理解运行时行为的关键它不注入--plugin-dir该 flag 保持为用户可用选项用户传入则原样转发app 在启动时把usr/lib/plotjuggler/plugins相对usr/bin/plotjuggler4解析为../lib/plotjuggler/pluginsseed进可写的 per-user extensions 目录复制新 id、刷新版本更新的 id再从 extensions 目录加载全部插件——因此 marketplace 的安装/卸载正常工作只读 bundle 始终是 seed 源。AppRun 还负责PYTHONHOME指向捆绑 stdlibusr/lib/pythonX.Y、为 Mosaico 的 gRPC 设GRPC_DEFAULT_SSL_ROOTS_FILE_PATH指向宿主 CA bundle、unsetQT_IM_MODULE规避 IBus 输入模块在捆绑 Qt 6.11 下的崩溃。Status脚本与 release CI 的分工RELEASE_BUILD.md 的 Status 一节明确了边界build_release_appimage.sh是上述两条流的便利封装服务于本地/离线嵌入构建。release CI 不使用它。release CI.github/workflows/linux-appimage-release.yml的做法是在ghcr.io/plotjuggler/pj4-appimage-builder容器即 Dockerfile.build 的ci-base薄目标由.github/workflows/appimage-builder-image.yml发布内只编译 app所有插件一律从 registry 获取--plugins-registry --retro-wad随后做 glibc audit、--selftest-python自测与 retro payload 核验tag 构建才附加到 GitHub Releaseworkflow_dispatch 仅产 artifact。也就是说registry 是官方发布通道本地编译嵌入脚本是离线/实验通道——两条通道携带完全相同的精选插件集可互换验证。对照 README.md 的整体打包说明AppDir 也是 Debian 包的 payload、--plugins-registry默认解析 registry 的development分支、BUNDLE_IDS与 Windows 安装器$PluginIds的一致性等可以得出完整结论理解build_release_appimage.sh的本地编译嵌入流程就等于掌握了 PJ4 发布版插件捆绑的离线侧全部机制——从 19 个.so的精确收口到 ROS 2 代理与 per-distro inner 的布局再到 glibc 2.35 底线的全程守护。赞分享数据可视化桌面应用数据分析【免费下载链接】PlotJugglerThe Time Series Visualization Tool that you deserve.项目地址https://gitcode.com/gh_mirrors/pl/PlotJuggler点击查看免费下载相关推荐Tyk 插件编译器镜像tyk-plugin-compiler完全指南构建、测试与发布 Go 插件Tyk 插件编译器镜像tyk plugin compiler完全指南构建、测试与发布 Go 插件 本文以 Tyk 开源仓库 ci/images/READMAPI网关后端云原生websocketd 构建与发布全流程指南交叉编译、版本注入与发布产物质检websocketd 构建与发布全流程指南交叉编译、版本注入与发布产物质检 本指南以仓库内的构建与发布测试计划 qa/plans/14 build releaCLIWebSocket后端Rust嵌入式图形cross与embedded-graphics编译Rust嵌入式图形cross与embedded graphics编译 你还在为Rust嵌入式项目的跨平台编译烦恼吗频繁更换开发板测试、依赖库版本冲突、交叉编开发工具构建工具上一篇如何用Electron-React-Boilerplate快速构建跨平台聊天应用下一篇WebSSH公钥认证完全指南支持DSA、RSA、ECDSA、Ed25519密钥创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考