Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 256 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
name: Build plugin

on:
push:
branches: [main]
tags: ['v[0-9]+.[0-9]+.[0-9]+']
pull_request:
workflow_dispatch:

env:
# Single source of truth: both the clone and the cache key derive from this.
PJ_TAG: '3.9.2'

jobs:
# Build PlotJuggler once per platform and cache the install tree. Hoisted out of
# the plugin matrix so it is not rebuilt once per build configuration.
plotjuggler:
name: PlotJuggler (${{ matrix.platform.label }})
runs-on: ${{ matrix.platform.os }}
container:
# Ubuntu is built inside a 22.04 container rather than on a 24.04 runner so
# the artifacts keep the older libstdc++/glibc floor: a binary built against
# GCC 13 needs GLIBCXX_3.4.32 and will not load on Ubuntu 22.04, while a
# 22.04 build loads on both. This also matches the Dockerfile exactly, so a
# CI failure reproduces locally with `docker build`.
image: ${{ matrix.platform.container || '' }}
strategy:
fail-fast: false
matrix:
platform:
- { os: ubuntu-latest, container: 'ubuntu:22.04', label: ubuntu-22.04 }
- { os: windows-2022, label: windows-2022 }

steps:
# GITHUB_WORKSPACE is backslash-separated on Windows; normalise it so a
# single bash step can hand the path to cmake on every platform.
- name: Resolve install prefix
shell: bash
run: echo "PJ_INSTALL=${GITHUB_WORKSPACE//\\//}/pj_install" >> "$GITHUB_ENV"

# The label is part of the key because runner.os alone cannot tell a 22.04
# container build from a build on the runner's own newer userland.
- name: Cache PlotJuggler install
id: cache
uses: actions/cache@v6
with:
path: pj_install
key: ${{ matrix.platform.label }}-plotjuggler-${{ env.PJ_TAG }}

- name: Install PlotJuggler dependencies
if: steps.cache.outputs.cache-hit != 'true' && runner.os == 'Linux'
# No sudo: the container runs as root. python3 matters -- CMakeLists falls
# back to an empty LogMessageDescriptions.h without it, silently dropping
# the field tooltips from the built plugin.
run: |
apt-get update
apt-get install -y --no-install-recommends \
build-essential cmake git ca-certificates python3 zstd \
qtbase5-dev libqt5svg5-dev libqt5websockets5-dev libqt5opengl5-dev \
libqt5x11extras5-dev libprotoc-dev libzmq3-dev liblz4-dev libzstd-dev

- name: Install Qt
if: steps.cache.outputs.cache-hit != 'true' && runner.os == 'Windows'
uses: jurplel/install-qt-action@v4
with:
version: '5.15.2'
arch: 'win64_msvc2019_64'

- name: Clone PlotJuggler
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: git clone --depth 1 --branch "$PJ_TAG" https://github.com/facontidavide/PlotJuggler.git plotjuggler

- name: Configure PlotJuggler
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
# CMAKE_POLICY_VERSION_MINIMUM is insurance: PlotJuggler 3.9.2 ships
# third-party directories declaring cmake_minimum_required(VERSION 3.0),
# which CMake 4 rejects outright. Ignored by CMake older than 3.31.
run: |
cmake -S plotjuggler -B pj_build \
-DCMAKE_INSTALL_PREFIX="$PJ_INSTALL" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5

- name: Build & install PlotJuggler
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: cmake --build pj_build --config RelWithDebInfo --target install --parallel "$(nproc || echo 2)"

plugin:
name: ${{ matrix.config.name }} (${{ matrix.platform.label }})
needs: plotjuggler
runs-on: ${{ matrix.platform.os }}
container:
image: ${{ matrix.platform.container || '' }}
strategy:
# Never let one configuration mask the others.
fail-fast: false
matrix:
platform:
- { os: ubuntu-latest, container: 'ubuntu:22.04', label: ubuntu-22.04 }
- { os: windows-2022, label: windows-2022 }
config:
- name: units
units: 'ON'
rcou: 'OFF'
- name: units-rcou
units: 'ON'
rcou: 'ON'
- name: plain
units: 'OFF'
rcou: 'OFF'

steps:
# Before checkout, so that actions/checkout finds git and makes a real clone
# instead of falling back to a source tarball.
- name: Install plugin dependencies
if: runner.os == 'Linux'
run: |
apt-get update
apt-get install -y --no-install-recommends \
build-essential cmake git ca-certificates python3 zstd \
qtbase5-dev libqt5svg5-dev libqt5websockets5-dev libqt5opengl5-dev \
libqt5x11extras5-dev

- name: Checkout plugin
uses: actions/checkout@v7

- name: Resolve install prefix
shell: bash
run: echo "PJ_INSTALL=${GITHUB_WORKSPACE//\\//}/pj_install" >> "$GITHUB_ENV"

# The plotjuggler job has already populated this key, so a miss means
# something is wrong and should fail loudly rather than rebuild silently.
- name: Restore PlotJuggler install
uses: actions/cache/restore@v6
with:
path: pj_install
key: ${{ matrix.platform.label }}-plotjuggler-${{ env.PJ_TAG }}
fail-on-cache-miss: true

- name: Install Qt
if: runner.os == 'Windows'
uses: jurplel/install-qt-action@v4
with:
version: '5.15.2'
arch: 'win64_msvc2019_64'

- name: Configure plugin
shell: bash
run: |
cmake -S . -B build \
-Dplotjuggler_DIR="$PJ_INSTALL/lib/cmake/plotjuggler" \
-DCMAKE_BUILD_TYPE=Release \
-DADD_UNITS=${{ matrix.config.units }} \
-DADD_RCOU_FUNCTION_LABELS=${{ matrix.config.rcou }}

- name: Build plugin
shell: bash
run: cmake --build build --config Release --parallel "$(nproc || echo 2)"

- name: Install plugin
shell: bash
run: cmake --install build --prefix plugin_install --config Release

- name: Build smoke test
shell: bash
run: |
cmake -S tests -B tests/build \
-DPJ_INCLUDE_DIR="$PJ_INSTALL/include" \
-DCMAKE_BUILD_TYPE=Release
cmake --build tests/build --config Release --parallel "$(nproc || echo 2)"

# Loads the plugin exactly as PlotJuggler does and parses a real log, so a
# plugin that builds but cannot be loaded fails here instead of in a user's
# hands. The --expect-* flags additionally assert that this job's CMake
# options actually reached the binary, which a build log cannot tell you.
# offscreen because CI has no display.
- name: Smoke test plugin
shell: bash
env:
QT_QPA_PLATFORM: offscreen
run: |
if [ -x tests/build/pj_plugin_smoketest ]; then
smoketest=tests/build/pj_plugin_smoketest
else
smoketest=tests/build/Release/pj_plugin_smoketest.exe
fi
plugin="$(find plugin_install -type f \( -name '*.so' -o -name '*.dll' \) -print -quit)"
# --verify is unconditional so that the all-OFF 'plain' configuration is
# asserted too, not merely reported.
expect=(--verify)
if [ "${{ matrix.config.units }}" = "ON" ]; then
expect+=(--expect-units)
fi
if [ "${{ matrix.config.rcou }}" = "ON" ]; then
expect+=(--expect-rcou)
fi
echo "Testing $plugin ${expect[*]}"
"$smoketest" "$plugin" tests/logs/00000001.BIN "${expect[@]}"

- name: Upload plugin artifact
uses: actions/upload-artifact@v7
with:
name: DataAPBin-${{ matrix.platform.label }}-${{ matrix.config.name }}
path: plugin_install/
if-no-files-found: error

release:
name: Draft release
needs: plugin
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- name: Checkout plugin
uses: actions/checkout@v7

- name: Download all plugin artifacts
uses: actions/download-artifact@v8
with:
path: artifacts

# Each artifact holds a single shared library under bin/. Flatten them
# into uniquely named assets, keeping the real extension so a downloaded
# asset is still recognisable as a plugin.
- name: Collect release assets
run: |
set -euo pipefail
mkdir -p assets
for dir in artifacts/*/; do
variant="$(basename "$dir")"
variant="${variant#DataAPBin-}"
# -print -quit rather than piping to head: under `set -o pipefail` a
# closed pipe would make find fail the whole step.
lib="$(find "$dir" -type f \( -name '*.so' -o -name '*.dll' -o -name '*.dylib' \) -print -quit)"
if [ -z "$lib" ]; then
echo "No plugin library found in $dir" >&2
exit 1
fi
case "$lib" in
*.dll) cp "$lib" "assets/DataAPBin-$variant.dll" ;;
*) cp "$lib" "assets/libDataAPBin-$variant.${lib##*.}" ;;
esac
done
ls -l assets

- name: Create draft release
uses: softprops/action-gh-release@v3
with:
draft: true
files: assets/*
fail_on_unmatched_files: true
81 changes: 0 additions & 81 deletions .github/workflows/win_build.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@
*.app
/CMakeLists.txt.user
build/*
tests/build/
4 changes: 2 additions & 2 deletions DataLoadAPBin/dataload_apbin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
//#define DEBUG_MULTIPLIERS
//#define DEBUG_UNITS

// Config
#define LABEL_WITH_UNIT
// LABEL_WITH_UNIT and LABEL_RCOU_FUNCTION are set by the build: see the
// ADD_UNITS and ADD_RCOU_FUNCTION_LABELS options in CMakeLists.txt.

bool is_nearly(double val, int val2)
{
Expand Down
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ Once compilation is finished, you will find your `.so` plugin in the `artifacts`
sudo apt -y install qtbase5-dev libqt5svg5-dev
```

2. If you want the units to be displayed in PlotJuggler (read at the end), you need to edit `dataload_apbin.cpp` and activate `#define LABEL_WITH_UNIT`.
2. The optional features are selected with cmake options, both `OFF` by default:
- `-DADD_UNITS=ON` displays the units of the logged fields (read at the end).
- `-DADD_RCOU_FUNCTION_LABELS=ON` displays the channel function next to its name.

3. Compile using cmake:

Expand All @@ -74,6 +76,23 @@ Once compilation is finished, you will find your `.so` plugin in the `artifacts`
sudo make install
```

### Testing a built plugin

`tests/` holds a headless check that loads a plugin the way PlotJuggler does and
parses the small log in `tests/logs/`, without starting the GUI.
It also verifies that the cmake options above actually reached the binary, and on
Linux reports whether the plugin's libstdc++ requirement is satisfied by your
system — which is what catches a plugin built on a newer distro than the one
running it.

```bash
cmake -S tests -B tests/build -DPJ_INCLUDE_DIR="$PJ_WS/install/include"
cmake --build tests/build
./tests/test_plugin.sh build/libDataAPBin.so
```

Point it at a plugin downloaded from CI or a release to check it before use.

### Notes for building on MacOS

Qt dependencies may not be found automatically.
Expand Down
Loading