Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d130c55be5 | ||
|
|
0e2100f383 | ||
|
|
26f702b7a4 | ||
|
|
37bd700564 | ||
|
|
684e05109d | ||
|
|
676ae05335 |
No files matched your search
@@ -14,3 +14,4 @@ build/
|
||||
build2/
|
||||
.envrc
|
||||
build4
|
||||
coverage-out/
|
||||
@@ -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,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
@@ -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
|
||||
}
|
||||
Executable → Regular
+4
-3
@@ -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
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
+16
-2
@@ -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 ==="
|
||||
Executable → Regular
+98
-21
@@ -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,19 +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}"
|
||||
|
||||
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
|
||||
@@ -551,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 \
|
||||
@@ -563,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
|
||||
Executable → Regular
+1
@@ -24,6 +24,7 @@ PIPELINE_FILES = [
|
||||
"new_docker_build.sh",
|
||||
"Dockerfile",
|
||||
"jenkins-ci-rme/Jenkinsfile",
|
||||
"jenkins-ci-rme/jenkins/Jenkinsfile",
|
||||
"jenkins-ci-rme/jenkins_builder_ubuntu26.sh",
|
||||
"jenkins-ci-rme/jenkins_publisher_ubuntu26.sh",
|
||||
"jenkins-ci-rme/release-16-10-2026.sh",
|
||||
|
||||
Reference in new issue
Block a user