Compare commits

...
Author SHA1 Message Date
berrux-dev d130c55be5 Fix Qt6 resource compilation so LogView icons are embedded at runtime
- QT5_ADD_RESOURCES was a no-op stub under Qt6, silently dropping .qrc
  files: LogView's :/image/* icons were never compiled into the binary.
  Map the stub onto qt6_add_resources() (outfiles-variable form, which
  appends the generated qrc_*.cpp to the source list). LogView is the
  only caller of the stub.
- nglwidgets' Qt6 branch only processed rme_light_style.qrc;
  nglresources.qrc (which provides :icons/16x16/* toolbar/window icons)
  was left as a raw file in the source list and never compiled
  (CMAKE_AUTORCC is off). Process both qrcs.
- LogView never loads libnglwidgets.so at runtime (--as-needed drops it:
  the code uses no nglwidgets symbols), so its :icons/16x16 resources
  were never registered for the app. Embed the 20 icons LogView actually
  uses directly into LogViewResources.qrc with explicit aliases (rcc
  rejects XML comments in .qrc and, without an alias, registers the full
  relative path as the resource name).
2026-11-03 13:31:02 +01:00
berrux-dev 0e2100f383 reset Jenkins file 2026-10-15 20:43:46 +02:00
berrux-dev 26f702b7a4 reset jenkins file 2026-10-15 20:40:29 +02:00
berrux-dev 37bd700564 Fixed make error 2026-10-15 12:21:52 +02:00
berrux-dev 684e05109d Add lcov code coverage to the release pipeline and Jenkins
- new_docker_build.sh: new --run-coverage mode (mutually exclusive with
  --run-jenkins-builder). Instruments the release-scope build with
  -O0 -g --coverage -fPIC -DNDEBUG (RELEASE flag override keeps -DNDEBUG
  and -fPIC so behavior and PIC match the green baseline), runs ctest,
  then collects the lcov report: capture --external -> extract on the
  four release dirs -> remove test sources -> summary -> genhtml, all
  with --ignore-errors mismatch,inconsistent,unused (GCC 15 + lcov 2.4).
  Report lands in --coverage-output-dir (default ./coverage-out):
  html/index.html, coverage.info, coverage_summary.txt.
- Dockerfile image gains lcov via APT_PACKAGES (genhtml ships in the
  same package).
- Jenkinsfile: RunCoverage parameter (default on) + per-OS Coverage
  stage running the driver on the agent and archiving
  coverage/<project>/<os>/**.
- release-16-10-2026.sh: same coverage step, gated by DRYRUN_COVERAGE
  (default ON, mirrors the Jenkins default).
- README: Step 6 (code coverage) and options/env reference entries.
- .gitignore: coverage-out/
2026-10-15 09:00:33 +02:00
berrux-dev 676ae05335 Rewrite the build README without excluded-module sections
Scope is now described only as what the release build contains
(TetraIF, Z/src, Lts/Common, TrainingAreaBase). All steps (image,
compile, tests, DEB packaging, Jenkins) kept and refreshed; the
license note is reduced to 'no license file is required'.
2026-10-14 20:40:05 +02:00
berrux-dev a17b431669 Trim stub header comments and redundant explanations
- Drop the 'Stub file ... BUILD_RTI=OFF / Auto-generated' headers from the
  tab_* and pdm_* stub files (RTI is gone on this branch; the names say it)
- Drop stub comments from MockCoordTrans.h and the coordTransTests placeholders
- Drop the DDS exclusion list comment from Lts/Common/CMakeLists.txt
- Shorten the staging and packages-out comments in new_docker_build.sh
2026-10-14 20:30:09 +02:00
berrux-dev 493893d2e6 Reduce make_rpm_ubuntu26.py line count (925 to 526) without changing behavior
- Merge build_single_deb and build_single_deb_nobuild into one build_deb()
- Add build_nobuild_package() factory for the 4 no-build packages
- Extract run(), prune_dirs() and write_deb_file() helpers
- Drop the unreachable release_scope copy branch (all call sites used the
  full-tree copy; the --release_scope CLI flag is kept)
- Trim pipeline_files to the 8 files that actually exist and are packaged
- Remove unused imports (configparser, getpass, re, datetime, Path, stat),
  unused vars (test_patterns, script_extensions) and a duplicated write block
2026-10-14 20:25:51 +02:00
29 changed files with 662 additions and 907 deletions

No files matched your search

@@ -14,3 +14,4 @@ build/
build2/
.envrc
build4
coverage-out/
@@ -4,12 +4,6 @@
# $Author$
#
# Release scope: modules with DDS/RTI dependencies not needed for TetraIF/Z are excluded
# DDS-dependent modules: CodeGen, LtsAppManager, LtsBotan, LtsCoordinate, LtsElevation,
# LtsLogin, LtsMultiMonitor, LtsPluginManager, LtsPrinting, LtsProjectionWorkstation,
# LtsScriptTimeline, LtsSession, LtsTimelineClassic, LtsVirtualKeyboard, LtsWidgets,
# PluginInterfaces (TopicReplayInterface, RecordReplayPlugin), TopicEditorBase
# Core modules needed for TetraIF and Z
ADD_SUBDIRECTORY(CommonUnitTestsPlaceholder)
ADD_SUBDIRECTORY(httq)
@@ -1,4 +1,4 @@
// Stub GTest smoke test for coordTrans
#include <gtest/gtest.h>
TEST(CoordTransSmokeTest, StubTest)
@@ -1,4 +1,4 @@
// Stub QtTest smoke test for coordTrans
#include <QTest>
class CoordTransSmokeTest : public QObject
@@ -1,5 +1,3 @@
// MockCoordTrans.h - Stub mock for CoordTrans functionality
// This is a placeholder to allow builds without full CoordTrans implementation
#ifndef MOCK_COORD_TRANS_H
#define MOCK_COORD_TRANS_H
@@ -35,8 +35,6 @@ NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptor
NGL_INSTALL_TARGET(LtsAppDescriptor)
# LtsAppDescriptorChecker
SET(LtsAppDescriptorChecker_SRCS
checker/main.cpp
@@ -51,27 +49,6 @@ NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorChecker
Qt6::Core
)
# LtsAppDescriptorEditor => Hat niemand benutzt, wird keiner benutzen, also wird der bis auf Weiteres auch nicht an die neue Syntax angepasst.
#SET(LtsAppDescriptorEditor_SRCS
# lts_app_descriptor_editor.cpp
# lts_app_descriptor_editor.h
#)
#NGL_WRAP_UI(LtsAppDescriptorEditor_SRCS
# lts_app_descriptor_editor.ui
#)
#NGL_ADD_LIBRARY2(WS NO_TRANSLATION LtsAppDescriptorEditor SHARED ${LtsAppDescriptorEditor_SRCS})
#NGL_TARGET_INCLUDE_DIRECTORIES(LtsAppDescriptorEditor
# PUBLIC
# ${CMAKE_CURRENT_SOURCE_DIR}/../
#)
if(QT6_GUI_AVAILABLE)
#NGL_TARGET_LINK_LIBRARIES(LtsAppDescriptorEditor
# PUBLIC
@@ -1,14 +1,6 @@
# Modified CMakeLists.txt from github.com/wille-io/httq
# Make ${Qt6_WebSockets} optional
# Link the real WebSockets module whenever the websocket code path is
# compiled: QT6_WEBSOCKETS_AVAILABLE (root CMakeLists) and the manual
# Qt6::WebSockets import are set when the real module was found. The old
# QT6_GUI_AVAILABLE condition never held in this environment (Qt6
# discovery takes the minimal path) and the Qt6_WebSockets variable was
# never defined, so AbstractServer.cpp compiled the websocket code
# without the module on the link line (undefined reference to
# QWebSocketServer::handleConnection).
if(QT6_WEBSOCKETS_REAL_FOUND OR Qt6WebSockets_FOUND)
set(Qt6_WebSockets Qt6::WebSockets)
else()
@@ -33,6 +33,9 @@ SET(SRCS_telegrams
training_area_telegrams.h
)
NGL_ADD_LIBRARY(AAR SV WS HLA tabTelegrams STATIC ${SRCS_telegrams})
# tabTelegrams is a STATIC lib linked into shared/MODULE targets
SET_TARGET_PROPERTIES(tabTelegrams PROPERTIES POSITION_INDEPENDENT_CODE ON)
NGL_TARGET_INCLUDE_DIRECTORIES(tabTelegrams
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/..
@@ -78,8 +81,6 @@ LIST(APPEND SRCS_common
# Create target only if component flags allow
NGL_ADD_LIBRARY2(AAR SV WS HLA svcTabCommon SHARED ${SRCS_common})
# Generate export header ALWAYS (needed for logger.h even if target not built)
# Use custom command to create minimal export header if target wasn't created
IF(NOT TARGET svcTabCommon)
# Create a dummy static library just for export header generation
ADD_LIBRARY(svcTabCommon STATIC ${SRCS_common})
@@ -1,5 +1,3 @@
// Stub file for tab_db - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated database code
#ifndef TAB_DB_STUB_HPP
#define TAB_DB_STUB_HPP
@@ -1,5 +1,3 @@
// Stub file for tab_enums - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated enums
#ifndef TAB_ENUMS_STUB_HPP
#define TAB_ENUMS_STUB_HPP
@@ -1,6 +1,3 @@
// Stub file for tab types - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated types
#ifndef TAB_STUB_HPP
#define TAB_STUB_HPP
@@ -1,6 +1,3 @@
// Stub file for tab_topic_type_plugin - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated plugin code
#include "tab_enums_stub.hpp"
namespace tab
@@ -1,5 +1,3 @@
// Stub file for pdm - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated code
#ifndef PDM_HPP
#define PDM_HPP
@@ -10,9 +8,6 @@
#include <QString>
#include <QStringList>
// Forward declarations and stub types for ProjectDataManagement namespace
// Used when BUILD_RTI=OFF to allow compilation without RTI Connext DDS
namespace ProjectDataManagement
{
@@ -1,6 +1,3 @@
// Stub file for pdm_db - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated database code
#ifndef PDM_DB_STUB_HPP
#define PDM_DB_STUB_HPP
@@ -1,5 +1,3 @@
// Stub file for pdm_enums - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated code
#ifndef PDM_ENUMS_STUB_HPP
#define PDM_ENUMS_STUB_HPP
@@ -1,5 +1,3 @@
// Stub file for pdm - BUILD_RTI=OFF
// Auto-generated stub to replace RTI IDL-generated code
#ifndef PDM_STUB_HPP
#define PDM_STUB_HPP
+87 -24
View File
@@ -1,30 +1,31 @@
# qt6-migrated-legatus — compile and run (step by step)
# qt6-migrated-legatus — build and run, step by step
Build guide for the Qt6-migrated legatus tree on the release
**validation-scope** branch. Everything runs inside a prebuilt Docker
image; the host only needs Docker.
## Scope and layout
## Scope
The release scope built by `new_docker_build.sh` is:
What `new_docker_build.sh` builds and packages:
| Area | Contents |
|---|---|
| `TetraIF/` | `CoPrtCnv`, `LogView`, `PrtCnv` (+ `unit-test/` — see below) |
| `TetraIF/` | `CoPrtCnv`, `LogView`, `PrtCnv` (+ `unit-test/` — see Step 3) |
| `Z/src/` | NGL application/core library stack (NGLLogger, nglcoreapplication, …) |
| `Lts/Common/` | LTS common libraries (LtsCoordTrans, LtsLicence, …) |
| `Lts/Proxies/TrainingAreaBase` | built as a dependency of TetraIF |
| `Lts/Common/` | LTS common libraries (LtsCoordTrans, LtsLicence, LtsUtils, …) |
| `Lts/Proxies/TrainingAreaBase` | `tabTelegrams` library, built as a TetraIF dependency |
Useful entries at the tree root:
Entries at the tree root:
- `new_docker_build.sh` — the build driver (image build, compile, ctest, DEB packaging)
- `new_docker_build.sh` — build driver (image build, compile, ctest, DEB packaging)
- `Dockerfile` — recipe of the prebuilt build image (Ubuntu 26.04 + Qt 6.10.2 + deps)
- `rpmbuild/make_rpm_ubuntu26.py` — in-tree DEB package producer (self-contained)
- `jenkins-ci-rme/` — in-tree copy of the Jenkins CI flow (see its own `README.md`)
- `build4/` — build tree, created by the driver (git-ignored scratch area)
Toolchain inside the image: **Ubuntu 26.04, GCC 15.2.0, Qt 6.10.2**
(`/opt/Qt/6.10.2/gcc_64`), C++17, Release build.
(`/opt/Qt/6.10.2/gcc_64`), C++17, Release build. No license file is
required.
## Prerequisites
@@ -35,14 +36,12 @@ Toolchain inside the image: **Ubuntu 26.04, GCC 15.2.0, Qt 6.10.2**
`new_docker_build.sh` invokes Docker, so running the driver as-is
satisfies this.
No license file is required: the RTI Connext DDS modules (the only
consumers of an RTI license) are not part of the release scope and are
never compiled on this branch.
`new_docker_build.sh` resolves the pipeline root from its own location
(override with the exported `MIGRATE_PIPELINE_ROOT` or the `.envrc` in
this directory).
The driver resolves the pipeline root from its own location (override
with the exported `MIGRATE_PIPELINE_ROOT` or the `.envrc` in this
directory).
All commands below are run **from this directory** (`qt6-migrated-legatus/`).
All commands below are run **from this directory**
(`qt6-migrated-legatus/`).
## Step 1 — Build the prebuilt Docker image (once)
@@ -70,7 +69,7 @@ To remove it later:
What the driver does inside the container:
1. `rm -rf build4 && mkdir build4 && cd build4` (fresh build tree)
2. Configure with CMake — the mandatory flags:
2. Configure with CMake:
```bash
cmake .. \
@@ -84,7 +83,7 @@ What the driver does inside the container:
(`RELEASE_BUILD=ON` selects the release scope; everything else is at
its CMake default.)
3. `make -j8` the release-scope targets (TetraIF modules, Z stack,
Lts/Common libs, all test executables — the list is
Lts/Common libraries, all test executables — the list is
`RELEASE_BUILD_TARGETS` in `new_docker_build.sh`).
4. Run **ctest** (see Step 3).
@@ -96,7 +95,29 @@ Output to inspect after the run:
- `build4/lib/` — shared libraries
To rebuild incrementally without a fresh tree, run `make` directly in an
interactive container (Step 4).
interactive container against the existing `build4/`:
```bash
docker run --rm -it -v /path/to/pipeline-root:/workspace legatus-qt6:1.0 \
bash -c 'cd /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus/build4 \
&& make -j8'
```
## Run an executable directly
To run a built executable interactively — e.g. the GUI apps under
`build4/bin/` (`LogView`, `PrtCnv`) against your local display — start a
shell inside the container with X11 forwarding:
```bash
docker run --rm -it \
-e DISPLAY \
-e LC_ALL=C.UTF-8 \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /path/to/pipeline-root:/workspace \
legatus-qt6:1.0 \
bash -c 'cd /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus/build4 && exec bash'
```
## Step 3 — Run the tests
@@ -145,7 +166,7 @@ ctest --output-on-failure'
Each QtTest binary accepts a single slot name to run just one test,
e.g. `./bin/coprtcnv_unit_test radioTelegramFragmentationRoundtrip`.
### 3.4 TetraIF unit tests (this tree, `TetraIF/unit-test/`)
### 3.4 TetraIF unit tests (`TetraIF/unit-test/`)
| Test | Module covered | Note |
|---|---|---|
@@ -182,7 +203,7 @@ DEBs in `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/`:
| `qt6-release-sources_*` | release-scope sources |
| `qt6-release-ctest-runtime_*` | test executables under `/usr/lib/ctest/` (incl. the TetraIF unit tests) |
| `qt6-release-ctest-sources_*` | test sources (files with "test" in the name under the release dirs, incl. `TetraIF/unit-test/*.cpp`) |
| `qt6-release-build-pipeline_*` | the in-tree pipeline files (`new_docker_build.sh`, `Dockerfile`, `rpmbuild/`, `jenkins-ci-rme/`) under `/usr/src/pipeline/` |
| `qt6-release-build-pipeline_*` | the in-tree pipeline files (`new_docker_build.sh`, `Dockerfile`, `CMakeLists.txt`, `rpmbuild/`, `jenkins-ci-rme/`) under `/usr/src/pipeline/` |
Verify a package:
@@ -207,6 +228,45 @@ jenkins-ci-rme/release-16-10-2026.sh
See `jenkins-ci-rme/README.md` for the pipeline details.
## Step 6 — Code coverage (lcov)
```bash
export WORKSPACE=/path/to/pipeline-root # e.g. ~/release/qt6-migration-pipeline
export PROJECT=guez
export OS_VERSION=26.04
./new_docker_build.sh --docker-image legatus-qt6:1.0 \
--run-coverage \
--coverage-output-dir "${WORKSPACE}/coverage/${PROJECT}/${OS_VERSION}/" \
> /path/to/coverage.log 2>&1
```
(export the variables *before* the command — command-prefix variables are
not expanded in the same command's arguments.)
The driver builds the release scope with `-O0 --coverage`, runs the same ctest
suite, then captures the data with lcov: the report covers the release scope
(`TetraIF`, `Z/src`, `Lts/Common`, `Lts/Proxies/TrainingAreaBase`), 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) and archives the report as build artifacts under
`coverage/<project>/<os>/`; 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.sh --help` prints the full option list. The main
@@ -214,16 +274,19 @@ ones:
| Option | Default | Purpose |
|---|---|---|
| `--docker-image IMAGE` | `legatus-qt6-prebuilt:latest` | image to use/build/delete |
| `--docker-image IMAGE` | `legatus-qt6:1.0` | image to use/build/delete |
| `--build-prebuilt-image` | — | build the image from `./Dockerfile` and exit |
| `--delete-prebuilt-image` | — | delete the image and exit |
| `--run-jenkins-builder` | off | produce the DEB packages (Step 4) |
| `--package-output-dir DIR` | `./packages-out` | where the DEBs are written |
| `--lts-version / --project / --build-number / --build-tag` | `1.0` / `guez` / `1` / `manual-build` | package metadata |
| `--run-coverage` | off | coverage build + lcov report (Step 6) |
| `--coverage-output-dir DIR` | `./coverage-out` | where the coverage report is written |
Environment overrides: `DOCKER_IMAGE`, `RUN_JENKINS_BUILDER`,
`PACKAGE_OUTPUT_DIR`, `PROJECT`, `LTS_VERSION`, `GUEZ_MODE`,
`BUILD_NUMBER`, `BUILD_TAG`, `MIGRATE_PIPELINE_ROOT`.
`PACKAGE_OUTPUT_DIR`, `RUN_COVERAGE`, `COVERAGE_OUTPUT_DIR`, `PROJECT`,
`LTS_VERSION`, `GUEZ_MODE`, `BUILD_NUMBER`, `BUILD_TAG`,
`MIGRATE_PIPELINE_ROOT`.
## Troubleshooting
@@ -14,6 +14,8 @@ NGL_TARGET_LINK_LIBRARIES(LogViewLogger
NGLLogger
)
SET_TARGET_PROPERTIES(LogViewLogger PROPERTIES POSITION_INDEPENDENT_CODE ON)
SET(my_SRCS
IntegerCalculator.cpp
IntegerCalculator.hpp
@@ -15,4 +15,26 @@
<file>image/ShowSend.png</file>
<file>image/Wls.png</file>
</qresource>
<qresource prefix="/icons/16x16">
<file alias="configure.png">../../Z/src/nglwidgets/icons/16x16/configure.png</file>
<file alias="dialog-ok-apply.png">../../Z/src/nglwidgets/icons/16x16/dialog-ok-apply.png</file>
<file alias="document-edit.png">../../Z/src/nglwidgets/icons/16x16/document-edit.png</file>
<file alias="document-import.png">../../Z/src/nglwidgets/icons/16x16/document-import.png</file>
<file alias="document-new.png">../../Z/src/nglwidgets/icons/16x16/document-new.png</file>
<file alias="document-open-data.png">../../Z/src/nglwidgets/icons/16x16/document-open-data.png</file>
<file alias="document-save.png">../../Z/src/nglwidgets/icons/16x16/document-save.png</file>
<file alias="edit-copy.png">../../Z/src/nglwidgets/icons/16x16/edit-copy.png</file>
<file alias="edit-delete.png">../../Z/src/nglwidgets/icons/16x16/edit-delete.png</file>
<file alias="edit-paste.png">../../Z/src/nglwidgets/icons/16x16/edit-paste.png</file>
<file alias="edit-redo.png">../../Z/src/nglwidgets/icons/16x16/edit-redo.png</file>
<file alias="go-down.png">../../Z/src/nglwidgets/icons/16x16/go-down.png</file>
<file alias="go-up.png">../../Z/src/nglwidgets/icons/16x16/go-up.png</file>
<file alias="list-add.png">../../Z/src/nglwidgets/icons/16x16/list-add.png</file>
<file alias="list-remove.png">../../Z/src/nglwidgets/icons/16x16/list-remove.png</file>
<file alias="mail-send.png">../../Z/src/nglwidgets/icons/16x16/mail-send.png</file>
<file alias="media-play-normal.png">../../Z/src/nglwidgets/icons/16x16/media-play-normal.png</file>
<file alias="media-playback-start.png">../../Z/src/nglwidgets/icons/16x16/media-playback-start.png</file>
<file alias="media-playback-stop.png">../../Z/src/nglwidgets/icons/16x16/media-playback-stop.png</file>
<file alias="rde_16x16.png">../../Z/src/nglwidgets/icons/16x16/rde_16x16.png</file>
</qresource>
</RCC>
@@ -83,11 +83,13 @@ NGL_WRAP_UI(nglwidgets_SRCS
)
# Collect big resource QRCs
set(oxygen_SRCS nglresources.qrc)
set(oxygen_SRCS)
if(TARGET Qt6::Core)
# Use Qt6's CMake helper to generate resource sources so resources are available at runtime
qt_add_resources(RME_LIGHT_RCC rme_light_style.qrc)
list(APPEND oxygen_SRCS ${RME_LIGHT_RCC})
# Use Qt6's CMake helper to generate resource sources so resources are available at runtime.
# Both qrcs MUST go through qt_add_resources: a raw .qrc left in the source list is not
# compiled (CMAKE_AUTORCC is off), so its resources would be missing at runtime
# (e.g. :icons/16x16/* toolbar/window icons used by LogView).
qt_add_resources(oxygen_SRCS nglresources.qrc rme_light_style.qrc)
else()
NGL_ADD_BIG_RESOURCES(oxygen_SRCS nglresources.qrc rme_light_style.qrc)
endif()
@@ -38,11 +38,20 @@ if(POLICY CMP0177)
cmake_policy(SET CMP0177 OLD)
endif()
# Compatibility stubs for Qt5 CMake macros when Qt6 is used.
# These stubs allow configure to succeed; actual resource/ui generation should be addressed during source migration.
# Compatibility stubs for Qt5 CMake macros when Qt6 is used (UI/CPP wrapping
# still no-op; resource handling is implemented below).
# QT5_ADD_RESOURCES maps onto Qt6's qt6_add_resources() in the outfiles-variable
# form: the generated qrc_<name>.cpp sources are appended to the given source
# list, so .qrc files are compiled into the targets that reference them
# (e.g. TetraIF/LogView). Without this the resources are silently dropped and
# ":/..." icons render empty at runtime.
if(NOT COMMAND QT5_ADD_RESOURCES)
macro(QT5_ADD_RESOURCES _out)
set(${_out} "" PARENT_SCOPE)
if(TARGET Qt6::Core)
qt6_add_resources(${_out} ${ARGN})
else()
message(WARNING "QT5_ADD_RESOURCES stub: Qt6::Core not found, skipping resources: ${ARGN}")
endif()
endmacro()
endif()
if(NOT COMMAND QT5_ADD_BIG_RESOURCES)
+19 -125
View File
@@ -1,140 +1,34 @@
// Release pipeline for the Qt6-migrated legatus validation-scope branch
// (story/release-validation-scope): TetraIF, Z, Lts/Common (+
// Lts/Proxies/TrainingAreaBase) -> 5 release DEB packages.
// Entry point of the release pipeline for the Qt6-migrated legatus
// validation-scope branch (story/release-validation-scope).
//
// Workspace layout (checked out by Jenkins, outer pipeline repo):
// <WORKSPACE>/
// external/
// qt-migration-legatus/qt6-after/qt6-migrated-legatus/ <- LEGATUS_ROOT
// Dockerfile (prebuilt build image recipe)
// new_docker_build.sh (local build driver)
// rpmbuild/make_rpm_ubuntu26.py (in-tree packaging)
// jenkins-ci-rme/ (this pipeline)
//
// The build container image is the prebuilt image built from the in-tree
// Dockerfile; it is built on the agent when not present (RebuildImage
// forces a fresh build).
def project = 'guez'
def legatusRoot = 'qt-migration-legatus/qt6-after/qt6-migrated-legatus'
def imageName = 'legatus-qt6-prebuilt:latest'
// Lives in jenkins-ci-rme/ of the DLBO Qt6 repo. Declares the job properties,
// allocates the build node, checks out the repo with its submodules and
// loads the build body from jenkins-ci-rme/jenkins/Jenkinsfile.
properties([
disableConcurrentBuilds(),
parameters([
string(name: 'OsVersions', defaultValue: '26.04', description: 'Comma-separated Ubuntu base versions, all built in parallel'),
choice(name: 'ProjectName', choices: ['guez'], description: 'LTS project flavor (passed to make_rpm_ubuntu26.py --project_name)'),
string(name: 'OsVersions', defaultValue: '26.04', description: 'Comma-separated Ubuntu base versions, built sequentially'),
string(name: 'LtsVersion', defaultValue: '1.0', description: 'LTS version (major.minor) passed to make_rpm_ubuntu26.py --version'),
booleanParam(name: 'ClearWorkspace', defaultValue: false, description: 'Clear entire workspace on all nodes used for build'),
booleanParam(name: 'ClearWorkspace', defaultValue: false, description: 'Clear entire workspace used for build'),
booleanParam(name: 'PublishArtifactRepo', defaultValue: true, description: 'Upload produced DEBs to the internal artifact repository'),
booleanParam(name: 'RebuildImage', defaultValue: false, description: 'Rebuild the prebuilt build image from the in-tree Dockerfile (default: reuse when present)')
booleanParam(name: 'RunCoverage', defaultValue: true, description: 'Build the release scope with -O0 --coverage, run ctest, collect the lcov report and archive it')
])
])
env.GIT_TERMINAL_PROMPT = '0'
env.LTS_VERSION = "${params.LtsVersion}"
env.ARTIFACTREPO = 'https://internal-repo.sl.defence-elec.de'
// OS versions this build covers; every build is isolated under
// rpms/${project}/${osVersion} so concurrent OS builds never collide.
def osVersions = params.OsVersions.split(',').collect { it.trim() }.findAll { it }
def builds = [:]
osVersions.each { osVersion ->
def rpmsDir = "rpms/${project}/${osVersion}"
builds["${project} (${osVersion})"] = {
stage("Prepare ${project} (${osVersion})") {
sh "rm -rf ${rpmsDir}"
sh "mkdir -p ${rpmsDir}"
}
stage("Prepare build image ${project} (${osVersion})") {
if (params.RebuildImage) {
sh "docker rmi ${imageName} || true"
}
// The in-tree driver owns the Dockerfile build args (APT_PACKAGES,
// QT_VERSION, ...) - single source of truth.
sh """
if docker image inspect ${imageName} >/dev/null 2>&1; then
echo "Reusing existing prebuilt image ${imageName}"
else
echo "Building prebuilt image ${imageName} from the in-tree Dockerfile..."
cd ${legatusRoot} && bash ./new_docker_build.sh --build-prebuilt-image --docker-image ${imageName}
fi
"""
}
stage("Build DEB ${project} (${osVersion})") {
def buildContainer = docker.image("${imageName}")
def guezMode = (project == 'guez') ? 'ON' : 'OFF'
def dockerOpts = "--init --shm-size=2g" +
" -v ${WORKSPACE}:/workspace" +
" -e WORKSPACE=/workspace" +
" -e PROJECT_BASE_DIR=/workspace" +
" -e PROJECT=${project}" +
" -e OS_VERSION=${osVersion}" +
" -e LTS_VERSION=${LTS_VERSION}" +
" -e GUEZ_MODE=${guezMode}" +
" -e BUILD_NUMBER=${env.BUILD_NUMBER}" +
" -e BUILD_TAG=${env.BUILD_TAG}"
buildContainer.inside(dockerOpts) {
sh "bash /workspace/${legatusRoot}/jenkins-ci-rme/jenkins_builder_ubuntu26.sh"
}
}
stage("Publish ${project} (${osVersion})") {
if (params.PublishArtifactRepo) {
withCredentials([usernamePassword(credentialsId: 'internal-repo-uploader',
usernameVariable: 'CURL_USER',
passwordVariable: 'CURL_PASS')]) {
sh """
export CURL_CRED="\${CURL_USER}:\${CURL_PASS}"
export PROJECT='${project}'
export OS_VERSION='${osVersion}'
export LTS_VERSION='${LTS_VERSION}'
export BUILD_NUMBER='${env.BUILD_NUMBER}'
export ARTIFACTREPO='${env.ARTIFACTREPO}'
export ARTIFACTFOLDER='${project}'
bash ${legatusRoot}/jenkins-ci-rme/jenkins_publisher_ubuntu26.sh
"""
}
def tdsUrl = readFile("url-${project}-${osVersion}.txt").trim()
def tdsVersion = readFile("tdsversion-${project}-${osVersion}.txt").trim()
def link = """<a href="${tdsUrl}" target="_blank">${project} ${tdsVersion} (OS ${osVersion})</a>"""
currentBuild.description = currentBuild.description ? "${currentBuild.description}<br/>${link}" : link
} else {
echo "Artifact-repo publish skipped for ${project} (OS ${osVersion}, PublishArtifactRepo=false)"
}
}
}
}
try {
stage("Initialization") {
node('jenkins-linux-node-2.sl.defence-elec.de') {
stage('Init submodule') {
if (params.ClearWorkspace) {
cleanWs()
checkout([
$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]],
userRemoteConfigs: scm.userRemoteConfigs
])
}
echo "Legatus Qt6 release build initialized — branch '${env.BRANCH_NAME}', project: ${project}, LTS ${env.LTS_VERSION}, OS version(s): ${osVersions.join(', ')}"
checkout([
$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'SubmoduleOption', disableSubmodules: false, parentCredentials: true, recursiveSubmodules: true, reference: '', trackingSubmodules: false]],
userRemoteConfigs: scm.userRemoteConfigs
])
}
parallel builds
stage("Finalization") {
echo "Legatus Qt6 release build completed — project: ${project} (LTS ${env.LTS_VERSION}), OS version(s): ${osVersions.join(', ')}"
}
currentBuild.result = 'SUCCESS'
} catch (e) {
currentBuild.result = 'FAILURE'
throw e
load 'jenkins-ci-rme/jenkins/Jenkinsfile'
}
@@ -5,7 +5,8 @@ only on files inside this source tree:
| File | Purpose |
|---|---|
| `Jenkinsfile` | Jenkins pipeline: prepare the prebuilt image (in-tree `Dockerfile`), run the builder inside the container, publish the DEBs to the artifact repo |
| `Jenkinsfile` | Jenkins entry point (job script path `jenkins-ci-rme/Jenkinsfile`): job properties/parameters, build node, checkout with submodules, then `load`s `jenkins-ci-rme/jenkins/Jenkinsfile` |
| `jenkins/Jenkinsfile` | Build body (per OS version, sequentially): install the prebuilt image from `legatus-qt6_1.0.tar.gz` when missing, run the builder inside the container, coverage, publish the DEBs to the artifact repo |
| `jenkins_builder_ubuntu26.sh` | Runs **inside** the build container: stages the workspace, runs the in-tree `rpmbuild/make_rpm_ubuntu26.py`, copies the DEBs to the packages-out mount |
| `jenkins_publisher_ubuntu26.sh` | Runs on the Jenkins agent: uploads the DEBs from `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` to the internal artifact repository |
| `release-16-10-2026.sh` | Local driver: the same flow without Jenkins, through the in-tree `new_docker_build.sh` |
@@ -24,9 +25,9 @@ only on files inside this source tree:
- Packaging uses the **in-tree** `rpmbuild/make_rpm_ubuntu26.py`
(was `${WORKSPACE}/rpmbuild` from the outer repo)
- The prebuilt build image is built from the **in-tree** `Dockerfile` via
`new_docker_build.sh --build-prebuilt-image` (was a pre-pulled harbor
image) — build args stay in `new_docker_build.sh` (single source of truth)
- The prebuilt build image `legatus-qt6:1.0` ships in the repo as
`legatus-qt6_1.0.tar.gz` (repo root); Jenkins `docker load`s it only when
the image is not installed on the agent yet, and never builds it
- `MIGRATE_PIPELINE_ROOT` is no longer needed: `new_docker_build.sh`
derives it from its own location
- DEB output path: `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` (Jenkins
@@ -40,15 +41,14 @@ only on files inside this source tree:
## Local run
```bash
cd qt6-migrated-legatus
cd "DLBO Qt6"
bash ./jenkins-ci-rme/release-16-10-2026.sh
# DEBs: <pipeline-root>/rpms/guez/26.04/
# DEBs: <repo-root>/rpms/guez/26.04/
```
## Jenkins setup
The job SCM must be the outer pipeline repository (the Jenkinsfile lives in
the `qt-migration-legatus` submodule; point the job's script path at
`qt-migration-legatus/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/Jenkinsfile`).
The job SCM is the DLBO Qt6 repository; the script path is
`jenkins-ci-rme/Jenkinsfile`, which loads `jenkins-ci-rme/jenkins/Jenkinsfile`.
Required Jenkins credential: `internal-repo-uploader` (username/password for
the artifact repository).
@@ -0,0 +1,135 @@
// Build body of the release pipeline for the Qt6-migrated legatus
// validation-scope branch (story/release-validation-scope): TetraIF, Z,
// Lts/Common (+ Lts/Proxies/TrainingAreaBase) -> 5 release DEB packages.
//
// Loaded by jenkins-ci-rme/Jenkinsfile inside the allocated node after the
// checkout; job properties/parameters live there.
//
// Workspace layout (checked out by Jenkins, DLBO Qt6 repo):
// <WORKSPACE>/
// jenkins-ci-rme/Jenkinsfile (entry point)
// new_docker_build.sh (local build driver)
// rpmbuild/make_rpm_ubuntu26.py (in-tree packaging)
// jenkins-ci-rme/ (this pipeline)
//
// The build container image is the prebuilt image shipped in the repo as
// legatus-qt6_1.0.tar.gz; it is loaded onto the agent when not installed
// yet, never built here.
def project = params.ProjectName
def imageName = 'legatus-qt6:1.0'
def imageArchive = 'legatus-qt6_1.0.tar.gz'
env.GIT_TERMINAL_PROMPT = '0'
env.LTS_VERSION = "${params.LtsVersion}"
env.ARTIFACTREPO = 'https://internal-repo.sl.defence-elec.de'
// OS versions this build covers, built one after another (the builder
// stages the workspace into a shared deb_stage directory); output is
// still isolated under rpms/${project}/${osVersion}.
def osVersions = params.OsVersions.split(',').collect { it.trim() }.findAll { it }
def buildOsVersion = { String osVersion ->
def rpmsDir = "rpms/${project}/${osVersion}"
stage("Prepare ${project} (${osVersion})") {
sh "rm -rf ${rpmsDir}"
sh "mkdir -p ${rpmsDir}"
}
stage("Build DEB ${project} (${osVersion})") {
def buildContainer = docker.image("${imageName}")
def guezMode = (project == 'guez') ? 'ON' : 'OFF'
def dockerOpts = "--init --shm-size=2g" +
" -v ${WORKSPACE}:/workspace" +
" -e WORKSPACE=/workspace" +
" -e PROJECT_BASE_DIR=/workspace" +
" -e PROJECT=${project}" +
" -e OS_VERSION=${osVersion}" +
" -e LTS_VERSION=${LTS_VERSION}" +
" -e GUEZ_MODE=${guezMode}" +
" -e BUILD_NUMBER=${env.BUILD_NUMBER}" +
" -e BUILD_TAG=${env.BUILD_TAG}"
buildContainer.inside(dockerOpts) {
sh "bash /workspace/jenkins-ci-rme/jenkins_builder_ubuntu26.sh"
}
}
stage("Coverage ${project} (${osVersion})") {
if (!params.RunCoverage) {
echo "Coverage skipped for ${project} (OS ${osVersion}, RunCoverage=false)"
return
}
// The driver (run on the agent, same pattern as the image-build
// stage) builds the scope with -O0 --coverage, runs ctest and
// collects the lcov report into the workspace mount.
sh "bash ./new_docker_build.sh --docker-image ${imageName} --run-coverage --coverage-output-dir ${WORKSPACE}/coverage/${project}/${osVersion}"
archiveArtifacts artifacts: "coverage/${project}/${osVersion}/**", allowEmptyArchive: true
}
stage("Publish ${project} (${osVersion})") {
if (params.PublishArtifactRepo) {
withCredentials([usernamePassword(credentialsId: 'internal-repo-uploader',
usernameVariable: 'CURL_USER',
passwordVariable: 'CURL_PASS')]) {
sh """
export CURL_CRED="\${CURL_USER}:\${CURL_PASS}"
export PROJECT='${project}'
export OS_VERSION='${osVersion}'
export LTS_VERSION='${LTS_VERSION}'
export BUILD_NUMBER='${env.BUILD_NUMBER}'
export ARTIFACTREPO='${env.ARTIFACTREPO}'
export ARTIFACTFOLDER='${project}'
bash jenkins-ci-rme/jenkins_publisher_ubuntu26.sh
"""
}
def tdsUrl = readFile("url-${project}-${osVersion}.txt").trim()
def tdsVersion = readFile("tdsversion-${project}-${osVersion}.txt").trim()
def link = """<a href="${tdsUrl}" target="_blank">${project} ${tdsVersion} (OS ${osVersion})</a>"""
currentBuild.description = currentBuild.description ? "${currentBuild.description}<br/>${link}" : link
} else {
echo "Artifact-repo publish skipped for ${project} (OS ${osVersion}, PublishArtifactRepo=false)"
}
}
}
try {
stage("Initialization") {
echo "Legatus Qt6 release build initialized — branch '${env.BRANCH_NAME}', project: ${project}, LTS ${env.LTS_VERSION}, OS version(s): ${osVersions.join(', ')}"
}
stage("Install build image") {
// Reuse the prebuilt image when it is already installed on the agent;
// otherwise load it from the archive shipped in the repo.
def imageInstalled = sh(script: "docker image inspect '${imageName}' >/dev/null 2>&1", returnStatus: true) == 0
if (imageInstalled) {
echo "Build image ${imageName} is already installed on the agent - reusing it"
} else {
if (!fileExists(imageArchive)) {
error "Build image ${imageName} not installed and image archive ${imageArchive} not found in the workspace"
}
echo "Build image ${imageName} not installed on the agent - loading it from ${imageArchive}"
sh "docker load -i '${imageArchive}'"
if (sh(script: "docker image inspect '${imageName}' >/dev/null 2>&1", returnStatus: true) != 0) {
error "Build image ${imageName} still not available after loading ${imageArchive}"
}
echo "Build image ${imageName} installed on the agent"
}
}
for (osVersion in osVersions) {
buildOsVersion(osVersion)
}
stage("Finalization") {
echo "Legatus Qt6 release build completed — project: ${project} (LTS ${env.LTS_VERSION}), OS version(s): ${osVersions.join(', ')}"
}
currentBuild.result = 'SUCCESS'
} catch (e) {
currentBuild.result = 'FAILURE'
throw e
}
+4 -3
View File
@@ -7,7 +7,7 @@
# Runs inside the prebuilt build container (built from the in-tree
# Dockerfile) with the pipeline workspace mounted at /workspace.
# Packaging is done by the IN-TREE rpmbuild copy
# (qt-migration-legatus/qt6-after/qt6-migrated-legatus/rpmbuild/), so the
# (rpmbuild/ at the DLBO Qt6 repo root), so the
# release flow needs no files outside the source tree.
#
# Required environment (set by the Jenkinsfile or `docker run -e ...`):
@@ -41,13 +41,14 @@ rm -rf "${STAGE_DIR}"
mkdir -p "${STAGE_DIR}"
tar --exclude='./rpms' --exclude='./.git' --exclude='./build' \
--exclude='./deb_build_tmp' --exclude='./deb_stage' --exclude='./packages-out' \
--exclude='./legatus-qt6_1.0.tar.gz' \
-cf - -C "${WORKSPACE}" . | tar -xf - -C "${STAGE_DIR}"
export VERSION_DATE
VERSION_DATE=$(date +%Y-%m-%d)
# Real CMake project root inside the staged tree (the in-tree source)
SOURCE_DIR="${STAGE_DIR}/qt-migration-legatus/qt6-after/qt6-migrated-legatus"
# CMake project root inside the staged tree (the DLBO Qt6 repo root)
SOURCE_DIR="${STAGE_DIR}"
if [ ! -f "${SOURCE_DIR}/CMakeLists.txt" ] || [ ! -f "${SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26.py" ]; then
echo "ERROR: staged source incomplete under ${SOURCE_DIR} (CMakeLists.txt or rpmbuild/make_rpm_ubuntu26.py missing)" >&2
exit 1
File mode changed.
+16 -2
View File
@@ -8,6 +8,8 @@
# image is not present yet
# - builds the release scope, runs ctest and produces the release DEB
# packages with the in-tree rpmbuild script
# - collects the lcov code-coverage report (--run-coverage; set
# DRYRUN_COVERAGE=OFF to skip)
#
# The DEB packages land in ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/
# (Jenkins-style layout; locally WORKSPACE is the pipeline root).
@@ -16,7 +18,7 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LEGATUS_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
PIPELINE_ROOT="$(cd "${LEGATUS_ROOT}/../../.." && pwd)"
PIPELINE_ROOT="${LEGATUS_ROOT}"
# Release build configuration (Jenkins-style variables)
export WORKSPACE="${PIPELINE_ROOT}"
@@ -27,7 +29,7 @@ export GUEZ_MODE="${GUEZ_MODE:-ON}"
export BUILD_NUMBER="${BUILD_NUMBER:-$(date +%Y%m%d-%H%M%S)}"
export BUILD_TAG="${BUILD_TAG:-release-qt6-first}"
DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6-prebuilt:latest}"
DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6:1.0}"
log_info() {
printf 'INFO: %s\n' "$*"
@@ -60,4 +62,16 @@ bash ./new_docker_build.sh \
--build-number "${BUILD_NUMBER}" \
--build-tag "${BUILD_TAG}"
# Code coverage (lcov) - mirrors the Jenkins Coverage stage. Set
# DRYRUN_COVERAGE=OFF for a fast local DEB-only run.
DRYRUN_COVERAGE="${DRYRUN_COVERAGE:-ON}"
if [[ "${DRYRUN_COVERAGE}" == "ON" ]]; then
bash ./new_docker_build.sh \
--docker-image "${DOCKER_IMAGE}" \
--run-coverage \
--coverage-output-dir "${WORKSPACE}/coverage/${PROJECT}/${OS_VERSION}"
else
log_info "Coverage skipped (DRYRUN_COVERAGE=OFF)"
fi
log_info "=== Release Pipeline Complete ==="
+99 -30
View File
@@ -9,7 +9,7 @@ set -euo pipefail
# optionally runs the Jenkins builder to produce the release DEB packages.
#
# - Resolves MIGRATE_PIPELINE_ROOT (exported variable, .envrc, or derived
# from the script location) for the workspace and external mounts
# from the script location = repo root) for the workspace mount
# - Uses a prebuilt Docker image with all build dependencies installed
# (build it from ./Dockerfile via --build-prebuilt-image)
# - Optional deletion of the prebuilt Docker image via --delete-prebuilt-image
@@ -28,7 +28,7 @@ Builds the release validation scope inside the prebuilt Docker image:
Options:
--docker-image IMAGE Docker image name to use/build/delete
(default: legatus-qt6-prebuilt:latest)
(default: legatus-qt6:1.0)
--build-prebuilt-image Build the prebuilt Docker image (from ./Dockerfile)
and exit. To run the build with it, run the script
again with --docker-image
@@ -43,6 +43,13 @@ Package production options (RPM/DEB):
--build-number NUM Build number for package (default: 1)
--build-tag TAG Build tag for package (default: manual-build)
Coverage options (lcov):
--run-coverage Build the release scope with -O0 --coverage, run ctest
and collect an lcov coverage report (mutually
exclusive with --run-jenkins-builder)
--coverage-output-dir DIR Directory to mount for coverage output
(default: ./coverage-out)
Environment variable overrides:
BUILD_PREBUILT_IMAGE=ON|OFF
DELETE_PREBUILT_IMAGE=ON|OFF
@@ -54,11 +61,13 @@ Environment variable overrides:
GUEZ_MODE=ON|OFF
BUILD_NUMBER=<num>
BUILD_TAG=<tag>
RUN_COVERAGE=ON|OFF
COVERAGE_OUTPUT_DIR=<dir>
MIGRATE_PIPELINE_ROOT resolution (highest precedence first):
1. exported MIGRATE_PIPELINE_ROOT (e.g. from a Jenkinsfile)
2. MIGRATE_PIPELINE_ROOT set by .envrc in this directory
3. derived from the script location (three levels up)
3. derived from the script location (the DLBO Qt6 repo root)
Examples:
./new_docker_build.sh --build-prebuilt-image --docker-image legatus-qt6:1.0
@@ -67,6 +76,9 @@ Examples:
./new_docker_build.sh --docker-image legatus-qt6:1.0 \
--run-jenkins-builder \
--package-output-dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/"
./new_docker_build.sh --docker-image legatus-qt6:1.0 \
--run-coverage \
--coverage-output-dir "${WORKSPACE}/coverage/${PROJECT}/${OS_VERSION}/"
EOF
}
@@ -184,6 +196,8 @@ APT_PACKAGES=(
postgresql-server-dev-all
git
python3-pip
# Code coverage (genhtml ships in the same package)
lcov
# Packaging tools for RPM/DEB build
rpm
debhelper
@@ -262,20 +276,12 @@ build_prebuilt_image() {
require_command docker
# MIGRATE_PIPELINE_ROOT resolution (highest precedence first):
# 1. exported environment variable (e.g. from a Jenkinsfile)
# 2. .envrc in this directory (if present)
# 3. derived from this script's location - the script always lives at
# <root>/qt-migration-legatus/qt6-after/qt6-migrated-legatus, so the
# pipeline root is three levels up. This makes the script work in a
# fresh Jenkins checkout with no environment setup at all.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MIGRATE_PIPELINE_ROOT_DEFAULT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
MIGRATE_PIPELINE_ROOT_DEFAULT="${SCRIPT_DIR}"
PIPELINE_ROOT_EXPORTED="${MIGRATE_PIPELINE_ROOT:-}"
if [[ -f ".envrc" ]]; then
set -a
# shellcheck disable=SC1091
source ".envrc"
set +a
fi
@@ -295,6 +301,9 @@ DELETE_PREBUILT_IMAGE="${DELETE_PREBUILT_IMAGE:-OFF}"
# Jenkins builder options for RPM/DEB package production
RUN_JENKINS_BUILDER="${RUN_JENKINS_BUILDER:-OFF}"
PACKAGE_OUTPUT_DIR="${PACKAGE_OUTPUT_DIR:-./packages-out}"
# Code coverage (lcov)
RUN_COVERAGE="${RUN_COVERAGE:-OFF}"
COVERAGE_OUTPUT_DIR="${COVERAGE_OUTPUT_DIR:-./coverage-out}"
LTS_VERSION="${LTS_VERSION:-1.0}"
PROJECT="${PROJECT:-guez}"
GUEZ_MODE="${GUEZ_MODE:-ON}"
@@ -327,6 +336,14 @@ while [[ $# -gt 0 ]]; do
[[ $# -gt 0 ]] || die "--package-output-dir requires a directory path"
PACKAGE_OUTPUT_DIR="$1"
;;
--run-coverage)
RUN_COVERAGE=ON
;;
--coverage-output-dir)
shift
[[ $# -gt 0 ]] || die "--coverage-output-dir requires a directory path"
COVERAGE_OUTPUT_DIR="$1"
;;
--lts-version)
shift
[[ $# -gt 0 ]] || die "--lts-version requires a version string"
@@ -362,12 +379,17 @@ done
BUILD_PREBUILT_IMAGE="$(normalize_on_off "$BUILD_PREBUILT_IMAGE" "BUILD_PREBUILT_IMAGE")"
DELETE_PREBUILT_IMAGE="$(normalize_on_off "$DELETE_PREBUILT_IMAGE" "DELETE_PREBUILT_IMAGE")"
RUN_JENKINS_BUILDER="$(normalize_on_off "$RUN_JENKINS_BUILDER" "RUN_JENKINS_BUILDER")"
RUN_COVERAGE="$(normalize_on_off "$RUN_COVERAGE" "RUN_COVERAGE")"
if [[ "${RUN_COVERAGE}" == "ON" && "${RUN_JENKINS_BUILDER}" == "ON" ]]; then
die "--run-coverage is mutually exclusive with --run-jenkins-builder"
fi
# Default for the Docker image name
DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6-prebuilt:latest}"
DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6:1.0}"
# Export variables for Docker container
export RELEASE_BUILD RUN_CTEST BUILD_PREBUILT_IMAGE DELETE_PREBUILT_IMAGE DOCKER_IMAGE RUN_JENKINS_BUILDER PACKAGE_OUTPUT_DIR LTS_VERSION PROJECT GUEZ_MODE BUILD_NUMBER BUILD_TAG
export RELEASE_BUILD RUN_CTEST BUILD_PREBUILT_IMAGE DELETE_PREBUILT_IMAGE DOCKER_IMAGE RUN_JENKINS_BUILDER PACKAGE_OUTPUT_DIR RUN_COVERAGE COVERAGE_OUTPUT_DIR LTS_VERSION PROJECT GUEZ_MODE BUILD_NUMBER BUILD_TAG
require_non_empty "${DOCKER_IMAGE}" "DOCKER_IMAGE"
@@ -380,7 +402,7 @@ require_non_empty "${MIGRATE_PIPELINE_ROOT:-}" "MIGRATE_PIPELINE_ROOT"
require_directory "${MIGRATE_PIPELINE_ROOT}" "MIGRATE_PIPELINE_ROOT"
WORKSPACE_ROOT_HOST="${MIGRATE_PIPELINE_ROOT}"
PROJECT_DIR_HOST="${WORKSPACE_ROOT_HOST}/qt-migration-legatus/qt6-after/qt6-migrated-legatus"
PROJECT_DIR_HOST="${WORKSPACE_ROOT_HOST}"
require_directory "${PROJECT_DIR_HOST}" "Project directory"
@@ -391,6 +413,8 @@ log_info "DELETE_PREBUILT_IMAGE=${DELETE_PREBUILT_IMAGE}"
log_info "DOCKER_IMAGE=${DOCKER_IMAGE}"
log_info "RUN_JENKINS_BUILDER=${RUN_JENKINS_BUILDER}"
log_info "PACKAGE_OUTPUT_DIR=${PACKAGE_OUTPUT_DIR}"
log_info "RUN_COVERAGE=${RUN_COVERAGE}"
log_info "COVERAGE_OUTPUT_DIR=${COVERAGE_OUTPUT_DIR}"
log_info "LTS_VERSION=${LTS_VERSION}"
log_info "PROJECT=${PROJECT}"
log_info "GUEZ_MODE=${GUEZ_MODE}"
@@ -426,6 +450,7 @@ RELEASE_BUILD="${RELEASE_BUILD:-ON}"
RUN_CTEST="${RUN_CTEST:-ON}"
# Packaging variables
RUN_JENKINS_BUILDER="${RUN_JENKINS_BUILDER:-OFF}"
RUN_COVERAGE="${RUN_COVERAGE:-OFF}"
LTS_VERSION="${LTS_VERSION:-1.0}"
PROJECT="${PROJECT:-guez}"
GUEZ_MODE="${GUEZ_MODE:-ON}"
@@ -449,20 +474,28 @@ log_info "Using prebuilt Docker image: all build dependencies are baked in"
export QT_QPA_PLATFORM=offscreen
cd /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus
cd /workspace
rm -rf build4
mkdir -p build4
cd build4
# RELEASE_BUILD=ON selects the release scope (TetraIF, Z/src, Lts/Common +
# TrainingAreaBase); all other BUILD_* flags are left at their CMake defaults.
COV_CMAKE_ARGS=()
if [[ "${RUN_COVERAGE}" == "ON" ]]; then
COV_CMAKE_ARGS=(
"-DCMAKE_C_FLAGS_RELEASE=-O0 -g --coverage -DNDEBUG -fPIC"
"-DCMAKE_CXX_FLAGS_RELEASE=-O0 -g --coverage -DNDEBUG -fPIC"
"-DCMAKE_EXE_LINKER_FLAGS=--coverage"
"-DCMAKE_SHARED_LINKER_FLAGS=--coverage"
)
fi
cmake .. \
-DBUILD_TESTING=ON \
-DRELEASE_BUILD="${RELEASE_BUILD}" \
-DCMAKE_CXX_STANDARD=17 \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR}:/usr/local"
-DCMAKE_PREFIX_PATH="${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR}:/usr/local" \
"${COV_CMAKE_ARGS[@]}"
read -r -a RELEASE_TARGETS_ARRAY <<< "${RELEASE_BUILD_TARGETS}"
@@ -479,22 +512,61 @@ else
log_info "Skipping CTest"
fi
if [[ "${RUN_COVERAGE}" == "ON" ]]; then
log_info "=== Code coverage (lcov) ==="
COVOUT=/workspace/coverage-out
SRCROOT=/workspace
mkdir -p "${COVOUT}"
COV_IGNORE=(--ignore-errors mismatch,inconsistent,unused)
lcov --capture --directory . --external "${COV_IGNORE[@]}" \
--rc branch_coverage=1 \
--output-file "${COVOUT}/raw.info"
lcov --extract "${COVOUT}/raw.info" \
"${SRCROOT}/TetraIF/*" \
"${SRCROOT}/Z/src/*" \
"${SRCROOT}/Lts/Common/*" \
"${SRCROOT}/Lts/Proxies/TrainingAreaBase/*" \
"${COV_IGNORE[@]}" \
--rc branch_coverage=1 \
--output-file "${COVOUT}/scoped.info"
lcov --remove "${COVOUT}/scoped.info" \
"*/unit-test/*" \
"*CommonUnitTestsPlaceholder*" \
"*/UnitTests/*" \
"*/tests/*" \
"*/test_*" \
"*_test.cpp" \
"*_test.h" \
"*_unit_test*" \
"${COV_IGNORE[@]}" \
--rc branch_coverage=1 \
--output-file "${COVOUT}/coverage.info"
lcov --summary "${COVOUT}/coverage.info" "${COV_IGNORE[@]}" --rc branch_coverage=1 \
> "${COVOUT}/coverage_summary.txt"
genhtml "${COVOUT}/coverage.info" \
--output-directory "${COVOUT}/html" \
"${COV_IGNORE[@]}" \
--branch-coverage --legend \
--rc branch_coverage=1
log_info "Coverage report written to ${COVOUT} (host: ${COVERAGE_OUTPUT_DIR})"
cat "${COVOUT}/coverage_summary.txt"
fi
# DEB package production with the in-tree rpmbuild script
if [[ "${RUN_JENKINS_BUILDER}" == "ON" ]]; then
log_info "=== DEB Package Production (in-tree rpmbuild) ==="
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | cut -d'"' -f2)
STAGE_DIR=/workspace/deb_stage
STAGED_SOURCE_DIR="${STAGE_DIR}/qt-migration-legatus/qt6-after/qt6-migrated-legatus"
STAGED_SOURCE_DIR="${STAGE_DIR}"
# Stage the workspace as a clean copy. The workspace itself is NEVER
# deleted (it contains git-managed sources); only the staging
# subdirectory is removed.
log_info "Staging workspace to ${STAGE_DIR}"
rm -rf "${STAGE_DIR}"
mkdir -p "${STAGE_DIR}"
tar --exclude='./rpms' --exclude='./.git' --exclude='./build' \
--exclude='./deb_build_tmp' --exclude='./deb_stage' --exclude='./packages-out' \
--exclude='./legatus-qt6_1.0.tar.gz' \
-cf - -C /workspace . | tar -xf - -C "${STAGE_DIR}"
if [[ ! -f "${STAGED_SOURCE_DIR}/CMakeLists.txt" || ! -f "${STAGED_SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26.py" ]]; then
@@ -525,12 +597,7 @@ if [[ "${RUN_JENKINS_BUILDER}" == "ON" ]]; then
exit 1
fi
# Copy produced DEB packages to the packages-out mount (host:
# ${PACKAGE_OUTPUT_DIR}, container: /workspace/packages-out) so they are
# available on the host after the container exits.
# make_rpm already writes to /workspace/rpms/... (the host workspace
# mount), so when the host's PACKAGE_OUTPUT_DIR is that same directory
# the packages are already in place - skip copying onto themselves.
# Copy produced DEB packages to the packages-out
DEST_DIR=/workspace/packages-out
mkdir -p "${DEST_DIR}"
shopt -s nullglob
@@ -559,6 +626,8 @@ docker run --rm \
-e RELEASE_BUILD \
-e RUN_CTEST \
-e RUN_JENKINS_BUILDER \
-e RUN_COVERAGE \
-e COVERAGE_OUTPUT_DIR \
-e PACKAGE_OUTPUT_DIR \
-e LTS_VERSION \
-e PROJECT \
@@ -571,8 +640,8 @@ docker run --rm \
-e QT_BASE_DIR \
-e RELEASE_BUILD_TARGETS="${RELEASE_BUILD_TARGETS_STRING}" \
-v "${WORKSPACE_ROOT_HOST}:/workspace" \
-v "${MIGRATE_PIPELINE_ROOT}/external:/workspace/external:ro" \
-v "${CONTAINER_SCRIPT_HOST}:/tmp/run-build-inside-container.sh:ro" \
-v "${PACKAGE_OUTPUT_DIR}:/workspace/packages-out" \
-v "${COVERAGE_OUTPUT_DIR}:/workspace/coverage-out" \
"${DOCKER_IMAGE}" \
bash /tmp/run-build-inside-container.sh
+245 -642
View File
File diff suppressed because it is too large. Load diff