Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/README.md
T
berrux-dev 09b6df8bc3 Add per-module unit-test dirs for the Release 2 scope
One unit-test/ directory per module/target, mirroring the existing
TetraIF/unit-test/ layout (one QtTest executable per module, guarded by
BUILD_TESTING and the module target, each registered with ctest):

  Lts/Common/CodeGen      codegen_unit_test
  Lts/Common/LtsCoordinate ltscoordinate_unit_test
  Lts/Common/LtsSession   ltssession_unit_test
  Lts/DDS/Core            ddscore_unit_test
  Lts/DDS/QosProfile      ddsqos_unit_test
  Lts/Tools/LogViewer     logviewer_unit_test
  Lts/Tools/SqlBrowser    sqlbrowser_unit_test
  Z/src/NGLLogger         ngllogger_unit_test
  Z/src/WMS_Interface     wms_json_ds_unit_test
  Z/src/nglapplication    nglcoreapplication_unit_test
  Z/src/nglcompression    nglcompression_unit_test
  Z/src/nglsettings       nglsettings_unit_test
  Z/src/ngltranslator     ngltranslator_unit_test

Where a module is built with hidden visibility and has no export macro
(LogViewer, SqlBrowser, ngltranslator, NGLLogger, nglcompression,
nglsettings), its sources are compiled directly into the test
executable, the same pattern as prtcnv_unit_test.

ctest baseline in the container (QT_QPA_PLATFORM=offscreen): 20/23
passed (13 new + 7 pre-existing in-scope tests), 3 Not Run as before
(nglcomp_test, GrantleeParserSmoke, utils_test).

README: ctest baseline table extended to the 23 registered tests and
section 2.4 now documents the per-module test layout. ddsview has no
unit test (GUI tool, XmlHelper needs the DDS dynamic-xtypes runtime).
2026-11-15 01:08:17 +01:00

361 lines
17 KiB
Markdown

# qt6-migrated-legatus — Release 2 Build Guide
Build guide for the Qt6-migrated legatus tree for **Release 2** (guez project).
Everything runs inside a prebuilt Docker image; the host only needs Docker.
The source tree on this branch is pruned to the Release 2 build closure:
only the modules the 46 scope targets compile (plus their transitive
service dependencies, the codegen inputs, and the build-pipeline files)
are present — out-of-scope modules have been removed.
## Release 2 Scope
**46 targets** across 4 build groups (GROUP1, GROUP3, GROUP5, GROUP6):
| Group | Area | Count | Targets |
|---|---|---|---|
| **GROUP1** | AP4 — DDS middleware | 6 | ddscore, ddsftccore, ddsfts, ddsgen, ddsQoS, ddsconnector |
| **GROUP3** | AP3 — shared libraries, TetraIF, Lts/Common, tests | 36 | see breakdown below |
| **GROUP5** | AP9 — viewers | 3 | ddsview, LogViewer, sqlbrowser |
| **GROUP6** | AP9 — tools | 1 | ngl_codegen |
### GROUP3 breakdown
| Area | Targets |
|---|---|
| NGL stack (14) | NGLLogger, nglapplication, nglcompression, nglcoreapplication, ngldb, nglguiapplication, nglsettings, nglsingleapplication, nglsinglecoreapplication, ngltools, ngltranslator, nglwidgets, qtsingleapplication, qtsinglecoreapplication |
| Services (6) | wms_json_ds, tcpserver, LtsCoordinate, LtsCoordTrans, LtsSession, LtsMultiMonitor |
| Plugin interfaces (2) | DataPluginInterface, GuiPluginInterface |
| TetraIF (5) | CoPrtCnv, LogViewLogger, LogView, PrtCnvLib, PrtCnv |
| Additional (2) | LtsLicence, MockCoordTrans |
| Tests (7) | aes_crypt_test, ngltools_qt_smoke, lts_coord_trans_unit_test, test_nglpdfwidget, coprtcnv_unit_test, logview_unit_test, prtcnv_unit_test |
The group target lists are the `GROUP*_TARGETS` arrays in
`new_docker_build_release2.sh`.
## Entries at the tree root
- `new_docker_build_release2.sh` — Release 2 build driver (compile, ctest, DEB packaging, coverage)
- `Dockerfile` — recipe of the build image (Ubuntu 26.04 + Qt 6.10.2 + deps)
- `rpmbuild/make_rpm_ubuntu26_release2.py` — Release 2 DEB package producer (5 packages)
- `jenkins-ci-rme/` — in-tree copy of the Jenkins CI flow (see its own `README.md`)
- `build4_<timestamp>_<pid>/` — per-run build tree, created by the driver (git-ignored via `build4_*`)
**Toolchain inside the image:** Ubuntu 26.04, Qt 6.10.2 (`/opt/Qt/6.10.2/gcc_64`),
Ninja, C++17. Qt is installed via `aqt install-qt` (no apt Qt6 packages).
## Prerequisites
1. **Docker** available on the host.
2. A prebuilt build image. The driver default is `qt6-migrated-legatus-release2`;
any equivalent prebuilt image can be selected with `--docker-image`
(or `DOCKER_IMAGE`).
The driver resolves the pipeline root with this precedence:
exported `MIGRATE_PIPELINE_ROOT` → `MIGRATE_PIPELINE_ROOT` from the `.envrc`
in this directory → derived from the script location. The pipeline root is
mounted in the container at `/repo` (override with `--docker-mount-root`), so
the tree is reachable at
`/repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus`.
All commands below are run **from this directory**
(`qt6-migrated-legatus/`).
## Step 1 — Compile the Release 2 scope
```bash
./new_docker_build_release2.sh --use-prebuilt-image --docker-image <image>
```
What the driver does inside the container:
1. Creates a fresh build tree `build4_<timestamp>_<pid>` (unique per run).
2. Configures with CMake (Ninja generator):
```bash
cmake -B build4_<ts> \
-G Ninja \
-DBUILD_TESTING=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_PREFIX_PATH=/opt/Qt/6.10.2/gcc_64 \
-DCMAKE_CXX_FLAGS="-DRTI_LINUX -DRTI_UNIX" \
-DCMAKE_C_FLAGS="-DRTI_LINUX -DRTI_UNIX" \
-DBUILD_RTI=ON \
-DBUILD_GROUP1=ON -DBUILD_GROUP3=ON -DBUILD_GROUP5=ON -DBUILD_GROUP6=ON \
.
```
`BUILD_RTI=ON` is required: RTI codegen consumers (e.g. `svcPdmCommon`)
need the generated headers, and the `BUILD_RTI=OFF` stubs are not part of
this tree. The scope is selected by the `BUILD_GROUP*` flags.
3. Builds the 46 scope targets with `cmake --build ... --target <t>`
(Ninja, per target, in group order).
4. Runs **ctest** (see Step 2).
Output to inspect after the run (in the run's `build4_*` dir):
- `bin/` — executables (apps + test binaries)
- `lib/` — shared libraries
To rebuild incrementally without a fresh tree, run `ninja` in an interactive
container against the existing build dir:
```bash
B=$(ls -dt build4_* | head -1)
docker run --rm -it -v "$MIGRATE_PIPELINE_ROOT":/repo <image> \
bash -c "cd /repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/${B} && ninja -j$(nproc)"
```
## Run an executable directly
To run a built executable interactively — e.g. the GUI apps under
`bin/` (`LogView`, `LogViewer`, `PrtCnv`) against your local display — start a
shell inside the container with X11 forwarding:
```bash
B=$(ls -dt build4_* | head -1)
docker run --rm -it \
-e DISPLAY \
-e LC_ALL=C.UTF-8 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v "$MIGRATE_PIPELINE_ROOT":/repo \
<image> \
bash -c "cd /repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/${B} && exec bash"
```
## Step 2 — Run the tests
### 2.1 ctest (automatic)
The driver runs `ctest --output-on-failure -j$(nproc)` (with
`QT_QPA_PLATFORM=offscreen` — the container is headless) after the compile.
Expected baseline (23 registered, 20 in-scope tests passed, 3 Not Run):
| # | Test | Module | Result |
|---|---|---|---|
| 1 | `coprtcnv_unit_test` | TetraIF (CoPrtCnv) | Passed |
| 2 | `logview_unit_test` | TetraIF (LogView) | Passed |
| 3 | `prtcnv_unit_test` | TetraIF (PrtCnv) | Passed |
| 4 | `wms_json_ds_unit_test` | WMS_Interface | Passed |
| 5 | `nglcoreapplication_unit_test` | nglapplication | Passed |
| 6 | `nglcomp_test` | nglcompression | Not Run |
| 7 | `nglcompression_unit_test` | nglcompression | Passed |
| 8 | `nglsettings_unit_test` | nglsettings | Passed |
| 9 | `ngltranslator_unit_test` | ngltranslator | Passed |
| 10 | `NGLToolsQtSmoke` | NGLToolsQt | Passed |
| 11 | `test_nglpdfwidget` | NGLPDFWidget | Passed |
| 12 | `ngllogger_unit_test` | NGLLogger | Passed |
| 13 | `logviewer_unit_test` | LogViewer | Passed |
| 14 | `sqlbrowser_unit_test` | SqlBrowser | Passed |
| 15 | `ddsqos_unit_test` | DDS/QosProfile | Passed |
| 16 | `ddscore_unit_test` | DDS/Core | Passed |
| 17 | `GrantleeParserSmoke` | Grantlee | Not Run |
| 18 | `codegen_unit_test` | CodeGen | Passed |
| 19 | `lts_coord_trans_unit_test` | LtsCoordTrans | Passed |
| 20 | `ltscoordinate_unit_test` | LtsCoordinate | Passed |
| 21 | `aes_crypt_test` | Common (AES crypt) | Passed |
| 22 | `ltssession_unit_test` | LtsSession | Passed |
| 23 | `utils_test` | Common (LtsUtils) | Not Run |
A few tests registered by in-scope CMakeLists are not part of the 46
built targets and show up as `***Not Run` (`nglcomp_test`,
`GrantleeParserSmoke`, `utils_test`) — that is expected and the driver
continues. (Out-of-scope modules were pruned from this branch, so the
tests they registered are gone with them.)
### 2.2 Build the unit tests only
```bash
B=$(ls -dt build4_* | head -1)
docker run --rm -v "$MIGRATE_PIPELINE_ROOT":/repo <image> \
bash -c "cd /repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/${B} \
&& ninja coprtcnv_unit_test logview_unit_test prtcnv_unit_test \
codegen_unit_test ddscore_unit_test ddsqos_unit_test \
logviewer_unit_test sqlbrowser_unit_test \
ltscoordinate_unit_test ltssession_unit_test \
wms_json_ds_unit_test nglcompression_unit_test \
nglsettings_unit_test ngltranslator_unit_test \
ngllogger_unit_test nglcoreapplication_unit_test"
```
### 2.3 Run a test executable directly
GUI-free tests need the offscreen Qt platform in a headless container:
```bash
B=$(ls -dt build4_* | head -1)
docker run --rm -it -v "$MIGRATE_PIPELINE_ROOT":/repo <image> \
bash -c "export QT_QPA_PLATFORM=offscreen
cd /repo/qt-migration-legatus/qt6-after/qt6-migrated-legatus/${B}
./bin/coprtcnv_unit_test # CoPrtCnv: telegrams, fragmentation, helpers
./bin/logview_unit_test # LogView: IntegerCalculator
./bin/prtcnv_unit_test # PrtCnv: PrtCnvMember fragmented-telegram handling
./bin/lts_coord_trans_unit_test
./bin/aes_crypt_test
./bin/test_nglpdfwidget
# or everything registered:
ctest --output-on-failure"
```
Each QtTest binary accepts a single slot name to run just one test,
e.g. `./bin/coprtcnv_unit_test radioTelegramFragmentationRoundtrip`.
### 2.4 Unit tests per module
Each in-scope module has its own `unit-test/` directory (the original
`TetraIF/unit-test/` layout, one test executable per module, each
registered with ctest):
| Test | Module | Covers |
|---|---|---|
| `coprtcnv_unit_test` | TetraIF | `CoPrtCnv` — telegram header fields, payload access, length checks, fragmentation/reassembly roundtrip, id→string helpers |
| `logview_unit_test` | TetraIF | `LogView` — `IntegerCalculator` (arithmetic, precedence, error codes, variables) |
| `prtcnv_unit_test` | TetraIF | `PrtCnv` — `PrtCnvMember` state + fragmented-telegram add/reassembly |
| `codegen_unit_test` | Common/CodeGen | name transforms, member/data/function/IDL wrappers, Grantlee wrapper getters (incl. JSON↔variant fallbacks), base data classes (`MemberInformation`/`CppData` `toString`) |
| `ddscore_unit_test` | DDS/Core | `ddsview`-independent DDS core helpers |
| `ddsqos_unit_test` | DDS/QosProfile | `DDS_DefaultQos` — default profile load, SHM/UDP/TCP participant QoS, default datawriter/datareader QoS, `print()` |
| `logviewer_unit_test` | Tools/LogViewer | `LogViewTableModel` (dimensions, roles, invalid index, header data, level colors, add/set data) + `SortFilterModel` (string/date filters, reset, date/level sort, `figureFilterOut`) |
| `sqlbrowser_unit_test` | Tools/SqlBrowser | `DataModel` (swap lists, role handling, tooltip timestamp, editability, set-data slots, delete lines) + `AddModel` (row creation, value stringification, remove/clear) |
| `ltscoordinate_unit_test` | Common/LtsCoordinate | constructors/geo accessors, validity checks, MGRS formatting, geo↔UTM roundtrips, UTM distances, angle degrees, elevation callback, `LtsCoordVector` |
| `ltssession_unit_test` | Common/LtsSession | session API roundtrips |
| `wms_json_ds_unit_test` | WMS_Interface | JSON dataset roundtrips (exercises, requirements, units) — `toJson`/`fromJson` fidelity |
| `nglcompression_unit_test` | nglcompression | `nglcomp` archive/tar filter helpers |
| `nglsettings_unit_test` | nglsettings | `NGL::Settings` + `NGL::Connections` (port offset, server hostname) |
| `ngltranslator_unit_test` | ngltranslator | `Translator` — catalog + `translate` (missing context, plural, disambiguation), JSON catalog import (valid/invalid, md5 cache, compressed), locale handling |
| `ngllogger_unit_test` | NGLLogger | `LoggerHierarchyHelper` naming/instance caching, log level ordering/enabled checks, bootstrap create/get, `AlreadyCreatedError` |
| `nglcoreapplication_unit_test` | nglapplication | `LoggerHandler` — `createLogger` naming (prefix/postfix), duplicate-root `AlreadyCreatedError` |
Hidden-visibility note: the tree builds with `CMAKE_CXX_VISIBILITY_PRESET
hidden`, so classes without an export macro are not in the shared
library's dynamic symbol table. Where a module has no export macro
(`LogViewer`, `SqlBrowser`, `ngltranslator`, `NGLLogger`, `nglcompression`,
`nglsettings`), its test compiles the module source files directly into
the test executable (same pattern as `prtcnv_unit_test`).
`ddsview` has no unit test: it is a GUI tool whose `XmlHelper` needs the
DDS dynamic-xtypes runtime and a GUI model.
Sources are registered with ctest via each module's
`unit-test/CMakeLists.txt` (guarded by `BUILD_TESTING` and by the module
target existing).
## Step 3 — Produce the Release 2 DEB packages
```bash
./new_docker_build_release2.sh --use-prebuilt-image --docker-image <image> \
--run-jenkins-builder \
--package-output-dir ./packages-out \
> /path/to/build.log 2>&1
```
The driver compiles the Release 2 scope (46 targets), runs ctest, then stages
the tree and runs `rpmbuild/make_rpm_ubuntu26_release2.py`, which builds the
scope again (Release configuration, Ninja, scoped target list) and produces
5 DEBs in `${MIGRATE_PIPELINE_ROOT}/rpms/${PROJECT}/${OS_VERSION}/`
(default `rpms/guez/26.04/`). A copy is also placed in `--package-output-dir`
(default `./packages-out`):
| DEB | Contents |
|---|---|
| `qt6-release-runtime_1.0-1_amd64.deb` | Release 2 executables + libraries, staged from the scoped build's `bin/` and `lib/` |
| `qt6-release-sources_1.0-1_amd64.deb` | Release 2 scope sources (source files + CMakeLists under the release dirs) |
| `qt6-release-ctest-runtime_1.0-1_amd64.deb` | Test executables under `/usr/lib/ctest/` (currently empty — the producer looks for a `build4/bin/` dir, which the driver's timestamped `build4_<ts>/` dirs do not match) |
| `qt6-release-ctest-sources_1.0-1_amd64.deb` | Test sources (files with "test" in the name under release dirs) |
| `qt6-release-build-pipeline_1.0-1_amd64.deb` | In-tree pipeline files (the producer's `PIPELINE_FILES`: `new_docker_build_release2.sh`, `Dockerfile`, `jenkins-ci-rme/*`, `rpmbuild/make_rpm_ubuntu26_release2.py`, `CMakeLists.txt`) under `/usr/src/pipeline/` |
(Version string = `--lts-version` + `-` + `--build-number`, default `1.0-1`.)
Verify a package:
```bash
dpkg -c "${MIGRATE_PIPELINE_ROOT}/rpms/guez/26.04/qt6-release-runtime_1.0-1_amd64.deb"
dpkg -i "${MIGRATE_PIPELINE_ROOT}/rpms/guez/26.04/"*.deb # install locally, if wanted
```
## Step 4 — CI / Jenkins flow (optional)
The in-tree `jenkins-ci-rme/` directory contains the full Jenkins
pipeline (`Jenkinsfile`, builder, publisher) adapted to this tree. For a
local dry run of the same flow without Jenkins:
```bash
jenkins-ci-rme/release-16-10-2026.sh
```
See `jenkins-ci-rme/README.md` for the pipeline details.
## Step 5 — Code coverage (lcov)
```bash
./new_docker_build_release2.sh --use-prebuilt-image --docker-image <image> \
--run-coverage \
--coverage-output-dir ./coverage-out \
> /path/to/coverage.log 2>&1
```
The driver builds the Release 2 scope with `-O0 --coverage`, runs the same
ctest suite, then captures the data with lcov: the report covers the Release 2
scope (AP3, AP4, AP9, TetraIF, Z/src, Lts/Common), and test sources are
filtered out of the report, so the percentages reflect the module code.
Artifacts in the coverage output directory:
| File | Contents |
|---|---|
| `html/index.html` | browsable report (line + branch coverage per file) |
| `coverage.info` | machine-readable lcov tracefile |
| `coverage_summary.txt` | whole-scope totals |
`--run-coverage` is mutually exclusive with `--run-jenkins-builder` (different
instrumentation of the same build tree).
The Jenkins pipeline runs the same step on every build (`RunCoverage`
parameter, on by default); the local dry run
(`jenkins-ci-rme/release-16-10-2026.sh`) does the same, with
`DRYRUN_COVERAGE=OFF` to skip coverage there.
## Options reference
`./new_docker_build_release2.sh --help` prints the full option list. The main
ones:
| Option | Default | Purpose |
|---|---|---|
| `--group1 / --group3 / --group5 / --group6` (or `--no-…`) | all on | enable/disable the build groups (AP4 / AP3 / AP9 / AP9) |
| `--no-ctest` | off | skip ctest |
| `--tests-only` | off | run ctest only, skip the build groups |
| `--use-prebuilt-image` / `--no-prebuilt-image` | off | use a prebuilt image vs. apt install in-container |
| `--docker-image IMAGE` | `qt6-migrated-legatus-release2` | image to use |
| `--cmake_build_flags FLAGS` | — | extra `-D` flags for the in-container configure |
| `--run-jenkins-builder` | off | produce the DEB packages (Step 3) |
| `--package-output-dir DIR` | `./packages-out` | host dir that receives the DEB copy |
| `--lts-version VERSION` | `1.0` | package version prefix |
| `--project NAME` | `guez` | project name for package naming |
| `--build-number NUM` / `--build-tag TAG` | `1` / `manual-build` | package metadata |
| `--run-coverage` | off | coverage build + lcov report (Step 5) |
| `--coverage-output-dir DIR` | `./coverage-out` | where the coverage report is written |
| `--docker-mount-root PATH` | `/repo` | container-side mount root |
Environment overrides: `BUILD_GROUP1..6`, `RUN_CTEST`, `TESTS_ONLY`,
`USE_PREBUILT_IMAGE`, `DOCKER_IMAGE`, `CMAKE_BUILD_FLAGS`,
`DOCKER_MOUNT_ROOT`, `RUN_JENKINS_BUILDER`, `PACKAGE_OUTPUT_DIR`,
`LTS_VERSION`, `PROJECT`, `BUILD_NUMBER`, `BUILD_TAG`, `RUN_COVERAGE`,
`COVERAGE_OUTPUT_DIR`, `GUEZ_MODE`, `MIGRATE_PIPELINE_ROOT`.
## Troubleshooting
- **"no Qt platform plugin could be initialized"** when running a test
binary by hand → `export QT_QPA_PLATFORM=offscreen`.
- **Stale build tree** → the driver always creates a fresh
`build4_<timestamp>_<pid>` dir per run; old dirs are git-ignored scratch
areas and can be deleted freely.
- **DEBs not on the host** → the output dir must be a path that exists
*on the host*; check the `--package-output-dir` argument and the
`rpms/<project>/<os>/` dir under the pipeline root.
- **Build fails with missing Qt modules** → the image must be a prebuilt
Release 2 image (Qt 6.10.2 installed via `aqt install-qt`); select it with
`--docker-image`.
- **DDS build fails on the license** → `rti_license.dat` must be present at
the source tree root; the driver exports `RTI_LICENSE` for in-container
use.