#!/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 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 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 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_GROUP1=ON|OFF BUILD_GROUP2=ON|OFF BUILD_GROUP3=ON|OFF BUILD_GROUP4=ON|OFF BUILD_GROUP5=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= 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_GROUP1=ON BUILD_GROUP2=ON BUILD_GROUP3=ON BUILD_GROUP4=OFF BUILD_GROUP5=OFF RUN_CTEST=ON TESTS_ONLY=OFF INTEGRATION_TEST=OFF USE_PREBUILT_IMAGE=OFF BUILD_PREBUILT_IMAGE=OFF DELETE_PREBUILT_IMAGE=OFF DOCKER_IMAGE=qt-migration-builder:latest 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 qt-migration-builder:latest ./new_docker_build.sh --use-prebuilt-image --docker-image qt-migration-builder:latest ./new_docker_build.sh --build-prebuilt-image --use-prebuilt-image --docker-image qt-migration-builder:latest ./new_docker_build.sh --delete-prebuilt-image --docker-image qt-migration-builder: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 TmsIfAdapterInterface TmsIfAdapter tabPluginUAS TabUASTest3 TabUASTest4_2 TabUASTest6 # Proxies module - TrainingAreaBaseOC svcTabocCommon svcTabocClient svcTabocServer svcTrainingAreaBaseOC serialtest # Proxies module - WirelessLocationSystem 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; 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_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:-OFF}" BUILD_GROUP5="${BUILD_GROUP5:-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}" if [[ "${USE_PREBUILT_IMAGE}" == "ON" ]]; then DOCKER_IMAGE="${DOCKER_IMAGE:-qt-migration-builder:latest}" else DOCKER_IMAGE="${DOCKER_IMAGE:-ubuntu:26.04}" fi 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 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 ;; --grantlee) BUILD_GRANTLEE=ON ;; --no-grantlee) BUILD_GRANTLEE=OFF ;; --arcgis) BUILD_ARCGIS=ON ;; --no-arcgis) BUILD_ARCGIS=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" ;; -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}" 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_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")" 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")" # Export variables for Docker container export BUILD_ALL BUILD_RTI BUILD_GRANTLEE BUILD_ARCGIS BUILD_GROUP1 BUILD_GROUP2 BUILD_GROUP3 BUILD_GROUP4 BUILD_GROUP5 RUN_CTEST TESTS_ONLY INTEGRATION_TEST USE_PREBUILT_IMAGE BUILD_PREBUILT_IMAGE DELETE_PREBUILT_IMAGE DOCKER_IMAGE # Group 5: Viewer module targets (conditional on BUILD_ARCGIS) if [[ "${BUILD_ARCGIS}" == "ON" ]]; then GROUP5_TARGETS=( # Viewer module with ArcGIS situationMapCommon advancedSymbology advancedSymbologyXML LtsDataView LtsFileDialog LtsReportDisplay ) else GROUP5_TARGETS=( # Viewer module without ArcGIS (advancedSymbology requires ArcGIS) situationMapCommon advancedSymbologyXML LtsDataView LtsFileDialog LtsReportDisplay ) fi 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_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[@]}")" 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_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:-OFF}" BUILD_GROUP5="${BUILD_GROUP5:-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[*]}" make -j8 "${targets[@]}" 2>&1 | tee "${log_file}" else log_info "Skipping ${group_id}" 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 export RTI_LICENSE_FILE=/workspace/rti_license.dat export QT_QPA_PLATFORM=offscreen # Setup ArcGIS SDK if enabled if [[ "${BUILD_ARCGIS}" == "ON" ]]; then log_info "Setting up ArcGIS SDK" if [[ -f "/workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus/install_arcgis.sh" ]]; then bash /workspace/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 /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus rm -rf build4 mkdir -p build4 cd build4 cmake .. \ -DBUILD_TESTING=ON \ -DBUILD_RTI="${BUILD_RTI}" \ -DBUILD_GRANTLEE="${BUILD_GRANTLEE}" \ -DBUILD_ARCGIS="${BUILD_ARCGIS}" \ -DCMAKE_CXX_STANDARD=17 \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_PREFIX_PATH="${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR}${BUILD_ARCGIS:+;/workspace/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}" 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}" if [[ "${TESTS_ONLY}" != "ON" ]]; then 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[@]}" 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_RTI \ -e BUILD_GRANTLEE \ -e BUILD_ARCGIS \ -e BUILD_GROUP1 \ -e BUILD_GROUP2 \ -e BUILD_GROUP3 \ -e BUILD_GROUP4 \ -e BUILD_GROUP5 \ -e RUN_CTEST \ -e TESTS_ONLY \ -e INTEGRATION_TEST \ -e USE_PREBUILT_IMAGE \ -e QT_VERSION \ -e QT_ARCH \ -e QT_ARCH_DIR \ -e QT_BASE_DIR \ -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}" \ -v "${WORKSPACE_ROOT_HOST}:/workspace" \ -v "${RTI_LICENSE_FILE_HOST}:/workspace/rti_license.dat" \ -v "${MIGRATE_PIPELINE_ROOT}/external:/workspace/external:ro" \ -v "${CONTAINER_SCRIPT_HOST}:/tmp/run-build-inside-container.sh:ro" \ "${DOCKER_IMAGE}" \ bash /tmp/run-build-inside-container.sh