diff --git a/qt6-after/qt6-migrated-legatus/Dockerfile b/qt6-after/qt6-migrated-legatus/Dockerfile index ed5a264f2..d1cdce9e8 100644 --- a/qt6-after/qt6-migrated-legatus/Dockerfile +++ b/qt6-after/qt6-migrated-legatus/Dockerfile @@ -1,8 +1,9 @@ -# Prebuilt build image for the release validation-scope branch +# Prebuilt build image for the Release 2 branch # (Ubuntu 26.04 + Qt6 + all dependencies for the legatus release build). # -# Built by new_docker_build.sh --build-prebuilt-image, which passes the -# package list and Qt settings as build args (see build_prebuilt_image()). +# Build with (the APT package list mirrors the in-container install list of +# new_docker_build_release2.sh): +# docker build --build-arg APT_PACKAGES="" -t . FROM ubuntu:26.04 diff --git a/qt6-after/qt6-migrated-legatus/README.md b/qt6-after/qt6-migrated-legatus/README.md index 6ead50f45..6f662c52f 100644 --- a/qt6-after/qt6-migrated-legatus/README.md +++ b/qt6-after/qt6-migrated-legatus/README.md @@ -205,7 +205,7 @@ scope again (Release configuration, Ninja, scoped target list) and produces | `qt6-release-sources_1.0-1_amd64.deb` | Release 2 scope sources (source files + CMakeLists under the release dirs) | | `qt6-release-ctest-runtime_1.0-1_amd64.deb` | Test executables under `/usr/lib/ctest/` (currently empty — the producer looks for a `build4/bin/` dir, which the driver's timestamped `build4_/` dirs do not match) | | `qt6-release-ctest-sources_1.0-1_amd64.deb` | Test sources (files with "test" in the name under release dirs) | -| `qt6-release-build-pipeline_1.0-1_amd64.deb` | In-tree pipeline files (the producer's `PIPELINE_FILES`: `new_docker_build.sh`, `Dockerfile`, `jenkins-ci-rme/*`, `rpmbuild/make_rpm_ubuntu26.py`, `CMakeLists.txt`) under `/usr/src/pipeline/` | +| `qt6-release-build-pipeline_1.0-1_amd64.deb` | In-tree pipeline files (the producer's `PIPELINE_FILES`: `new_docker_build_release2.sh`, `Dockerfile`, `jenkins-ci-rme/*`, `rpmbuild/make_rpm_ubuntu26_release2.py`, `CMakeLists.txt`) under `/usr/src/pipeline/` | (Version string = `--lts-version` + `-` + `--build-number`, default `1.0-1`.) diff --git a/qt6-after/qt6-migrated-legatus/install_arcgis.sh b/qt6-after/qt6-migrated-legatus/install_arcgis.sh index 266d10deb..f42ec81d4 100755 --- a/qt6-after/qt6-migrated-legatus/install_arcgis.sh +++ b/qt6-after/qt6-migrated-legatus/install_arcgis.sh @@ -67,7 +67,7 @@ if [ -x "${CONFIGURE_SCRIPT}" ]; then # The -np flag skips postInstall.sh which integrates with Qt Creator # Remove -np if Qt Creator integration is needed. # - # configure.sh is mounted read-only (new_docker_build.sh mounts external:ro), + # configure.sh is mounted read-only (the build driver mounts external:ro), # so its `sed -i` on ideintegration/*.pri (Qt Creator IDE patching only) fails # with "Read-only file system" and exits 1. That step is NOT used by the CMake # build (which consumes ArcGISRuntime.cmake, not the .pri files), and the diff --git a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/Jenkinsfile b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/Jenkinsfile index 3c69428b6..f896a9e23 100644 --- a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/Jenkinsfile +++ b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/Jenkinsfile @@ -8,9 +8,9 @@ properties([ disableConcurrentBuilds(), parameters([ - choice(name: 'ProjectName', choices: ['guez'], description: 'LTS project flavor (passed to make_rpm_ubuntu26.py --project_name)'), + choice(name: 'ProjectName', choices: ['guez'], description: 'LTS project flavor (passed to make_rpm_ubuntu26_release2.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'), + string(name: 'LtsVersion', defaultValue: '1.0', description: 'LTS version (major.minor) passed to make_rpm_ubuntu26_release2.py --version'), 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: 'RunCoverage', defaultValue: true, description: 'Build the release scope with -O0 --coverage, run ctest, collect the lcov report and archive it') diff --git a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/README.md b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/README.md index 44e14ec68..b8dab9bb3 100644 --- a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/README.md +++ b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/README.md @@ -1,4 +1,4 @@ -# jenkins-ci-rme — release pipeline for the Qt6 validation-scope branch +# jenkins-ci-rme — release pipeline for the Qt6 Release 2 branch In-tree copy of the Jenkins CI flow, adapted so the release pipeline depends only on files inside this source tree: @@ -7,9 +7,9 @@ only on files inside this source tree: |---|---| | `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_builder_ubuntu26.sh` | Runs **inside** the build container: stages the workspace, runs the in-tree `rpmbuild/make_rpm_ubuntu26_release2.py` with the Release 2 target list, 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` | +| `release-16-10-2026.sh` | Local driver: the same flow without Jenkins, through the in-tree `new_docker_build_release2.sh` | ## Not included (superseded) @@ -23,27 +23,29 @@ only on files inside this source tree: ## Adaptations vs. the outer-repo copy -- Packaging uses the **in-tree** `rpmbuild/make_rpm_ubuntu26.py` +- Packaging uses the **in-tree** `rpmbuild/make_rpm_ubuntu26_release2.py` (was `${WORKSPACE}/rpmbuild` from the outer repo) - 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 +- `MIGRATE_PIPELINE_ROOT` is exported by the local dry run (derived from the + tree location); `new_docker_build_release2.sh` falls back to its own + location when it is not set - DEB output path: `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` (Jenkins convention); the packages-out copy is skipped when that directory is the - make_rpm output dir (same device:inode guard as in `new_docker_build.sh`) + make_rpm output dir (same device:inode guard as in + `new_docker_build_release2.sh`) - Publisher uploads `${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/` directly — - `make_rpm_ubuntu26.py` writes the DEBs there without a TDS subfolder + `make_rpm_ubuntu26_release2.py` writes the DEBs there without a TDS subfolder - The post-publish Cleanup stage was dropped: the DEBs are kept under `${WORKSPACE}/rpms/...` (the documented output location) ## Local run ```bash -cd "DLBO Qt6" +cd /qt-migration-legatus/qt6-after/qt6-migrated-legatus bash ./jenkins-ci-rme/release-16-10-2026.sh -# DEBs: /rpms/guez/26.04/ +# DEBs: /rpms/guez/26.04/ ``` ## Jenkins setup diff --git a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins/Jenkinsfile b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins/Jenkinsfile index fdf926219..b42484898 100644 --- a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins/Jenkinsfile +++ b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins/Jenkinsfile @@ -1,16 +1,16 @@ // 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. +// Release 2 branch: AP3, AP4, AP9, TetraIF, tests (46 targets) -> +// 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): // / -// 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) +// jenkins-ci-rme/Jenkinsfile (entry point) +// new_docker_build_release2.sh (local build driver) +// rpmbuild/make_rpm_ubuntu26_release2.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 @@ -65,7 +65,10 @@ def buildOsVersion = { String osVersion -> // 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}" + // MIGRATE_PIPELINE_ROOT must be exported: it points at the checkout + // root (the mounted pipeline root) and wins over the checked-in + // .envrc, which carries a host-specific path. + sh "export MIGRATE_PIPELINE_ROOT='${WORKSPACE}' && bash ./new_docker_build_release2.sh --use-prebuilt-image --docker-image ${imageName} --run-coverage --coverage-output-dir ${WORKSPACE}/coverage/${project}/${osVersion}" archiveArtifacts artifacts: "coverage/${project}/${osVersion}/**", allowEmptyArchive: true } diff --git a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_builder_ubuntu26.sh b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_builder_ubuntu26.sh index 5f83aa272..a26020ea6 100644 --- a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_builder_ubuntu26.sh +++ b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_builder_ubuntu26.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # # Build the LTS DEB packages for the Qt6-migrated legatus release -# (validation scope: TetraIF, Z, Lts/Common + Lts/Proxies/TrainingAreaBase) +# (Release 2 scope: AP3, AP4, AP9, TetraIF, tests - 46 targets) # for Ubuntu 26.04. # # Runs inside the prebuilt build container (built from the in-tree @@ -42,6 +42,7 @@ 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' \ + --exclude='./build4*' \ -cf - -C "${WORKSPACE}" . | tar -xf - -C "${STAGE_DIR}" export VERSION_DATE @@ -49,20 +50,26 @@ VERSION_DATE=$(date +%Y-%m-%d) # 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 +if [ ! -f "${SOURCE_DIR}/CMakeLists.txt" ] || [ ! -f "${SOURCE_DIR}/rpmbuild/make_rpm_ubuntu26_release2.py" ]; then + echo "ERROR: staged source incomplete under ${SOURCE_DIR} (CMakeLists.txt or rpmbuild/make_rpm_ubuntu26_release2.py missing)" >&2 exit 1 fi +# Release 2 scope targets - mirrors the GROUP*_TARGETS arrays in +# new_docker_build_release2.sh (keep in sync). A full-tree build is not +# possible on the Release 2 tree, so the scoped list must be passed. +RELEASE2_TARGETS=(ddscore ddsftccore ddsfts ddsgen ddsQoS ddsconnector NGLLogger nglapplication nglcompression nglcoreapplication ngldb nglguiapplication nglsettings nglsingleapplication nglsinglecoreapplication ngltools ngltranslator nglwidgets qtsingleapplication qtsinglecoreapplication wms_json_ds tcpserver LtsCoordinate LtsCoordTrans LtsSession LtsMultiMonitor DataPluginInterface GuiPluginInterface CoPrtCnv LogViewLogger LogView PrtCnvLib PrtCnv LtsLicence MockCoordTrans aes_crypt_test ngltools_qt_smoke lts_coord_trans_unit_test test_nglpdfwidget coprtcnv_unit_test logview_unit_test prtcnv_unit_test ddsview LogViewer sqlbrowser ngl_codegen) + # Output is isolated per OS version so parallel OS builds of the same # project never collide cd "${SOURCE_DIR}/rpmbuild" -python3 make_rpm_ubuntu26.py -c LTS \ +python3 make_rpm_ubuntu26_release2.py -c LTS \ --project_name "${PROJECT}" \ --version "${LTS_VERSION}" \ --output_dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" \ --source_dir "${SOURCE_DIR}" \ - --cmake_build_flags "-DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=${GUEZ_MODE} -DBUILD_WLS=ON -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/ -DRELEASE_BUILD=ON" \ + --cmake_build_flags "-DUSE_IPO=ON -DUSE_UNITY_BUILD=ON -DGUEZ_MODE=${GUEZ_MODE} -DBUILD_WLS=ON -DPostgreSQL_TYPE_INCLUDE_DIR=/usr/include/postgresql/ -DBUILD_RTI=ON -DRELEASE_BUILD=ON" \ + --build_targets "${RELEASE2_TARGETS[*]}" \ --build_number "${BUILD_NUMBER:-1}" \ --release_scope diff --git a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_publisher_ubuntu26.sh b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_publisher_ubuntu26.sh index 494948ed6..185a3f8b2 100644 --- a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_publisher_ubuntu26.sh +++ b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/jenkins_publisher_ubuntu26.sh @@ -6,7 +6,7 @@ # ${WORKSPACE}/url-${PROJECT}-${OS_VERSION}.txt — browseable URL of the uploaded folder # ${WORKSPACE}/tdsversion-${PROJECT}-${OS_VERSION}.txt — full version string (LTS-build) # -# Adapted for the in-tree flow: make_rpm_ubuntu26.py writes the DEBs +# Adapted for the in-tree flow: make_rpm_ubuntu26_release2.py writes the DEBs # directly under ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/ (no TDS # subfolder), so that directory is uploaded as-is. # diff --git a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/release-16-10-2026.sh b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/release-16-10-2026.sh index c8483fd96..95bb6817f 100644 --- a/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/release-16-10-2026.sh +++ b/qt6-after/qt6-migrated-legatus/jenkins-ci-rme/release-16-10-2026.sh @@ -1,27 +1,30 @@ #!/usr/bin/env bash # -# Local release pipeline for the Qt6-migrated legatus validation scope -# (TetraIF, Z, Lts/Common + Lts/Proxies/TrainingAreaBase). +# Local release pipeline for the Qt6-migrated legatus Release 2 scope +# (AP3, AP4, AP9, TetraIF, tests - 46 targets). # -# Runs the in-tree new_docker_build.sh: -# - builds the prebuilt Docker image from the in-tree Dockerfile when the -# image is not present yet +# Runs the in-tree new_docker_build_release2.sh: +# - uses the prebuilt Docker image when present; otherwise the driver +# installs the dependencies in-container from the base image (slower) # - 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). +# The DEB packages land in ${MIGRATE_PIPELINE_ROOT}/rpms/${PROJECT}/${OS_VERSION}/ +# (Jenkins-style layout; locally the pipeline root is the directory that +# contains qt-migration-legatus/). # set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" LEGATUS_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" -PIPELINE_ROOT="${LEGATUS_ROOT}" +# Tree layout: /qt-migration-legatus/qt6-after/qt6-migrated-legatus +PIPELINE_ROOT="$(cd "${LEGATUS_ROOT}/../../.." && pwd)" # Release build configuration (Jenkins-style variables) export WORKSPACE="${PIPELINE_ROOT}" +export MIGRATE_PIPELINE_ROOT="${MIGRATE_PIPELINE_ROOT:-${PIPELINE_ROOT}}" export PROJECT="${PROJECT:-guez}" export OS_VERSION="${OS_VERSION:-26.04}" export LTS_VERSION="${LTS_VERSION:-1.0}" @@ -45,15 +48,19 @@ log_info "Package output: ${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" cd "${LEGATUS_ROOT}" -# Build the prebuilt image from the in-tree Dockerfile when not present yet -# (--build-prebuilt-image builds the image and exits) -if ! docker image inspect "${DOCKER_IMAGE}" >/dev/null 2>&1; then - log_info "Prebuilt image not found - building it from the in-tree Dockerfile..." - bash ./new_docker_build.sh --build-prebuilt-image --docker-image "${DOCKER_IMAGE}" +# Use the prebuilt image when present; otherwise let the driver install the +# dependencies in-container from the base image (slower, no image build). +PREBUILT_FLAG=() +if docker image inspect "${DOCKER_IMAGE}" >/dev/null 2>&1; then + PREBUILT_FLAG=(--use-prebuilt-image) + log_info "Using prebuilt image ${DOCKER_IMAGE}" +else + log_info "Prebuilt image ${DOCKER_IMAGE} not found - the driver will install dependencies in-container" fi # Release scope build + ctest + DEB production (in-tree rpmbuild) -bash ./new_docker_build.sh \ +bash ./new_docker_build_release2.sh \ + "${PREBUILT_FLAG[@]}" \ --docker-image "${DOCKER_IMAGE}" \ --run-jenkins-builder \ --package-output-dir "${WORKSPACE}/rpms/${PROJECT}/${OS_VERSION}/" \ @@ -66,7 +73,8 @@ bash ./new_docker_build.sh \ # 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 \ + bash ./new_docker_build_release2.sh \ + "${PREBUILT_FLAG[@]}" \ --docker-image "${DOCKER_IMAGE}" \ --run-coverage \ --coverage-output-dir "${WORKSPACE}/coverage/${PROJECT}/${OS_VERSION}" diff --git a/qt6-after/qt6-migrated-legatus/new_docker_build.sh b/qt6-after/qt6-migrated-legatus/new_docker_build.sh deleted file mode 100755 index 738769fab..000000000 --- a/qt6-after/qt6-migrated-legatus/new_docker_build.sh +++ /dev/null @@ -1,1684 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -# ----------------------------------------------------------------------------- -# Build helper for qt-migrated-legatus inside Docker -# -# Features: -# - Loads environment from .envrc -# - Validates MIGRATE_PIPELINE_ROOT and rti_license.dat -# - BUILD_RTI controllable via first positional argument: ON|OFF -# - BUILD_GRANTLEE controllable via --grantlee/--no-grantlee options -# - 5 separately switchable make build groups -# - Optional usage of a prebuilt Docker image with installed dependencies -# - Optional creation of that prebuilt Docker image via --build-prebuilt-image -# - Optional deletion of that prebuilt Docker image via --delete-prebuilt-image -# - Optional disabling of ctest -# - Optional tests-only mode -# - Uses a temporary container-side script for robust execution -# - Supersedes docker_build.sh: its full migrated-service target set, apt -# package additions, and exclusion notes are merged into this script -# ----------------------------------------------------------------------------- - -usage() { - cat <<'EOF' -Usage: ./new_docker_build.sh [ON|OFF] [options] - -BUILD_RTI: - First positional argument may be: - ON Enable BUILD_RTI - OFF Disable BUILD_RTI - -BUILD_GRANTLEE: - --grantlee / --no-grantlee Enable/disable BUILD_GRANTLEE (default: ON) - -BUILD_ARCGIS: - --arcgis / --no-arcgis Enable/disable BUILD_ARCGIS (default: OFF) - -BUILD_CODIFICATION: - --codification / --no-codification Enable/disable BUILD_CODIFICATION (default: OFF, requires KDReports) - -Build groups: - --group1 / --no-group1 Enable/disable DDS core libraries build - --group2 / --no-group2 Enable/disable migration_tests build - --group3 / --no-group3 Enable/disable remaining application and service targets build - (NGL app targets + full migrated Lts service set with per-service tests) - --group4 / --no-group4 Enable/disable DDS tests and Lts/Proxies module targets - --group5 / --no-group5 Enable/disable Lts/Viewer module targets and tests only - --group6 / --no-group6 Enable/disable LTS Tools (Qt6 migration) build - --group7 / --no-group7 Enable/disable LTS Tools Group 7 (A,B,C,E,I) build - --group8 / --no-group8 Enable/disable LTS Tools Group 8 (J,M,N,P,Q) build - --group9 / --no-group9 Enable/disable LTS Tools Group 9 (R,S,T,V,W) build - --group10 / --no-group10 Enable/disable LTS Projects build - --group11 / --no-group11 Enable/disable LTS Application build - --group12 / --no-group12 Enable/disable runtime GUI/Data plugin build (OperatorApplication runtime deps) - --build-viewer-only Build only Viewer module targets (skip Groups 1-4, implies --group5 --codification; ctest runs) - -Test execution: - --no-ctest Skip ctest execution - --tests-only Run only ctest, skip all make build groups - --integration-test Run only integration tests (test_z_*, bld_*, tab_*, wls_*) - -Prebuilt Docker image usage: - --use-prebuilt-image Use a Docker image with dependencies already installed - --no-prebuilt-image Use base image and run apt-get install inside the container - --docker-image IMAGE Docker image name to use/build/delete - --cmake_build_flags FLAGS Extra CMake flags passed to the in-container configure - (space-separated -D flags, e.g. "-DBUILD_WLS=ON -DGUEZ_MODE=ON") - -Docker mount configuration: - --docker-mount-root PATH Container-side mount root path (default: /repo) - Changes where host directories are mounted in container - -Prebuilt Docker image management: - --build-prebuilt-image Build the prebuilt Docker image before running the build - If used alone, the script builds the image and exits - If combined with --use-prebuilt-image, the built image is used immediately - --delete-prebuilt-image Delete the configured Docker image and exit - -Environment variable overrides: - BUILD_RTI=ON|OFF - BUILD_GRANTLEE=ON|OFF - BUILD_ARCGIS=ON|OFF - BUILD_CODIFICATION=ON|OFF - BUILD_GROUP1=ON|OFF - BUILD_GROUP2=ON|OFF - BUILD_GROUP3=ON|OFF - BUILD_GROUP4=ON|OFF - BUILD_GROUP5=ON|OFF - BUILD_GROUP6=ON|OFF - BUILD_GROUP7=ON|OFF - BUILD_GROUP8=ON|OFF - BUILD_GROUP9=ON|OFF - BUILD_GROUP10=ON|OFF - BUILD_GROUP11=ON|OFF - BUILD_GROUP12=ON|OFF - RUN_CTEST=ON|OFF - TESTS_ONLY=ON|OFF - INTEGRATION_TEST=ON|OFF - USE_PREBUILT_IMAGE=ON|OFF - BUILD_PREBUILT_IMAGE=ON|OFF - DELETE_PREBUILT_IMAGE=ON|OFF - DOCKER_IMAGE= - DOCKER_MOUNT_ROOT= - -Required .envrc variable: - MIGRATE_PIPELINE_ROOT= - -Expected file: - ${MIGRATE_PIPELINE_ROOT}/rti_license.dat - -Defaults: - BUILD_RTI=ON - BUILD_GRANTLEE=ON - BUILD_ARCGIS=OFF - BUILD_CODIFICATION=OFF - BUILD_GROUP1=ON - BUILD_GROUP2=ON - BUILD_GROUP3=ON - BUILD_GROUP4=ON - BUILD_GROUP5=ON - BUILD_GROUP6=ON - BUILD_GROUP7=ON - BUILD_GROUP8=ON - BUILD_GROUP9=ON - BUILD_GROUP10=ON - BUILD_GROUP11=ON - BUILD_GROUP12=ON - RUN_CTEST=ON - TESTS_ONLY=OFF - INTEGRATION_TEST=OFF - USE_PREBUILT_IMAGE=OFF - BUILD_PREBUILT_IMAGE=OFF - DELETE_PREBUILT_IMAGE=OFF - DOCKER_IMAGE=legatus-qt6-prebuilt:latest - DOCKER_MOUNT_ROOT=/repo - -Examples: - ./new_docker_build.sh - ./new_docker_build.sh OFF - ./new_docker_build.sh --no-group3 - ./new_docker_build.sh --no-group1 --group2 --no-group3 - ./new_docker_build.sh --no-ctest - ./new_docker_build.sh --tests-only - ./new_docker_build.sh --build-prebuilt-image --docker-image legatus-qt6-prebuilt:latest - ./new_docker_build.sh --use-prebuilt-image --docker-image legatus-qt6-prebuilt:latest - ./new_docker_build.sh --build-prebuilt-image --use-prebuilt-image --docker-image legatus-qt6-prebuilt:latest - ./new_docker_build.sh --delete-prebuilt-image --docker-image legatus-qt6-prebuilt:latest - ./new_docker_build.sh --use-prebuilt-image --no-group1 --no-group3 --integration-test -EOF -} - -log_info() { - printf 'INFO: %s\n' "$*" -} - -log_error() { - printf 'ERROR: %s\n' "$*" >&2 -} - -die() { - log_error "$*" - exit 1 -} - -require_command() { - local cmd="$1" - command -v "$cmd" >/dev/null 2>&1 || die "Required command not found: ${cmd}" -} - -require_file() { - local path="$1" - local label="$2" - [[ -f "$path" ]] || die "${label} not found: ${path}" -} - -require_directory() { - local path="$1" - local label="$2" - [[ -d "$path" ]] || die "${label} directory not found: ${path}" -} - -require_non_empty() { - local value="$1" - local name="$2" - [[ -n "$value" ]] || die "Required variable ${name} is not set or empty" -} - -normalize_on_off() { - local value="$1" - local name="$2" - - case "${value^^}" in - ON|OFF) - printf '%s\n' "${value^^}" - ;; - *) - die "Invalid value for ${name}: ${value}. Expected ON or OFF" - ;; - esac -} - -log_group() { - local group_name="$1" - local enabled="$2" - - if [[ "$enabled" == "ON" ]]; then - log_info "${group_name} enabled" - else - log_info "${group_name} disabled - skipping" - fi -} - -join_by() { - local delimiter="$1" - shift || true - local first=1 - local arg - - for arg in "$@"; do - if [[ $first -eq 1 ]]; then - printf '%s' "$arg" - first=0 - else - printf '%s%s' "$delimiter" "$arg" - fi - done -} - -cleanup_temp_dir() { - local dir="${1:-}" - if [[ -n "$dir" && -d "$dir" ]]; then - rm -rf "$dir" - fi -} - -delete_prebuilt_image() { - local image_name="$1" - - if docker image inspect "$image_name" >/dev/null 2>&1; then - log_info "Deleting Docker image: ${image_name}" - docker rmi "$image_name" - log_info "Docker image deleted successfully: ${image_name}" - else - log_info "Docker image does not exist, nothing to delete: ${image_name}" - fi -} - -APT_PACKAGES=( - build-essential - cmake - libboost-dev - libkf6texttemplate-dev - libqt6core6 - libqt6gui6 - libqt6widgets6 - libqt6sql6 - libqt6sql6-psql - libqt6test6 - qt6-base-dev - qt6-l10n-tools - qt6-serialport-dev - qt6-svg-dev - qt6-tools-dev-tools - qt6-tools-dev - qt6-websockets-dev - libgtest-dev - libpq-dev - postgresql-server-dev-all - libvlc-dev - vlc-plugin-base - git - python3-pip -) - -# INTERFACE libraries (header-only) are built automatically as dependencies -# Only list actual buildable targets (SHARED/STATIC libraries, executables) -GROUP1_TARGETS=( - ddscore - svcCoreClient - ddsftccore - ddsfts - ddsgen - ddsQoS - ddsconnector -) - -GROUP2_TARGETS=( - migration_tests -) - -# Validation builds the full service set, not only the targets that -# happened to be migrated first: every service library, the per-service -# test executables, and the shared libraries they need. Targets that are -# known blocked for reasons outside this migration are excluded below, so -# a green run means every migratable service actually compiles. -# -# This is the full validation set formerly built by docker_build.sh, which -# is superseded by this script. -# -# Excluded, each for a dependency this migration cannot supply: -# svcTargetManagement - needs SituationMap::ElevationMap / -# LineOfSightCalculation, the GDAL module -# whose CMakeLists states it was never -# migrated (main_handler.h:18 includes -# ). -# svcExerciseManagement - needs QStateMachine / QState, moved from -# svcInfrastructureManagement QtCore to the Qt SCXML module in Qt6 -# exmStateMachineTest (Qt6::StateMachine). No qt6-scxml-dev in -# the image and qstatemachine.h is absent. -# svcBuildings - its generated record_replay_plugin -# (bld_record_replay_plugin.cpp) calls -# fromQVariant() for the nested foreign -# ProjectDataManagement types -# VulnerabilityState / -# StateChangeOriginator, for which no -# specialization is generated (they are -# not Buildings' own types), leaving the -# generic fromQVariant template -# undefined -> link error. -# svcParticipantManagement - its record_replay custom header -# (RecordReplay/ppm_record_replay_plugin_custom.h) -# declares Q_INTERFACES(RecordReplay:: -# RecordReplayPlugin) on a class that also -# inherits ParticipantHandling::BaseDataProvider -# (a second Q_OBJECT base the other record_replay -# custom plugins lack). Qt6's MOC reports -# "Undefined interface" for the Q_INTERFACES in -# that multi-Q_OBJECT-base context (RecordReplay:: -# RecordReplayPlugin is a Q_GADGET, not a Q_OBJECT), -# so the plugin autogen step fails before link. -# (The nested-foreign-PDM fromQVariant link error -# that also applied is now resolved by the -# fromQVariant primary-template body added to -# svc_record_replay_plugin.cpp.grantlee.) The PPM -# client/common/server libs still build; only this -# exe is excluded. -GROUP3_TARGETS=( - NGLLogger - nglapplication - nglcompression - nglcoreapplication - ngldb - nglguiapplication - nglsettings - nglsingleapplication - nglsinglecoreapplication - ngltools - ngltranslator - nglwidgets - qtsingleapplication - qtsinglecoreapplication - wms_json_ds - tcpserver - # ProjectDataManagement - svcPdmCommon - svcPdmClient - svcPdmServer - svcProjectDataManagement - pdmTests - # Migrated Lts services (full validation set merged from docker_build.sh) - svcAesClient - svcAesCommon - svcAesServer - svcAlmClient - svcAlmCommon - svcAlmServer - svcAreaEffectSimulation - svcAsmClient - svcAsmCommon - svcAsmServer - svcAssetManagement - svcAudioVideoManagement - svcAvmClient - svcAvmCommon - svcAvmServer - # svcBldServer builds in Group 4 (Proxies module) - svcBldClient - svcBldCommon - svcCentralEffectSimulation - svcCesClient - svcCesCommon - svcCesDDSCommon - svcCesGeoPairingImpl - svcCesServer - svcCodClient - svcCodCommon - svcCodServer - svcEemClient - svcEemCommon - svcEemServer - svcEffectShowClient - svcEscClient - svcEscCommon - svcEscServer - svcEsmClient - svcEsmCommon - svcEsmServer - svcEvlClient - svcEvlCommon - svcEvlServer - svcExerciseEventManagement - svcExmClient - svcExmCommon - svcExmServer - svcFileManagement - svcFilterManagement - svcFlmClient - svcFlmCommon - svcFlmServer - svcFltClient - svcFltCommon - svcFltServer - svcGimClient - svcGimCommon - svcGimServer - svcGmpServer - svcGuezIedManagement - svcIsmClient - svcIsmCommon - svcIsmServer - svcMapDummy - svcMdmClient - svcMdmCommon - svcMdmServer - svcMessaging - svcMeteoDataManagement - svcMrkClient - svcMrkCommon - svcMrkServer - svcMsgClient - svcMsgCommon - svcMsgServer - svcNomClient - svcNomCommon - svcNomServer - svcNotificationManagement - svcNmeClient - svcNmeCommon - svcNmeServer - svcNmeaManagement - svcObdClient - svcObdCommon - svcObdServer - svcOcBaseDownload - svcOcSituationClient - svcOcSituationServer - svcOperatorManagement - svcOpmClient - svcOpmCommon - svcOpmServer - svcOreDummy - svcOscClient - svcOscCommon - svcOscServer - svcOssClient - svcOssCommon - svcOssServer - svcPedDummy - svcPpmClient - svcPpmCommon - svcPpmServer - svcPreClient - svcPreCommon - svcPreServer - svcPwsCommon - svcRecCommon - svcRecordingManagement - svcRepClient - svcRepCommon - svcRepCommonExecutable - svcRepServer - svcReportAnalyzer - svcReportGenerator - svcScmClient - svcScmCommon - svcScmServer - svcScrDummy - svcServiceManagement - svcSituationReplay - svcSmoDummy - svcSomClient - svcSomCommon - svcSomServer - svcSoundManagement - svcSrmCommon - svcSrpClient - svcSrpCommon - svcSrpServer - svcTgtClient - svcTgtCommon - svcTgtServer - svcVideoOverlayManagement - svcWarehouseGuez - svcWhgClient - svcWhgCommon - svcWhgServer - # Per-service tests (merged from docker_build.sh) - asmTests - avmFtTests - avmTests - avmVcaTests - cesTests - eemTests - evlTests - exmDtUnitTest - exmTests - flmTests - gmpTests - ismTests - mrkTests - mvsTests - nomTests - opmTests - ppmTests - preTests - repTests - scmDtUnitTest - srpFtTests - tgtTests - whgTests -) - -GROUP4_TARGETS=( - # DDS tests - ddsGenericDataTests - ddsDataTopicTests - ddsFunctionTopicTests - # Proxies module - Buildings - BuildingControlCommon - BuildingControlBsm - BuildingControlTestBsm - BuildingControlVwm - BuildingControlTestVwm - BuildingControlTestVwmXml - # BuildingControlJson - requires Qt6WebSockets (not available) - # ControlEffects - may depend on BuildingControlJson - # ControlEffectsTest - # BuildingControlUnit - depends on BuildingControlJson - svcBldServer - svcBuildings - # Proxies module - TrainingAreaBase - tabTelegrams - svcTabCommon - svcTabClient - svcTabServer - svcTrainingAreaBase - # tabPluginInterface - defined in the CMake but no make rule is generated (base state) - # TmsIfAdapterInterface/TmsIfAdapter/tabPluginUAS/TabUASTest3/TabUASTest4_2/TabUASTest6 - # - only built with BUILD_UAS_PROXY=ON (default OFF, not exposed by this script) - # tabPluginInterface - # TmsIfAdapterInterface - # TmsIfAdapter - # tabPluginUAS - # TabUASTest3 - # TabUASTest4_2 - # TabUASTest6 - # Proxies module - TrainingAreaBaseOC - svcTabocCommon - svcTabocClient - svcTabocServer - svcTrainingAreaBaseOC - serialtest - # Proxies module - WirelessLocationSystem (requires -DBUILD_WLS=ON, e.g. via - # --cmake_build_flags "-DBUILD_WLS=ON") - # svcWirelessLocationSystem - # wlsJsonClientTest - # Proxies module - Other - svcCmoCommon - svcCmoClient - svcCmoServer - svcComponentMonitor - svcCnrHelper - svcCombatNetRadio - svcDifferentialGPS - svcGnaCommon - svcGnaClient - svcGnaServer - svcWarehouseManagement - Tetra_dgps_simulator -) - -APT_PACKAGES_STRING="$(join_by ' ' "${APT_PACKAGES[@]}")" - -build_prebuilt_image() { - local image_name="$1" - local tmp_dir - tmp_dir="$(mktemp -d)" - - trap 'cleanup_temp_dir "$tmp_dir"' RETURN - - cat > "${tmp_dir}/Dockerfile" </dev/null || \ - (git clone --depth 1 https://github.com/KDAB/KDReports.git /tmp/KDReports && \ - cd /tmp/KDReports && \ - mkdir build && cd build && \ - cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_PREFIX_PATH=${QT_BASE_DIR} .. && \ - make -j10 && \ - make install && \ - cd / && rm -rf /tmp/KDReports) - -# Legacy sources include but the Qt6 package installs headers flat -# under /usr/local/include/KDReports-qt6 - alias the directory so the prefixed -# includes resolve through the default /usr/local/include search path. -RUN ln -sfn KDReports-qt6 /usr/local/include/KDReports - -CMD ["/bin/bash"] -EOF - - log_info "Building prebuilt Docker image: ${image_name}" - docker build -t "${image_name}" "${tmp_dir}" - log_info "Prebuilt Docker image created successfully: ${image_name}" -} - -install_qt6_packages() { - log_info "Installing Qt6 packages via aqtinstall" - - # Install aqtinstall if not available - if ! command -v aqt &> /dev/null; then - log_info "Installing aqtinstall via pip3" - pip3 install --break-system-packages --quiet aqtinstall - fi - - # Install Qt6 modules (same as app/Dockerfile) - # Modules: qtmultimedia, qtserialport, qtimageformats, qtwebsockets, qtwebengine, - # qtpdf, qtwebview, qt5compat, qtwebchannel, qtpositioning, qtlocation, qtsensors - # Note: qtsvg is NOT available via aqtinstall - it's provided by libqt6svg6-dev apt package - aqt install-qt linux desktop "${QT_VERSION:-6.10.2}" "${QT_ARCH:-linux_gcc_64}" \ - -m qtmultimedia qtserialport qtimageformats qtwebsockets qtwebengine \ - qtpdf qtwebview qt5compat qtwebchannel qtpositioning qtlocation qtsensors \ - --outputdir "${QT_BASE_DIR:-/opt/Qt}" - - log_info "Qt6 packages installed successfully" -} - -require_command docker - -if [[ ! -f ".envrc" ]]; then - die ".envrc not found in current directory. Please create .envrc with required environment variables (e.g., MIGRATE_PIPELINE_ROOT)" -fi - -set -a -# shellcheck disable=SC1091 -source ".envrc" -set +a - -BUILD_ALL="${BUILD_ALL:-ON}" -BUILD_SV="${BUILD_SV:-ON}" -BUILD_WS="${BUILD_WS:-ON}" -BUILD_AAR="${BUILD_AAR:-ON}" -BUILD_RTI="${BUILD_RTI:-ON}" -BUILD_GRANTLEE="${BUILD_GRANTLEE:-ON}" -BUILD_ARCGIS="${BUILD_ARCGIS:-OFF}" -BUILD_CODIFICATION="${BUILD_CODIFICATION:-OFF}" -BUILD_GROUP1="${BUILD_GROUP1:-ON}" -BUILD_GROUP2="${BUILD_GROUP2:-ON}" -BUILD_GROUP3="${BUILD_GROUP3:-ON}" -BUILD_GROUP4="${BUILD_GROUP4:-ON}" -BUILD_GROUP5="${BUILD_GROUP5:-ON}" -BUILD_GROUP6="${BUILD_GROUP6:-ON}" -BUILD_GROUP7="${BUILD_GROUP7:-ON}" -BUILD_GROUP8="${BUILD_GROUP8:-ON}" -BUILD_GROUP9="${BUILD_GROUP9:-ON}" -BUILD_GROUP10="${BUILD_GROUP10:-ON}" -BUILD_GROUP11="${BUILD_GROUP11:-ON}" -BUILD_GROUP12="${BUILD_GROUP12:-ON}" -BUILD_VIEWER_ONLY="${BUILD_VIEWER_ONLY:-OFF}" -RUN_CTEST="${RUN_CTEST:-ON}" -TESTS_ONLY="${TESTS_ONLY:-OFF}" -INTEGRATION_TEST="${INTEGRATION_TEST:-OFF}" -USE_PREBUILT_IMAGE="${USE_PREBUILT_IMAGE:-OFF}" -BUILD_PREBUILT_IMAGE="${BUILD_PREBUILT_IMAGE:-OFF}" -DELETE_PREBUILT_IMAGE="${DELETE_PREBUILT_IMAGE:-OFF}" -export QT_VERSION="${QT_VERSION:-6.10.2}" -export QT_ARCH="${QT_ARCH:-linux_gcc_64}" -# aqtinstall uses 'linux_gcc_64' but creates directory 'gcc_64' -export QT_ARCH_DIR="${QT_ARCH_DIR:-gcc_64}" -export QT_BASE_DIR="${QT_BASE_DIR:-/opt/Qt}" - -if [[ $# -gt 0 ]]; then - case "$1" in - ON|OFF) - BUILD_RTI="$1" - shift - ;; - esac -fi - -# Initialize DOCKER_MOUNT_ROOT default before argument parsing -DOCKER_MOUNT_ROOT="${DOCKER_MOUNT_ROOT:-/repo}" - -while [[ $# -gt 0 ]]; do - case "$1" in - --group1) - BUILD_GROUP1=ON - ;; - --no-group1) - BUILD_GROUP1=OFF - ;; - --group2) - BUILD_GROUP2=ON - ;; - --no-group2) - BUILD_GROUP2=OFF - ;; - --group3) - BUILD_GROUP3=ON - ;; - --no-group3) - BUILD_GROUP3=OFF - ;; - --group4) - BUILD_GROUP4=ON - ;; - --no-group4) - BUILD_GROUP4=OFF - ;; - --group5) - BUILD_GROUP5=ON - ;; - --no-group5) - BUILD_GROUP5=OFF - ;; - --group6) - BUILD_GROUP6=ON - ;; - --no-group6) - BUILD_GROUP6=OFF - ;; - --group7) - BUILD_GROUP7=ON - ;; - --no-group7) - BUILD_GROUP7=OFF - ;; - --group8) - BUILD_GROUP8=ON - ;; - --no-group8) - BUILD_GROUP8=OFF - ;; - --group9) - BUILD_GROUP9=ON - ;; - --no-group9) - BUILD_GROUP9=OFF - ;; - --group10) - BUILD_GROUP10=ON - ;; - --no-group10) - BUILD_GROUP10=OFF - ;; - --group11) - BUILD_GROUP11=ON - ;; - --no-group11) - BUILD_GROUP11=OFF - ;; - --group12) - BUILD_GROUP12=ON - ;; - --no-group12) - BUILD_GROUP12=OFF - ;; - --build-viewer-only) - BUILD_VIEWER_ONLY=ON - BUILD_GROUP5=ON - BUILD_CODIFICATION=ON - RUN_CTEST=ON - ;; - --grantlee) - BUILD_GRANTLEE=ON - ;; - --no-grantlee) - BUILD_GRANTLEE=OFF - ;; - --arcgis) - BUILD_ARCGIS=ON - ;; - --no-arcgis) - BUILD_ARCGIS=OFF - ;; - --codification) - BUILD_CODIFICATION=ON - ;; - --no-codification) - BUILD_CODIFICATION=OFF - ;; - --no-ctest) - RUN_CTEST=OFF - ;; - --tests-only) - TESTS_ONLY=ON - ;; - --integration-test) - INTEGRATION_TEST=ON - ;; - --use-prebuilt-image) - USE_PREBUILT_IMAGE=ON - ;; - --no-prebuilt-image) - USE_PREBUILT_IMAGE=OFF - ;; - --build-prebuilt-image) - BUILD_PREBUILT_IMAGE=ON - ;; - --delete-prebuilt-image) - DELETE_PREBUILT_IMAGE=ON - ;; - --docker-image) - shift - [[ $# -gt 0 ]] || die "--docker-image requires an image name" - DOCKER_IMAGE="$1" - ;; - --cmake_build_flags) - shift - [[ $# -gt 0 ]] || die "--cmake_build_flags requires a flag string" - CMAKE_BUILD_FLAGS="$1" - ;; - --docker-mount-root) - shift - [[ $# -gt 0 ]] || die "--docker-mount-root requires a path" - DOCKER_MOUNT_ROOT="$1" - ;; - -h|--help) - usage - exit 0 - ;; - *) - usage - die "Unknown option: $1" - ;; - esac - shift -done - -# Set defaults for variables not set by command-line arguments -BUILD_RTI="${BUILD_RTI:-ON}" -BUILD_GROUP1="${BUILD_GROUP1:-ON}" -BUILD_GROUP2="${BUILD_GROUP2:-ON}" -BUILD_GROUP3="${BUILD_GROUP3:-ON}" -BUILD_GROUP4="${BUILD_GROUP4:-ON}" -BUILD_GROUP5="${BUILD_GROUP5:-ON}" -BUILD_GROUP6="${BUILD_GROUP6:-ON}" -BUILD_GROUP7="${BUILD_GROUP7:-ON}" -BUILD_GROUP8="${BUILD_GROUP8:-ON}" -BUILD_GROUP9="${BUILD_GROUP9:-ON}" -BUILD_GROUP10="${BUILD_GROUP10:-ON}" -BUILD_GROUP11="${BUILD_GROUP11:-ON}" -RUN_CTEST="${RUN_CTEST:-ON}" -TESTS_ONLY="${TESTS_ONLY:-OFF}" -INTEGRATION_TEST="${INTEGRATION_TEST:-OFF}" -USE_PREBUILT_IMAGE="${USE_PREBUILT_IMAGE:-OFF}" -BUILD_PREBUILT_IMAGE="${BUILD_PREBUILT_IMAGE:-OFF}" -DELETE_PREBUILT_IMAGE="${DELETE_PREBUILT_IMAGE:-OFF}" - -BUILD_ALL="$(normalize_on_off "$BUILD_ALL" "BUILD_ALL")" -BUILD_RTI="$(normalize_on_off "$BUILD_RTI" "BUILD_RTI")" -BUILD_GRANTLEE="$(normalize_on_off "$BUILD_GRANTLEE" "BUILD_GRANTLEE")" -BUILD_ARCGIS="$(normalize_on_off "$BUILD_ARCGIS" "BUILD_ARCGIS")" -BUILD_CODIFICATION="$(normalize_on_off "$BUILD_CODIFICATION" "BUILD_CODIFICATION")" -BUILD_GROUP1="$(normalize_on_off "$BUILD_GROUP1" "BUILD_GROUP1")" -BUILD_GROUP2="$(normalize_on_off "$BUILD_GROUP2" "BUILD_GROUP2")" -BUILD_GROUP3="$(normalize_on_off "$BUILD_GROUP3" "BUILD_GROUP3")" -BUILD_GROUP4="$(normalize_on_off "$BUILD_GROUP4" "BUILD_GROUP4")" -BUILD_GROUP5="$(normalize_on_off "$BUILD_GROUP5" "BUILD_GROUP5")" -# Auto-enable BUILD_ARCGIS when BUILD_GROUP5=ON (situationMap depends on advancedSymbology) -if [[ "${BUILD_GROUP5}" == "ON" ]]; then - BUILD_ARCGIS=ON -fi -BUILD_GROUP6="$(normalize_on_off "$BUILD_GROUP6" "BUILD_GROUP6")" -BUILD_GROUP7="$(normalize_on_off "$BUILD_GROUP7" "BUILD_GROUP7")" -BUILD_GROUP8="$(normalize_on_off "$BUILD_GROUP8" "BUILD_GROUP8")" -BUILD_GROUP9="$(normalize_on_off "$BUILD_GROUP9" "BUILD_GROUP9")" -BUILD_GROUP10="$(normalize_on_off "$BUILD_GROUP10" "BUILD_GROUP10")" -BUILD_GROUP11="$(normalize_on_off "$BUILD_GROUP11" "BUILD_GROUP11")" -BUILD_VIEWER_ONLY="$(normalize_on_off "$BUILD_VIEWER_ONLY" "BUILD_VIEWER_ONLY")" -RUN_CTEST="$(normalize_on_off "$RUN_CTEST" "RUN_CTEST")" -TESTS_ONLY="$(normalize_on_off "$TESTS_ONLY" "TESTS_ONLY")" -INTEGRATION_TEST="$(normalize_on_off "$INTEGRATION_TEST" "INTEGRATION_TEST")" -USE_PREBUILT_IMAGE="$(normalize_on_off "$USE_PREBUILT_IMAGE" "USE_PREBUILT_IMAGE")" -BUILD_PREBUILT_IMAGE="$(normalize_on_off "$BUILD_PREBUILT_IMAGE" "BUILD_PREBUILT_IMAGE")" -DELETE_PREBUILT_IMAGE="$(normalize_on_off "$DELETE_PREBUILT_IMAGE" "DELETE_PREBUILT_IMAGE")" - -# Set DOCKER_IMAGE default after argument parsing -if [[ "${USE_PREBUILT_IMAGE}" == "ON" ]]; then - DOCKER_IMAGE="${DOCKER_IMAGE:-legatus-qt6-prebuilt:latest}" -else - DOCKER_IMAGE="${DOCKER_IMAGE:-ubuntu:26.04}" -fi - -# Default for DOCKER_MOUNT_ROOT -DOCKER_MOUNT_ROOT="${DOCKER_MOUNT_ROOT:-/repo}" - -# Default for extra CMake flags (set via --cmake_build_flags or environment) -CMAKE_BUILD_FLAGS="${CMAKE_BUILD_FLAGS:-}" - -# Export variables for Docker container -export BUILD_ALL BUILD_RTI BUILD_GRANTLEE BUILD_ARCGIS BUILD_CODIFICATION BUILD_GROUP1 BUILD_GROUP2 BUILD_GROUP3 BUILD_GROUP4 BUILD_GROUP5 BUILD_GROUP6 BUILD_GROUP7 BUILD_GROUP8 BUILD_GROUP9 BUILD_GROUP10 BUILD_GROUP11 BUILD_VIEWER_ONLY RUN_CTEST TESTS_ONLY INTEGRATION_TEST USE_PREBUILT_IMAGE BUILD_PREBUILT_IMAGE DELETE_PREBUILT_IMAGE DOCKER_IMAGE CMAKE_BUILD_FLAGS DOCKER_MOUNT_ROOT - -# Group 5: Viewer module targets (conditional on BUILD_ARCGIS) -# Note: LtsFileDialog excluded from viewer-only builds due to Group 4 dependencies (svcExmCommon, svcOpmCommon, svcFlmCommon) -if [[ "${BUILD_ARCGIS}" == "ON" ]]; then - if [[ "${BUILD_VIEWER_ONLY}" == "ON" ]]; then - # Viewer-only build: exclude LtsFileDialog (requires Group 4 services) - GROUP5_TARGETS=( - # Viewer module with ArcGIS (viewer-only subset) - situationMapCommon - ArcGISQt5Hack - situationMapElevationMap - situationMapGeometryModel - situationMapSideBar - advancedSymbology - advancedSymbologyXML - situationMap - LtsDataView - LtsDataViewTest - # Qt6 Migration Unit Tests - test_qt6_api_migrations - test_graphical_objects - test_rubberbands - test_mathutils - test_mapimpl - test_symbologyimpl - test_viewshed3d - ) - else - GROUP5_TARGETS=( - # Viewer module with ArcGIS (full build) - situationMapCommon - ArcGISQt5Hack - situationMapElevationMap - situationMapGeometryModel - situationMapSideBar - advancedSymbology - advancedSymbologyXML - situationMap - LtsDataView - LtsDataViewTest - LtsFileDialog - LtsFileDialogTest - # Qt6 Migration Unit Tests - test_qt6_api_migrations - test_graphical_objects - test_rubberbands - test_mathutils - test_mapimpl - test_symbologyimpl - test_viewshed3d - ) - fi -else - if [[ "${BUILD_VIEWER_ONLY}" == "ON" ]]; then - # Viewer-only build: exclude LtsFileDialog (requires Group 4 services) - GROUP5_TARGETS=( - # Viewer module without ArcGIS (viewer-only subset, advancedSymbology requires ArcGIS) - situationMapCommon - situationMapElevationMap - situationMapGeometryModel - situationMapSideBar - advancedSymbologyXML - situationMap - LtsDataView - LtsDataViewTest - # Qt6 Migration Unit Tests - test_qt6_api_migrations - test_graphical_objects - test_rubberbands - test_mathutils - test_mapimpl - test_symbologyimpl - test_viewshed3d - ) - else - GROUP5_TARGETS=( - # Viewer module without ArcGIS (full build) - situationMapCommon - situationMapElevationMap - situationMapGeometryModel - situationMapSideBar - advancedSymbologyXML - situationMap - LtsDataView - LtsDataViewTest - LtsFileDialog - LtsFileDialogTest - # Qt6 Migration Unit Tests - test_qt6_api_migrations - test_graphical_objects - test_rubberbands - test_mathutils - test_mapimpl - test_symbologyimpl - test_viewshed3d - ) - fi -fi - -# LtsReportDisplay only exists when BUILD_CODIFICATION=ON (the module -# RETURN()s otherwise); requesting the target unconditionally aborts make -# with "No rule to make target" -if [[ "${BUILD_CODIFICATION}" == "ON" ]]; then - GROUP5_TARGETS+=("LtsReportDisplay") -fi - -# Group 6: LTS Tools (Qt6 migration targets) - Release 2 AP9 scope only -# These tools require RTI DDS for DataSampleGenerator and DdsView -GROUP6_TARGETS=( - # AP9 tools for Release 2 - tDataSampleGenerator - ddsview - LogViewer - ParticipantDataGenerator - sqlbrowser - topicdiscover - VulnerabilityStateGenerator -) - -# Group 7: LTS Tools A,B,C,E,I directories (Qt6 migration targets) -GROUP7_TARGETS=( - AdlerWebSocketSimulator - # AsmWorkstationCertifier - requires botan2 (not available in prebuilt image); target not generated - CnrProxyTester - ConfigX - EEMFakeServer - egcuSimulator -) - -# Group 8: LTS Tools J,M,N,P,Q directories (Qt6 migration targets) -GROUP8_TARGETS=( - ParticipantDataGenerator - ProjectSettingsEditor - qledline - qledmatrix -) - -# Group 9: LTS Tools R,S,T,V,W directories (Qt6 migration targets) -GROUP9_TARGETS=( - RestClientUi - ScreenIdShow - SerialToTcpConverter - Splash - sqlbrowser - textEditorTest - ctime - stime - topicdiscover - topicdiscoverexe - # TrajectoryWidget - standalone sub-project (own project()/find_package), not part of the main build - vapixconfig - # VideoImport - subdir commented out in Lts/Tools/CMakeLists.txt - # wlsRandomPositions - requires -DBUILD_WLS=ON -) - -# Group 10: LTS Projects (Qt6 migration targets) -GROUP10_TARGETS=( - ProjectGuezPlugin - ProjectQatarMOUTPlugin - ProjectQatarPlugin - ProjectLegatusPlugin - ProjectDemoTabletPlugin - ProjectL400P2Plugin - ProjectComMasterPlugin - ProjectAhtcPlugin - ProjectEtsPlugin -) - -# Group 11: LTS Application (Qt6 migration targets) -GROUP11_TARGETS=( - OperatorApplication - # thp_viewer - Lts/Application/THP subdir commented out (VLC dependency unavailable) - aarApp -) - -# Group 12: runtime GUI/Data plugins. OperatorApplication's plugin loader -# (Lts/Common/LtsPluginManager/lts_plugin_loader.cpp) scans /../lib for -# *Plugin*.so and matches the IID metadata against apps.json plugin requirements; -# without these the app reports "App Requirements check failed" at startup. -# Plugin outputs land in build4/lib, the directory the loader scans. -# Excluded (environmental floors, not migration regressions): -# cesPluginGeoPairing - needs the external Schusstafel.h header (missing) -# BldInfoGuiPlugin - links BuildingViewerCommon (dtEntity/OSG SDK absent) -GROUP12_TARGETS=( - AesAirSupportGuiPlugin - AesBcContaminationGuiPlugin - AesBorderlineGuiPlugin - AesChargeAdministrationGuiPlugin - AesChargeEffectGuiPlugin - AesDangerAreaGuiPlugin - AesDataPlugin - AesExplosionGuiPlugin - AesFunctionalAreaGuiPlugin - AesGasPipeGuiPlugin - AesInfoGuiPlugin - AesMineAreaGuiPlugin - AesMineCorridorGuiPlugin - AesMineSingleVirtualGuiPlugin - AesNContaminationGuiPlugin - AesTechnicalAreaGuiPlugin - AlmConfigAlarmGuiPlugin - AlmDataPlugin - AlmEmergencyCallGuiPlugin - AlmOnlineReportsGuiPlugin - AppStarterGuiPlugin - AsbDataPlugin - AsbForeignDataPluginThp - AsbSymEditGuiPlugin - AsbSymbolProxyGuiPlugin - AsmDataPlugin - AsmGuiPlugin - AvmDataPlugin - AvmElokaGuiPlugin - BatGuiPlugin - BldDataPlugin - CdsSimulationGuiPlugin - CesDataPlugin - CesParticipantMoveGuiPlugin - CesParticipantUASGuiPlugin - CmoDataPlugin - DevGuiPlugin - EfmDataPlugin - EfmSoundAreaGuiPlugin - EscDataPlugin - EscEffectShowGuiPlugin - EsmComboBoxGuiPlugin - EsmDataPlugin - EsmEffectShowGuiPlugin - EvlDataPlugin - EvlEditGuiPlugin - EvlSanNineLinerEditGuiPlugin - ExmDataPlugin - ExmEditGuiPlugin - ExmWatchGuiPlugin - FlmComboBoxGuiPlugin - FlmDataPlugin - FlmExplorerGuiPlugin - FspGuiPlugin - GimDataPlugin - GimInfoGuiPlugin - GimPairingGuiPlugin - GnaDataPlugin - GnaNasatGuiPlugin - GnaNasatPartGuiPlugin - GuiElementPlugin - IsmAvcGuiPlugin - IsmComboBoxGuiPlugin - IsmDataPlugin - IsmDataPluginThp - IsmExerciseAssignmentClassicGuiPlugin - IsmResGuiPlugin - MdmDataPlugin - MdmMeteoDataGuiPlugin - MrkDataPlugin - MrkEditGuiPlugin - MsgDataPlugin - MsgMessageingGuiPlugin - MvsVideoTeamGuiPlugin - NmeNotificationGuiPlugin - NomDataPlugin - NomEditGuiPlugin - ObdBaseDownloaderGuiPlugin - ObdDataPlugin - OpmComboBoxGuiPlugin - OpmDataPlugin - OpmEditGuiPlugin - OpmLoginGuiPlugin - OpmOverviewGuiPlugin - OpmSettingsGuiPlugin - OscDataPlugin - OscParticipantInfoGuiPlugin - OscSystemGuiPlugin - OscTerminalGuiPlugin - PdmChargeTableGuiPlugin - PdmComboBoxGuiPlugin - PdmDataPlugin - PlanOverlaysGuiPlugin - PpmComboBoxGuiPlugin - PpmDataPlugin - PpmOperationalPlaningGuiPlugin - PpmParticipantEditGuiPlugin - PpmParticipantInfoGuiPlugin - PpmParticipantTemplatesGuiPlugin - PpmPartyEditGuiPlugin - PpmTypeEditGuiPlugin - PpmUasGuiPlugin - PreDataPlugin - PreEditGuiPlugin - PreScriptTimelineGuiPlugin - ProjectAhtcPlugin - ProjectComMasterPlugin - ProjectDemoTabletPlugin - ProjectEtsPlugin - ProjectGuezPlugin - ProjectL400P2Plugin - ProjectLegatusPlugin - ProjectQatarMOUTPlugin - ProjectQatarPlugin - PwsGuiPlugin - RecordReplayPlugin - RepDataPlugin - RmeDarkStylePlugin - RmeLightStylePlugin - SaaDataPlugin - SaaGuiPlugin - ScmDataPlugin - ScmEditGuiPlugin - ScrScreenRecordingGuiPlugin - SitmapGuiPlugin - SituationMapScriptFilterGuiPlugin - SrmDataPlugin - SrmReplayManagementGuiPlugin - SrpDataPlugin - SrpReplayControlGuiPlugin - TabDataPlugin - TabNotificationGuiPlugin - TabOcSfmMessagingGuiPlugin - TabocDataPlugin - TabocGuiPlugin - TgtDataPlugin - TgtTargetGuiPlugin - Thp2ManagementGuiPlugin - Thp2UsbManagementGuiPlugin - TlnDataPlugin - TlnEventTimelineGuiPlugin - VkbPlugin - WhmDataPlugin - WhmGuiPlugin - aesRecordReplayPlugin - aesTopicTypePlugin - almRecordReplayPlugin - almTopicTypePlugin - asmTopicTypePlugin - avmCombatNetRadioGuiPlugin - avmMenuEditGuiPlugin - avmTopicTypePlugin - avmTrainingVoiceGuiPlugin - bldRecordReplayPlugin - bldTopicTypePlugin - cesPluginArtillerySound - cesPluginBasic - cesPluginCES_FunctionalAreas - cesPluginCES_Jamming - cesPluginCES_MissionPlan - cesPluginCES_NBC - cesPluginCesBuildings - cesPluginExplosions - cesPluginMineAreas - cesPluginMineLayingArtillery - cesPluginParticipantBuildings - cesPluginVirtualMines - cesRecordReplayPlugin - cesTopicTypePlugin - cmoTopicTypePlugin - codTopicTypePlugin - coreTopicTypePlugin - eemTopicTypePlugin - escTopicTypePlugin - esmTopicTypePlugin - evlTopicTypePlugin - exmTopicTypePlugin - flmTopicTypePlugin - fltTopicTypePlugin - gimRecordReplayPlugin - gimTopicTypePlugin - gnaRecordReplayPlugin - gnaTopicTypePlugin - ismTopicTypePlugin - ltswidgetsplugin - mdmTopicTypePlugin - mrkTopicTypePlugin - msgTopicTypePlugin - nmeTopicTypePlugin - nomTopicTypePlugin - obdTopicTypePlugin - opmTopicTypePlugin - oscTopicTypePlugin - ossRecordReplayPlugin - ossTopicTypePlugin - pdmTopicTypePlugin - ppmRecordReplayPlugin - ppmTopicTypePlugin - preTopicTypePlugin - repTopicTypePlugin - scmTopicTypePlugin - somTopicTypePlugin - srpTopicTypePlugin - tabPluginAdler - tabPluginDebugJsonDir - tabPluginHla - tabPluginWlsTetra - tabRecordReplayPlugin - tabTopicTypePlugin - tabocTopicTypePlugin - tgtTopicTypePlugin - whgTopicTypePlugin -) - -require_non_empty "${DOCKER_IMAGE}" "DOCKER_IMAGE" - -if [[ "${DELETE_PREBUILT_IMAGE}" == "ON" ]]; then - delete_prebuilt_image "${DOCKER_IMAGE}" - exit 0 -fi - -require_non_empty "${MIGRATE_PIPELINE_ROOT:-}" "MIGRATE_PIPELINE_ROOT" -require_directory "${MIGRATE_PIPELINE_ROOT}" "MIGRATE_PIPELINE_ROOT" - -RTI_LICENSE_FILE_HOST="${MIGRATE_PIPELINE_ROOT}/rti_license.dat" -WORKSPACE_ROOT_HOST="${MIGRATE_PIPELINE_ROOT}" -PROJECT_DIR_HOST="${WORKSPACE_ROOT_HOST}/qt-migration-legatus/qt6-after/qt6-migrated-legatus" - -require_file "${RTI_LICENSE_FILE_HOST}" "RTI license file" -require_directory "${PROJECT_DIR_HOST}" "Project directory" - -if [[ "$TESTS_ONLY" == "ON" ]]; then - BUILD_GROUP1=OFF - BUILD_GROUP2=OFF - BUILD_GROUP3=OFF - RUN_CTEST=ON -fi - -log_info "BUILD_RTI=${BUILD_RTI}" -log_group "Build Group 1 (ddscore ddsftccore ddsQoS ddsconnector ddsfts)" "$BUILD_GROUP1" -log_group "Build Group 2 (migration_tests)" "$BUILD_GROUP2" -log_group "Build Group 3 (application + service targets)" "$BUILD_GROUP3" -log_group "Build Group 4 (DDS tests + Proxies)" "$BUILD_GROUP4" -log_group "Build Group 5 (Viewer)" "$BUILD_GROUP5" -log_group "Build Group 6 (LTS Tools)" "$BUILD_GROUP6" -log_group "Build Group 7 (LTS Tools A,B,C,E,I)" "$BUILD_GROUP7" -log_group "Build Group 8 (LTS Tools J,M,N,P,Q)" "$BUILD_GROUP8" -log_group "Build Group 9 (LTS Tools R,S,T,V,W)" "$BUILD_GROUP9" -log_group "Build Group 10 (LTS Projects)" "$BUILD_GROUP10" -log_group "Build Group 11 (LTS Application)" "$BUILD_GROUP11" -log_group "Build Group 12 (GUI/Data Plugins)" "$BUILD_GROUP12" -log_info "BUILD_VIEWER_ONLY=${BUILD_VIEWER_ONLY}" -log_info "RUN_CTEST=${RUN_CTEST}" -log_info "TESTS_ONLY=${TESTS_ONLY}" -log_info "INTEGRATION_TEST=${INTEGRATION_TEST}" -log_info "USE_PREBUILT_IMAGE=${USE_PREBUILT_IMAGE}" -log_info "BUILD_PREBUILT_IMAGE=${BUILD_PREBUILT_IMAGE}" -log_info "DELETE_PREBUILT_IMAGE=${DELETE_PREBUILT_IMAGE}" -log_info "DOCKER_IMAGE=${DOCKER_IMAGE}" -log_info "MIGRATE_PIPELINE_ROOT=${MIGRATE_PIPELINE_ROOT}" -log_info "RTI_LICENSE_FILE_HOST=${RTI_LICENSE_FILE_HOST}" -log_info "PROJECT_DIR_HOST=${PROJECT_DIR_HOST}" - -if [[ "${BUILD_PREBUILT_IMAGE}" == "ON" ]]; then - build_prebuilt_image "${DOCKER_IMAGE}" - - if [[ "${USE_PREBUILT_IMAGE}" != "ON" ]]; then - log_info "Prebuilt image was built successfully." - log_info "Exiting because --use-prebuilt-image was not requested." - log_info "To use it, run:" - printf ' ./new_docker_build.sh --use-prebuilt-image --docker-image %q\n' "${DOCKER_IMAGE}" - exit 0 - fi - - log_info "Continuing with freshly built prebuilt image: ${DOCKER_IMAGE}" -fi - -GROUP1_TARGETS_STRING="$(join_by ' ' "${GROUP1_TARGETS[@]}")" -GROUP2_TARGETS_STRING="$(join_by ' ' "${GROUP2_TARGETS[@]}")" -GROUP3_TARGETS_STRING="$(join_by ' ' "${GROUP3_TARGETS[@]}")" -GROUP4_TARGETS_STRING="$(join_by ' ' "${GROUP4_TARGETS[@]}")" -GROUP5_TARGETS_STRING="$(join_by ' ' "${GROUP5_TARGETS[@]}")" -GROUP6_TARGETS_STRING="$(join_by ' ' "${GROUP6_TARGETS[@]}")" -GROUP7_TARGETS_STRING="$(join_by ' ' "${GROUP7_TARGETS[@]}")" -GROUP8_TARGETS_STRING="$(join_by ' ' "${GROUP8_TARGETS[@]}")" -GROUP9_TARGETS_STRING="$(join_by ' ' "${GROUP9_TARGETS[@]}")" -GROUP10_TARGETS_STRING="$(join_by ' ' "${GROUP10_TARGETS[@]}")" -GROUP11_TARGETS_STRING="$(join_by ' ' "${GROUP11_TARGETS[@]}")" -GROUP12_TARGETS_STRING="$(join_by ' ' "${GROUP12_TARGETS[@]}")" - -HOST_TEMP_DIR="$(mktemp -d)" -CONTAINER_SCRIPT_HOST="${HOST_TEMP_DIR}/run-build-inside-container.sh" -cleanup_all() { - cleanup_temp_dir "${HOST_TEMP_DIR}" -} -trap cleanup_all EXIT - -cat > "${CONTAINER_SCRIPT_HOST}" <<'EOF' -#!/usr/bin/env bash -set -euo pipefail - -# Default variable assignments to prevent unbound variable errors -USE_PREBUILT_IMAGE="${USE_PREBUILT_IMAGE:-OFF}" -BUILD_ALL="${BUILD_ALL:-ON}" -BUILD_SV="${BUILD_SV:-ON}" -BUILD_WS="${BUILD_WS:-ON}" -BUILD_AAR="${BUILD_AAR:-ON}" -BUILD_RTI="${BUILD_RTI:-ON}" -BUILD_GRANTLEE="${BUILD_GRANTLEE:-ON}" -BUILD_ARCGIS="${BUILD_ARCGIS:-OFF}" -BUILD_GROUP1="${BUILD_GROUP1:-ON}" -BUILD_GROUP2="${BUILD_GROUP2:-ON}" -BUILD_GROUP3="${BUILD_GROUP3:-ON}" -BUILD_GROUP4="${BUILD_GROUP4:-ON}" -BUILD_GROUP5="${BUILD_GROUP5:-ON}" -BUILD_GROUP6="${BUILD_GROUP6:-ON}" -BUILD_GROUP7="${BUILD_GROUP7:-ON}" -BUILD_GROUP8="${BUILD_GROUP8:-ON}" -BUILD_GROUP9="${BUILD_GROUP9:-ON}" -BUILD_GROUP10="${BUILD_GROUP10:-ON}" -BUILD_GROUP11="${BUILD_GROUP11:-ON}" -BUILD_GROUP12="${BUILD_GROUP12:-ON}" -BUILD_VIEWER_ONLY="${BUILD_VIEWER_ONLY:-OFF}" -RUN_CTEST="${RUN_CTEST:-ON}" -TESTS_ONLY="${TESTS_ONLY:-OFF}" -INTEGRATION_TEST="${INTEGRATION_TEST:-OFF}" -APT_PACKAGES_STRING="${APT_PACKAGES_STRING:-}" - -log_info() { - printf 'INFO: %s\n' "$*" -} - -install_qt6_packages() { - log_info "Installing Qt6 packages via aqtinstall" - - # Install aqtinstall if not available - if ! command -v aqt &> /dev/null; then - log_info "Installing aqtinstall via pip3" - pip3 install --break-system-packages --quiet aqtinstall - fi - - # Install Qt6 modules (same as app/Dockerfile) - # Modules: qtmultimedia, qtserialport, qtimageformats, qtwebsockets, qtwebengine, - # qtpdf, qtwebview, qt5compat, qtwebchannel, qtpositioning, qtlocation, qtsensors - # Note: qtsvg is NOT available via aqtinstall - it's provided by libqt6svg6-dev apt package - aqt install-qt linux desktop "${QT_VERSION:-6.10.2}" "${QT_ARCH:-linux_gcc_64}" \ - -m qtmultimedia qtserialport qtimageformats qtwebsockets qtwebengine \ - qtpdf qtwebview qt5compat qtwebchannel qtpositioning qtlocation qtsensors \ - --outputdir "${QT_BASE_DIR:-/opt/Qt}" - - log_info "Qt6 packages installed successfully" -} - -run_build_group() { - local group_id="$1" - local enabled="$2" - local log_file="$3" - shift 3 - local targets=("$@") - - if [[ "${enabled}" == "ON" ]]; then - log_info "Building ${group_id}: ${targets[*]}" - # Use || true to continue if optional targets (e.g., svcWirelessLocationSystem) are not configured - make -j10 "${targets[@]}" 2>&1 | tee "${log_file}" || true - else - log_info "Skipping ${group_id}" - fi -} - -# Ensure a local PostgreSQL DB is available for the DB tools (dbUpdate, dbAdministration, ...). -# Checks whether the server is pre-installed (baked into the image); if not, installs -# postgresql-18. Then maps EXCDBS01/EXCADB01 -> 127.0.0.1 and starts the cluster, seeding -# the roles (postgres, ctc_sv) + databases (lts_ets_pro, dbAdmin) the tools connect with. -# Entirely non-fatal: a DB problem must never abort the build. -ensure_database() { - log_info "Checking for a pre-installed PostgreSQL server..." - if ls /usr/lib/postgresql/*/bin/postgres >/dev/null 2>&1; then - log_info "PostgreSQL server already installed - skipping apt install" - else - log_info "PostgreSQL server not found - installing postgresql-18" - apt-get update -qq || true - DEBIAN_FRONTEND=noninteractive apt-get install -y -qq postgresql-18 >/dev/null 2>&1 || true - fi - - # Map the app's DB hostnames to the local server + start the cluster (idempotent). - grep -qE 'EXCDBS01' /etc/hosts || echo '127.0.0.1 EXCDBS01 EXCADB01' >> /etc/hosts - pg_ctlcluster 18 main start >/dev/null 2>&1 || true - sleep 1 - - # Ensure the roles + databases the DB tools use (idempotent; login password is 'postgres'). - su postgres -c "psql -c \"ALTER USER postgres PASSWORD 'postgres'\"" >/dev/null 2>&1 || true - if ! su postgres -c "psql -tAc \"SELECT 1 FROM pg_roles WHERE rolname='ctc_sv'\"" 2>/dev/null | grep -q 1; then - su postgres -c "psql -c \"CREATE ROLE ctc_sv LOGIN PASSWORD 'postgres' CREATEDB\"" >/dev/null 2>&1 || true - fi - if ! su postgres -c "psql -tAc \"SELECT 1 FROM pg_database WHERE datname='lts_ets_pro'\"" 2>/dev/null | grep -q 1; then - su postgres -c "createdb -O postgres lts_ets_pro" >/dev/null 2>&1 || true - fi - if ! su postgres -c "psql -tAc \"SELECT 1 FROM pg_database WHERE datname='dbAdmin'\"" 2>/dev/null | grep -q 1; then - su postgres -c "createdb -O postgres dbAdmin" >/dev/null 2>&1 || true - fi - - if pg_isready -h 127.0.0.1 -p 5432 >/dev/null 2>&1; then - log_info "PostgreSQL ready on 127.0.0.1:5432 (roles postgres/ctc_sv, dbs lts_ets_pro/dbAdmin)" - else - log_info "WARNING: PostgreSQL not ready on 127.0.0.1:5432 (DB tools may not connect; install may have failed)" - fi -} - -if [[ "${USE_PREBUILT_IMAGE}" == "ON" ]]; then - log_info "Using prebuilt Docker image - skipping apt-get install and Qt6 package installation" -else - log_info "Using base image - installing apt packages" - apt-get update -qq - # shellcheck disable=SC2086 - apt-get install -y -qq ${APT_PACKAGES_STRING} > /dev/null 2>&1 - - # Install Qt6 packages via aqtinstall for non-prebuilt-image builds - install_qt6_packages -fi - -# Ensure the local PostgreSQL DB (dbUpdate / dbAdministration, ...) is available before the build. -ensure_database - -export RTI_LICENSE_FILE=${DOCKER_MOUNT_ROOT}/rti_license.dat -export DDS_PATH=${DOCKER_MOUNT_ROOT}/external/rti_connext_dds-7.7.0 -export QT_QPA_PLATFORM=offscreen - -# Setup ArcGIS SDK if enabled -if [[ "${BUILD_ARCGIS}" == "ON" ]]; then - log_info "Setting up ArcGIS SDK" - if [[ -f "${DOCKER_MOUNT_ROOT}/qt-migration-legatus/qt6-after/qt6-migrated-legatus/install_arcgis.sh" ]]; then - bash ${DOCKER_MOUNT_ROOT}/qt-migration-legatus/qt6-after/qt6-migrated-legatus/install_arcgis.sh - else - log_info "install_arcgis.sh not found, skipping ArcGIS SDK setup" - fi -fi - -cd ${DOCKER_MOUNT_ROOT}/qt-migration-legatus/qt6-after/qt6-migrated-legatus - -# Clean build directory (running as root inside container) -# Use find to handle permission issues from previous runs with different UID -if [ -d build4 ]; then - rm -rf build4 -fi -mkdir -p build4 -cd build4 - -cmake .. \ - -DBUILD_TESTING=ON \ - -DBUILD_SITMAP_UNIT_TESTS=ON \ - -DBUILD_ALL="${BUILD_ALL}" \ - -DBUILD_SV="${BUILD_SV}" \ - -DBUILD_WS="${BUILD_WS}" \ - -DBUILD_AAR="${BUILD_AAR}" \ - -DBUILD_RTI="${BUILD_RTI}" \ - -DBUILD_VIEWER_ONLY="${BUILD_VIEWER_ONLY}" \ - -DBUILD_GRANTLEE="${BUILD_GRANTLEE}" \ - -DBUILD_ARCGIS="${BUILD_ARCGIS}" \ - -DBUILD_CODIFICATION="${BUILD_CODIFICATION}" \ - ${CMAKE_BUILD_FLAGS:-} \ - -DCMAKE_CXX_DEPENDENCIES_USE_COMPILER=OFF \ - -DCMAKE_CXX_STANDARD=17 \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo \ - -DRTI_DIR=${DOCKER_MOUNT_ROOT}/external/rti_connext_dds-7.7.0 \ - -DCMAKE_PREFIX_PATH="${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR}${BUILD_ARCGIS:+;${DOCKER_MOUNT_ROOT}/qt-migration-legatus/qt6-after/qt6-migrated-legatus/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk};/usr/local" - -read -r -a GROUP1_ARRAY <<< "${GROUP1_TARGETS}" -read -r -a GROUP2_ARRAY <<< "${GROUP2_TARGETS}" -read -r -a GROUP3_ARRAY <<< "${GROUP3_TARGETS}" -read -r -a GROUP4_ARRAY <<< "${GROUP4_TARGETS}" -read -r -a GROUP5_ARRAY <<< "${GROUP5_TARGETS}" -read -r -a GROUP6_ARRAY <<< "${GROUP6_TARGETS}" -read -r -a GROUP7_ARRAY <<< "${GROUP7_TARGETS}" -read -r -a GROUP8_ARRAY <<< "${GROUP8_TARGETS}" -read -r -a GROUP9_ARRAY <<< "${GROUP9_TARGETS}" -read -r -a GROUP10_ARRAY <<< "${GROUP10_TARGETS}" -read -r -a GROUP11_ARRAY <<< "${GROUP11_TARGETS}" -read -r -a GROUP12_ARRAY <<< "${GROUP12_TARGETS}" - -if [[ "${TESTS_ONLY}" != "ON" ]]; then - if [[ "${BUILD_VIEWER_ONLY}" == "ON" ]]; then - log_info "BUILD_VIEWER_ONLY enabled - skipping Groups 1-4, building only Viewer module targets" - BUILD_GROUP1=OFF - BUILD_GROUP2=OFF - BUILD_GROUP3=OFF - BUILD_GROUP4=OFF - BUILD_GROUP5=ON - fi - run_build_group "Group 1" "${BUILD_GROUP1}" "group1_build.log" "${GROUP1_ARRAY[@]}" - run_build_group "Group 4 (DDS tests + Proxies)" "${BUILD_GROUP4}" "group4_build.log" "${GROUP4_ARRAY[@]}" - run_build_group "Group 2" "${BUILD_GROUP2}" "group2_build.log" "${GROUP2_ARRAY[@]}" - run_build_group "Group 3" "${BUILD_GROUP3}" "group3_build.log" "${GROUP3_ARRAY[@]}" - run_build_group "Group 5 (Viewer)" "${BUILD_GROUP5}" "group5_build.log" "${GROUP5_ARRAY[@]}" - run_build_group "Group 6 (LTS Tools)" "${BUILD_GROUP6}" "group6_build.log" "${GROUP6_ARRAY[@]}" - run_build_group "Group 7 (LTS Tools A,B,C,E,I)" "${BUILD_GROUP7}" "group7_build.log" "${GROUP7_ARRAY[@]}" - run_build_group "Group 8 (LTS Tools J,M,N,P,Q)" "${BUILD_GROUP8}" "group8_build.log" "${GROUP8_ARRAY[@]}" - run_build_group "Group 9 (LTS Tools R,S,T,V,W)" "${BUILD_GROUP9}" "group9_build.log" "${GROUP9_ARRAY[@]}" - run_build_group "Group 10 (LTS Projects)" "${BUILD_GROUP10}" "group10_build.log" "${GROUP10_ARRAY[@]}" - run_build_group "Group 12 (GUI/Data Plugins)" "${BUILD_GROUP12}" "group12_build.log" "${GROUP12_ARRAY[@]}" - run_build_group "Group 11 (LTS Application)" "${BUILD_GROUP11}" "group11_build.log" "${GROUP11_ARRAY[@]}" -else - log_info "TESTS_ONLY enabled - skipping all build groups" -fi - -if [[ "${RUN_CTEST}" == "ON" ]]; then - if [[ "${INTEGRATION_TEST}" == "ON" ]]; then - log_info "Running integration tests (Z-module + Proxies)" - ctest --test-dir . --output-on-failure -R "(test_z_|bld_|tab_|wls_)" - else - log_info "Running CTest" - ctest --test-dir . --output-on-failure - fi -else - log_info "Skipping CTest" -fi -EOF - -chmod +x "${CONTAINER_SCRIPT_HOST}" - -docker run --rm \ - -e MIGRATE_PIPELINE_ROOT \ - -e LANG \ - -e LC_ALL \ - -e BUILD_ALL \ - -e BUILD_SV \ - -e BUILD_WS \ - -e BUILD_AAR \ - -e BUILD_RTI \ - -e BUILD_GRANTLEE \ - -e BUILD_ARCGIS \ - -e BUILD_CODIFICATION \ - -e BUILD_GROUP1 \ - -e BUILD_GROUP2 \ - -e BUILD_GROUP3 \ - -e BUILD_GROUP4 \ - -e BUILD_GROUP5 \ - -e BUILD_GROUP6 \ - -e BUILD_GROUP7 \ - -e BUILD_GROUP8 \ - -e BUILD_GROUP9 \ - -e BUILD_GROUP10 \ - -e BUILD_GROUP11 \ - -e BUILD_GROUP12 \ - -e BUILD_VIEWER_ONLY \ - -e RUN_CTEST \ - -e TESTS_ONLY \ - -e INTEGRATION_TEST \ - -e USE_PREBUILT_IMAGE \ - -e CMAKE_BUILD_FLAGS \ - -e QT_VERSION \ - -e QT_ARCH \ - -e QT_ARCH_DIR \ - -e QT_BASE_DIR \ - -e DDS_PATH \ - -e RTI_LICENSE_FILE \ - -e APT_PACKAGES_STRING="${APT_PACKAGES_STRING}" \ - -e GROUP1_TARGETS="${GROUP1_TARGETS_STRING}" \ - -e GROUP2_TARGETS="${GROUP2_TARGETS_STRING}" \ - -e GROUP3_TARGETS="${GROUP3_TARGETS_STRING}" \ - -e GROUP4_TARGETS="${GROUP4_TARGETS_STRING}" \ - -e GROUP5_TARGETS="${GROUP5_TARGETS_STRING}" \ - -e GROUP6_TARGETS="${GROUP6_TARGETS_STRING}" \ - -e GROUP7_TARGETS="${GROUP7_TARGETS_STRING}" \ - -e GROUP8_TARGETS="${GROUP8_TARGETS_STRING}" \ - -e GROUP9_TARGETS="${GROUP9_TARGETS_STRING}" \ - -e GROUP10_TARGETS="${GROUP10_TARGETS_STRING}" \ - -e GROUP11_TARGETS="${GROUP11_TARGETS_STRING}" \ - -e GROUP12_TARGETS="${GROUP12_TARGETS_STRING}" \ - -e DOCKER_MOUNT_ROOT="${DOCKER_MOUNT_ROOT}" \ - -v "${WORKSPACE_ROOT_HOST}:${DOCKER_MOUNT_ROOT}" \ - -v "${RTI_LICENSE_FILE_HOST}:${DOCKER_MOUNT_ROOT}/rti_license.dat" \ - -v "${MIGRATE_PIPELINE_ROOT}/external:${DOCKER_MOUNT_ROOT}/external:ro" \ - -v "${CONTAINER_SCRIPT_HOST}:/tmp/run-build-inside-container.sh:ro" \ - "${DOCKER_IMAGE}" \ - bash /tmp/run-build-inside-container.sh diff --git a/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh b/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh index 68fdc7867..9f4cf286a 100755 --- a/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh +++ b/qt6-after/qt6-migrated-legatus/new_docker_build_release2.sh @@ -9,7 +9,8 @@ set -euo pipefail # - AP4: DDS middleware (Core, DDSConnector, Routing, QosProfile, RTI layer) # - AP9: Tools and translations (DdsView, LogViewer, SqlBrowser, generators, lupdate) # -# This script is derived from new_docker_build.sh but focused on Release 2 targets only. +# This is the Release 2 scope driver (the full-tree driver of the earlier +# validation scope has been removed from this branch). # ----------------------------------------------------------------------------- usage() { @@ -35,7 +36,7 @@ Prebuilt Docker image usage: Package production options (DEB): --run-jenkins-builder Build the release DEB packages inside the container - using the in-tree rpmbuild/make_rpm_ubuntu26.py + using the in-tree rpmbuild/make_rpm_ubuntu26_release2.py --package-output-dir DIR Directory to mount for package output (default: ./packages-out) --lts-version VERSION LTS version for package (default: 1.0) --project NAME Project name for package (default: guez) diff --git a/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26.py b/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26.py deleted file mode 100644 index 562960818..000000000 --- a/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26.py +++ /dev/null @@ -1,527 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -""" -DEB package builder for Ubuntu 26.04 - Qt6 Release -Creates 5 separate DEB packages as per customer requirements: -1. qt6-release-runtime - binaries and libraries from S -2. qt6-release-sources - Qt6 C++ sources from S -3. qt6-release-ctest-runtime - CTest executables -4. qt6-release-ctest-sources - CTest source files -5. qt6-release-build-pipeline - Dockerfiles, build scripts, CI/CD files -""" - -import argparse -import fnmatch -import os -import shutil -import subprocess -import sys -from email.utils import formatdate - -SKIP_DIRS = {'build', 'cmake-build-debug', 'cmake-build-release', 'deb_build_tmp'} -SOURCE_EXTENSIONS = ('.cpp', '.h', '.hpp', '.cc', '.cxx', '.hxx') -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", - "rpmbuild/make_rpm_ubuntu26.py", - "CMakeLists.txt", -] - - -def verbose(): - verb = os.getenv("EMERGE_VERBOSE") - if verb is not None and verb.isdigit() and int(verb) > 0: - return int(verb) - return 0 - - -def debug(message): - if verbose() >= 1: - print(f"debug: {message}") - return True - - -def info(message): - print(f"info: {message}") - return True - - -def warning(message): - print(f"warning: {message}") - return True - - -def error(message): - die(message) - - -def die(message): - print(f"emerge fatal error: {message}", file=sys.stderr) - sys.exit(1) - - -def run(cmd, label, env=None): - """Run a shell command, print its output and die on failure.""" - debug(f"Executing: {cmd}") - ret = subprocess.run(cmd, shell=True, env=env, capture_output=True, text=True) - if ret.returncode != 0: - print(ret.stdout) - print(ret.stderr) - die(f"{label} with code {ret.returncode}") - - -def remove_directory(path): - if os.path.exists(path): - shutil.rmtree(path) - - -def is_dds_file(filepath): - """True if the path is DDS-related and must be excluded.""" - return 'dds' in filepath.lower() - - -def prune_dirs(dirs, root, file_filter): - """Prune hidden/build dirs in-place (and dirs matching file_filter).""" - dirs[:] = [d for d in dirs - if not d.startswith('.') - and d not in SKIP_DIRS - and (file_filter is None or not file_filter(os.path.join(root, d)))] - - -def copy_src_dir_to_dest_dir(src_dir, dest_dir, file_filter=None): - """Copy the source tree, skipping hidden/build dirs and filtered files.""" - os.makedirs(dest_dir, exist_ok=True) - for root, dirs, files in os.walk(src_dir): - prune_dirs(dirs, root, file_filter) - for file in files: - src_file = os.path.join(root, file) - if file_filter and file_filter(src_file): - continue - dest_file = os.path.join(dest_dir, os.path.relpath(src_file, src_dir)) - os.makedirs(os.path.dirname(dest_file), exist_ok=True) - shutil.copy2(src_file, dest_file) - - -def find_test_module_source(pkg_dir, test_name, release_dirs): - """Module dir (relative to pkg_dir) whose CMakeLists defines test_name, or None.""" - for rel_dir in release_dirs: - module_dir = os.path.join(pkg_dir, rel_dir) - if not os.path.exists(module_dir): - continue - for root, dirs, files in os.walk(module_dir): - prune_dirs(dirs, root, None) - if 'CMakeLists.txt' not in files: - continue - try: - with open(os.path.join(root, 'CMakeLists.txt')) as f: - content = f.read() - except Exception: - continue - if f'ADD_EXECUTABLE({test_name}' in content or f'ADD_TEST(NAME {test_name}' in content: - return os.path.relpath(root, pkg_dir) - return None - - -def find_test_executables(pkg_dir, release_dirs): - """(executable, module) pairs for the test executables in build4/bin/.""" - test_executables = [] - build_bin_dir = os.path.join(pkg_dir, "build4", "bin") - if not os.path.exists(build_bin_dir): - warning(f"Build bin directory not found: {build_bin_dir}") - return test_executables - for filename in os.listdir(build_bin_dir): - file_path = os.path.join(build_bin_dir, filename) - if not (os.path.isfile(file_path) and os.access(file_path, os.X_OK)): - continue - if 'test' not in filename.lower(): - continue - module_path = find_test_module_source(pkg_dir, filename, release_dirs) - if module_path: - test_executables.append((file_path, module_path)) - debug(f" Found test executable: {filename} from {module_path}") - else: - debug(f" Skipping test executable (no module found): {filename}") - return test_executables - - -def find_test_sources(pkg_dir, release_dirs): - """Relative paths of test source files (name containing 'test', .cpp/.h).""" - test_sources = [] - for rel_dir in release_dirs: - module_dir = os.path.join(pkg_dir, rel_dir) - if not os.path.exists(module_dir): - continue - for root, dirs, files in os.walk(module_dir): - prune_dirs(dirs, root, None) - for filename in files: - if 'test' in filename.lower() and filename.endswith(('.cpp', '.h')): - file_path = os.path.join(root, filename) - rel_path = os.path.relpath(file_path, pkg_dir) - test_sources.append(rel_path) - debug(f" Found test source: {rel_path}") - return test_sources - - -def write_deb_file(deb_dir, name, content, executable=False): - """Write a debian/* file and log its creation.""" - path = os.path.join(deb_dir, name) - with open(path, "w") as f: - f.write(content) - if executable: - os.chmod(path, 0o755) - info(f"Created {path}") - - -def create_debian_control(deb_dir, package_name, version, build_number, description, - depends="", section="devel"): - write_deb_file(deb_dir, "control", f"""Source: {package_name} -Section: {section} -Priority: optional -Maintainer: Legatus Team -Build-Depends: debhelper (>= 13), cmake, qt6-base-dev, qt6-tools-dev -Standards-Version: 4.6.0 - -Package: {package_name} -Architecture: any -Depends: ${{shlibs:Depends}}, ${{misc:Depends}}{", " + depends if depends else ""} -Description: {description} - Legatus Qt6 Release Package - This package is part of the Legatus Qt6 migration release. -""") - - -def create_debian_changelog(deb_dir, package_name, version, build_number): - write_deb_file(deb_dir, "changelog", f"""{package_name} ({version}-{build_number}) unstable; urgency=medium - - * Qt6 Release Build - - -- Legatus Team {formatdate(localtime=True)} -""") - - -def create_debian_rules(deb_dir, cmake_flags="", skip_tests=False): - test_override = """ -override_dh_auto_test: - # Tests skipped for this package type -""" if skip_tests else "" - write_deb_file(deb_dir, "rules", f"""#!/usr/bin/make -f -%: - dh $@ --buildsystem=cmake - -override_dh_auto_configure: - dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release {cmake_flags} - -override_dh_auto_build: - dh_auto_build --parallel - -override_dh_auto_install: - dh_auto_install --destdir=debian/tmp -{test_override}""", executable=True) - - -def create_debian_rules_nobuild(deb_dir, skip_shlibdeps=False): - content = """#!/usr/bin/make -f -%: - dh $@ - -override_dh_auto_build: - # No build step needed - pre-built files only - -override_dh_auto_configure: - # No configure step needed - pre-built files only - -override_dh_auto_install: - dh_auto_install -""" - if skip_shlibdeps: - content += """ -override_dh_shlibdeps: - # Skip shlibdeps for test executables - Qt6 deps are external system packages -""" - write_deb_file(deb_dir, "rules", content, executable=True) - - -def create_debian_install(deb_dir, install_lines): - install_file = os.path.join(deb_dir, "install") - with open(install_file, "w") as f: - for line in install_lines: - f.write(line + "\n") - info(f"Created {install_file} with {len(install_lines)} entries") - - -def create_manifest(output_dir, package_name, pkg_dir): - """Write the manifest of package contents (from the DEB, or the pkg dir).""" - manifest_file = os.path.join(output_dir, "manifests", f"{package_name}.manifest") - os.makedirs(os.path.dirname(manifest_file), exist_ok=True) - deb_file = next((os.path.join(output_dir, f) for f in os.listdir(output_dir) - if f.startswith(package_name) and f.endswith(".deb")), None) - manifest_lines = [] - if deb_file and os.path.exists(deb_file): - result = subprocess.run(["dpkg-deb", "--contents", deb_file], - capture_output=True, text=True) - if result.returncode == 0: - # dpkg-deb --contents: "-rw-r--r-- root/root 1234 2024-01-01 00:00 ./path" - for line in result.stdout.strip().split("\n"): - parts = line.split() - if len(parts) >= 6: - file_path = parts[-1] - if file_path.startswith("./"): - file_path = file_path[2:] - elif file_path.startswith("/"): - file_path = file_path[1:] - if file_path: - manifest_lines.append(file_path) - elif os.path.exists(pkg_dir): - info(f"Warning: DEB file not found for {package_name}, scanning directory instead") - for root, dirs, files in os.walk(pkg_dir): - for file in files: - manifest_lines.append(os.path.relpath(os.path.join(root, file), pkg_dir)) - manifest_lines.sort() - with open(manifest_file, "w") as f: - for line in manifest_lines: - f.write(line + "\n") - info(f"Created manifest: {manifest_file} ({len(manifest_lines)} entries)") - return manifest_lines - - -def validate_package_contents(package_name, manifest_lines, allowed_patterns, forbidden_patterns=None): - """Validate package contents against the allowlist/forbidden list.""" - errors = [] - warnings = [] - for file_path in manifest_lines: - if file_path.endswith('/'): - continue - if forbidden_patterns: - for pattern in forbidden_patterns: - if fnmatch.fnmatch(file_path, pattern): - errors.append(f"FORBIDDEN file in {package_name}: {file_path} (matches {pattern})") - allowed = bool(allowed_patterns) and any(fnmatch.fnmatch(file_path, p) for p in allowed_patterns) - if not allowed and allowed_patterns: - warnings.append(f"Unexpected file in {package_name}: {file_path}") - for err in errors: - error(f"Validation error: {err}") - if errors: - return False - for warn in warnings: - warning(f"Validation warning: {warn}") - return True - - -def build_deb(pkg_name, pkg_dir, output_dir, version, build_number, - cmake_flags="", nobuild=False, skip_tests=False, skip_shlibdeps=False, - install_lines=None, description="", section="devel", depends=""): - """Build one DEB package (with or without a cmake build) and move its artifacts.""" - info(f"Building DEB package {'(no-build): ' if nobuild else ''}{pkg_name}") - deb_dir = os.path.join(pkg_dir, "debian") - os.makedirs(deb_dir) - create_debian_control(deb_dir, pkg_name, version, build_number, description, depends, section) - create_debian_changelog(deb_dir, pkg_name, version, build_number) - if nobuild: - create_debian_rules_nobuild(deb_dir, skip_shlibdeps=skip_shlibdeps) - else: - create_debian_rules(deb_dir, cmake_flags, skip_tests) - os.makedirs(os.path.join(deb_dir, "source")) - with open(os.path.join(deb_dir, "source", "format"), "w") as f: - f.write("3.0 (quilt)\n") - with open(os.path.join(deb_dir, "compat"), "w") as f: - f.write("13\n") - if install_lines: - create_debian_install(deb_dir, install_lines) - - info(f"Running debuild for {pkg_name}...") - os.chdir(pkg_dir) - env = os.environ.copy() - env["DEB_BUILD_OPTIONS"] = "parallel=$(nproc)" - run("debuild -us -uc -b", f"debuild failed for {pkg_name}", env=env) - - parent_dir = os.path.dirname(pkg_dir) - for f in os.listdir(parent_dir): - if f.endswith((".deb", ".dsc", ".changes", ".buildinfo")): - src = os.path.join(parent_dir, f) - dst = os.path.join(output_dir, f) - if os.path.exists(dst): - os.remove(dst) - shutil.move(src, output_dir) - info(f"Moved {f} to {output_dir}") - return True - - -def source_install_lines(pkg_dir, release_dirs): - lines = [] - for rel_dir in release_dirs: - src_dir = os.path.join(pkg_dir, rel_dir) - if not os.path.exists(src_dir): - continue - for root, dirs, files in os.walk(src_dir): - dirs[:] = [d for d in dirs if not d.startswith('.')] - for file in files: - if os.path.splitext(file)[1].lower() in SOURCE_EXTENSIONS or file == "CMakeLists.txt": - rel_path = os.path.relpath(os.path.join(root, file), pkg_dir) - lines.append(f"{rel_path} {os.path.join('usr/src', os.path.dirname(rel_path))}/") - return lines - - -def ctest_runtime_install_lines(pkg_dir, release_dirs): - lines = [] - for exe_path, module_path in find_test_executables(pkg_dir, release_dirs): - lines.append(f"{os.path.relpath(exe_path, pkg_dir)} usr/lib/ctest/") - info(f" Including test executable: {os.path.basename(exe_path)} from {module_path}") - for ctest_file in ("build4/CTestTestfile.cmake", "build4/DartConfiguration.tcl", "build4/Testing/TAG"): - if os.path.exists(os.path.join(pkg_dir, ctest_file)): - lines.append(f"{ctest_file} usr/lib/ctest/") - return lines - - -def test_sources_install_lines(pkg_dir, release_dirs): - return [f"{rel_path} {os.path.dirname(rel_path)}/" for rel_path in find_test_sources(pkg_dir, release_dirs)] - - -def pipeline_install_lines(pkg_dir): - lines = [] - for pipeline_file in PIPELINE_FILES: - if os.path.exists(os.path.join(pkg_dir, pipeline_file)): - lines.append(f"{pipeline_file} {os.path.join('usr/src/pipeline', os.path.dirname(pipeline_file))}/") - info(f" Added pipeline file: {pipeline_file}") - return lines - - -def build_nobuild_package(name, source_dir, build_base, output_dir, version, build_number, - description, prepare, allowed_patterns, forbidden_patterns, - file_filter=None, skip_shlibdeps=False, section="devel"): - """Stage the source tree, build a no-build DEB and validate its contents.""" - info(f"\n=== Building {name} ===") - pkg_dir = os.path.join(build_base, f"{name}-{version}") - os.makedirs(pkg_dir) - copy_src_dir_to_dest_dir(source_dir, pkg_dir, file_filter=file_filter) - build_deb(pkg_name=name, pkg_dir=pkg_dir, output_dir=output_dir, - version=version, build_number=build_number, nobuild=True, - skip_shlibdeps=skip_shlibdeps, install_lines=prepare(pkg_dir), - description=description, section=section) - manifest = create_manifest(output_dir, name, pkg_dir) - validate_package_contents(name, manifest, allowed_patterns, forbidden_patterns) - - -def build_all_debs(source_dir, output_dir, version, build_number, cmake_flags): - """Build the 5 DEB packages: build once from the source tree, then package.""" - info("========================================") - info("Building 5 DEB packages for Qt6 Release") - info("========================================") - os.makedirs(output_dir, exist_ok=True) - os.makedirs(os.path.join(output_dir, "manifests"), exist_ok=True) - build_base = os.path.join(source_dir, "deb_build_tmp") - remove_directory(build_base) - os.makedirs(build_base) - release_dirs = ["TetraIF", "Z/src", "Lts/Common"] - - # Step 1: build once from the full source tree - info("\n=== Step 1: Building from full source tree ===") - build_dir = os.path.join(source_dir, "build") - os.makedirs(build_dir, exist_ok=True) - os.chdir(build_dir) - info("Running CMake configuration...") - run(f"cmake -DCMAKE_BUILD_TYPE=Release {cmake_flags} ..", "CMake configuration failed") - info("Running build...") - run(f"make -j$(nproc)", "Build failed") - info("Build completed successfully") - - # Package 1: qt6-release-runtime (binaries and libraries, built via debuild) - info("\n=== Building qt6-release-runtime ===") - pkg1_dir = os.path.join(build_base, f"qt6-release-runtime-{version}") - os.makedirs(pkg1_dir) - # FULL source tree (needed for debian/rules cmake reference) - copy_src_dir_to_dest_dir(source_dir, pkg1_dir) - # Install from all component install paths: ALL -> bin/, lib/ ; SV/ ; WS/ - install_lines_1 = [ - "usr/bin/* usr/bin/", - "usr/lib/*.so* usr/lib/", - "usr/SV/bin/* usr/bin/", - "usr/SV/lib/*.so* usr/lib/", - "usr/WS/bin/* usr/bin/", - "usr/WS/lib/*.so* usr/lib/", - ] - build_deb(pkg_name="qt6-release-runtime", pkg_dir=pkg1_dir, output_dir=output_dir, - version=version, build_number=build_number, cmake_flags=cmake_flags, - skip_tests=True, install_lines=install_lines_1, - description="Qt6 Release Runtime - binaries and libraries from release scope S", - section="libs") - manifest_1 = create_manifest(output_dir, "qt6-release-runtime", pkg1_dir) - validate_package_contents("qt6-release-runtime", manifest_1, - allowed_patterns=["usr/bin/*", "usr/lib/*", "usr/SV/*", "usr/WS/*", "usr/share/doc/*", "debian/*"], - forbidden_patterns=["*.cpp", "*.h", "*.hpp", "tests/*", "jenkins/*", "Dockerfile*"]) - - # Package 2: qt6-release-sources (release-scope sources, DDS excluded) - build_nobuild_package( - "qt6-release-sources", source_dir, build_base, output_dir, version, build_number, - description="Qt6 Release Sources - C++ source files from release scope S", - prepare=lambda pkg_dir: source_install_lines(pkg_dir, release_dirs), - allowed_patterns=["usr/src/*", "usr/share/doc/*", "debian/*"], - forbidden_patterns=["build/*", "tests/*", "jenkins/*"], - file_filter=is_dds_file) - - # Package 3: qt6-release-ctest-runtime (test executables from release scope) - build_nobuild_package( - "qt6-release-ctest-runtime", source_dir, build_base, output_dir, version, build_number, - description="Qt6 Release CTest Runtime - executable test programs from release scope", - prepare=lambda pkg_dir: ctest_runtime_install_lines(pkg_dir, release_dirs), - allowed_patterns=["usr/lib/ctest/*", "usr/share/doc/*", "debian/*"], - forbidden_patterns=["*.cpp", "*.h", "jenkins/*"], - skip_shlibdeps=True) - - # Package 4: qt6-release-ctest-sources (test source files from release scope) - build_nobuild_package( - "qt6-release-ctest-sources", source_dir, build_base, output_dir, version, build_number, - description="Qt6 Release CTest Sources - test source files from release scope", - prepare=lambda pkg_dir: test_sources_install_lines(pkg_dir, release_dirs), - allowed_patterns=["Lts/*", "TetraIF/*", "Z/*", "usr/share/doc/*", "debian/*"], - forbidden_patterns=["build/*", "jenkins/*"]) - - # Package 5: qt6-release-build-pipeline (Docker, Jenkins, CMake, packaging scripts) - build_nobuild_package( - "qt6-release-build-pipeline", source_dir, build_base, output_dir, version, build_number, - description="Qt6 Release Build Pipeline - Docker, Jenkins, CMake, and packaging scripts", - prepare=pipeline_install_lines, - allowed_patterns=["usr/src/pipeline/*", "usr/share/doc/*", "debian/*"], - forbidden_patterns=["*.cpp", "*.h", "tests/*"]) - - # Cleanup - os.chdir(source_dir) - remove_directory(build_base) - - info("\n========================================") - info(f"DEB package build completed: {output_dir}") - info("Generated packages:") - for f in os.listdir(output_dir): - if f.endswith(".deb"): - info(f" - {f}") - info("========================================") - - -def main(): - parser = argparse.ArgumentParser(description="Build DEB packages for Legatus Qt6 Release") - parser.add_argument("-c", "--config", required=True, help="Config type (LTS)") - parser.add_argument("--project_name", required=True, help="Project name (qatar|ahtc|guez)") - parser.add_argument("--version", required=True, help="Version (Major.minor)") - parser.add_argument("--output_dir", required=True, help="Output directory for packages") - parser.add_argument("--source_dir", required=True, help="Source directory path") - parser.add_argument("--cmake_build_flags", default="", help="CMake build flags") - parser.add_argument("--build_number", default="1", help="Build number") - parser.add_argument("--release_scope", action="store_true", help="Only include release scope files") - - args = parser.parse_args() - info(f"Building {args.config} package for {args.project_name} v{args.version}") - info(f"Output directory: {args.output_dir}") - info(f"Source directory: {args.source_dir}") - info(f"CMake flags: {args.cmake_build_flags}") - info(f"Release scope: {args.release_scope}") - build_all_debs(source_dir=args.source_dir, output_dir=args.output_dir, - version=args.version, build_number=args.build_number, - cmake_flags=args.cmake_build_flags) - - -if __name__ == "__main__": - main() diff --git a/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py b/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py index 3e7154186..9eb9fe6bd 100644 --- a/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py +++ b/qt6-after/qt6-migrated-legatus/rpmbuild/make_rpm_ubuntu26_release2.py @@ -21,14 +21,14 @@ from email.utils import formatdate SKIP_DIRS = {'build', 'cmake-build-debug', 'cmake-build-release', 'deb_build_tmp'} SOURCE_EXTENSIONS = ('.cpp', '.h', '.hpp', '.cc', '.cxx', '.hxx') PIPELINE_FILES = [ - "new_docker_build.sh", + "new_docker_build_release2.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", - "rpmbuild/make_rpm_ubuntu26.py", + "rpmbuild/make_rpm_ubuntu26_release2.py", "CMakeLists.txt", ]