Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/new_docker_build.sh
T

1649 lines
49 KiB
Bash
Executable File

#!/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")
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=<image-name>
Required .envrc variable:
MIGRATE_PIPELINE_ROOT=<absolute-path>
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=OFF
BUILD_GROUP5=OFF
BUILD_GROUP6=OFF
BUILD_GROUP7=OFF
BUILD_GROUP8=OFF
BUILD_GROUP9=OFF
BUILD_GROUP10=OFF
BUILD_GROUP11=OFF
BUILD_GROUP12=OFF
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
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
# <ElevationMap/elevation_map.h>).
# 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" <<EOF
FROM ubuntu:26.04
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update -qq && \
apt-get install -y -qq \
${APT_PACKAGES_STRING} \
libqt6svg6-dev \
libgtest-dev \
libgmock-dev \
python3-pip && \
rm -rf /var/lib/apt/lists/*
# Install Qt6 packages via aqtinstall
# Note: QtWebKit is deprecated in Qt6, use QtWebEngine instead
# KDReports is installed via aqtinstall or built from source if needed
# Note: qtsvg is NOT available via aqtinstall - it's provided by libqt6svg6-dev apt package
RUN pip3 install --break-system-packages --quiet aqtinstall && \
aqt install-qt linux desktop ${QT_VERSION} ${QT_ARCH} \
-m qtmultimedia qtserialport qtimageformats qtwebsockets qtwebengine \
qtpdf qtwebview qt5compat qtwebchannel qtpositioning qtlocation qtsensors \
--outputdir ${QT_BASE_DIR} && \
rm -rf /root/.cache/Aqt
# Install KDReports from source (apt package not available in Ubuntu 22.04/26.04)
# Try apt install first (will fail), then build from KDAB GitHub mirror
RUN apt-get install -y -qq libkdreports-dev 2>/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 -j$(nproc) && \
make install && \
cd / && rm -rf /tmp/KDReports)
# Legacy sources include <KDReports/...> 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:-OFF}"
BUILD_GROUP5="${BUILD_GROUP5:-OFF}"
BUILD_GROUP6="${BUILD_GROUP6:-OFF}"
BUILD_GROUP7="${BUILD_GROUP7:-OFF}"
BUILD_GROUP8="${BUILD_GROUP8:-OFF}"
BUILD_GROUP9="${BUILD_GROUP9:-OFF}"
BUILD_GROUP10="${BUILD_GROUP10:-OFF}"
BUILD_GROUP11="${BUILD_GROUP11:-OFF}"
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
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"
;;
-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:-OFF}"
BUILD_GROUP5="${BUILD_GROUP5:-OFF}"
BUILD_GROUP6="${BUILD_GROUP6:-OFF}"
BUILD_GROUP7="${BUILD_GROUP7:-OFF}"
BUILD_GROUP8="${BUILD_GROUP8:-OFF}"
BUILD_GROUP9="${BUILD_GROUP9:-OFF}"
BUILD_GROUP10="${BUILD_GROUP10:-OFF}"
BUILD_GROUP11="${BUILD_GROUP11:-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}"
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")"
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 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
# 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
advancedSymbology
advancedSymbologyXML
LtsDataView
LtsDataViewTest
)
else
GROUP5_TARGETS=(
# Viewer module with ArcGIS (full build)
situationMapCommon
advancedSymbology
advancedSymbologyXML
LtsDataView
LtsDataViewTest
LtsFileDialog
LtsFileDialogTest
)
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
advancedSymbologyXML
LtsDataView
LtsDataViewTest
)
else
GROUP5_TARGETS=(
# Viewer module without ArcGIS (full build)
situationMapCommon
advancedSymbologyXML
LtsDataView
LtsDataViewTest
LtsFileDialog
LtsFileDialogTest
)
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)
# These tools require RTI DDS for DataSampleGenerator, DataSampleReceiver, and DdsView
GROUP6_TARGETS=(
dbAdministration
SettingsRemover
dbUpdate
tDataSampleGenerator
tDataSampleReceiver
DateTimeSyncer
ddsview
# ddsview runtime topic-type plugins (39 *TopicTypePlugin.so). Not CMake link deps of
# ddsview (loaded at runtime via LtsPluginLoader), so `make ddsview` alone skips them and
# ddsview shows empty Data/Function topic lists. Built here alongside ddsview.
aesTopicTypePlugin
almTopicTypePlugin
asmTopicTypePlugin
avmTopicTypePlugin
bldTopicTypePlugin
cesTopicTypePlugin
cmoTopicTypePlugin
codTopicTypePlugin
coreTopicTypePlugin
eemTopicTypePlugin
escTopicTypePlugin
esmTopicTypePlugin
evlTopicTypePlugin
exmTopicTypePlugin
flmTopicTypePlugin
fltTopicTypePlugin
gimTopicTypePlugin
gnaTopicTypePlugin
ismTopicTypePlugin
mdmTopicTypePlugin
mrkTopicTypePlugin
msgTopicTypePlugin
nmeTopicTypePlugin
nomTopicTypePlugin
obdTopicTypePlugin
opmTopicTypePlugin
oscTopicTypePlugin
ossTopicTypePlugin
pdmTopicTypePlugin
ppmTopicTypePlugin
preTopicTypePlugin
repTopicTypePlugin
scmTopicTypePlugin
somTopicTypePlugin
srpTopicTypePlugin
tabTopicTypePlugin
tabocTopicTypePlugin
tgtTopicTypePlugin
whgTopicTypePlugin
displayPanelSimulator
LicenceEditor
localDomainFinder
LogView
LogViewer
CoPrtCnv
PrtCnvLib
PrtCnv
)
# 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
)
# 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 <appdir>/../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:-OFF}"
BUILD_GROUP5="${BUILD_GROUP5:-OFF}"
BUILD_GROUP6="${BUILD_GROUP6:-OFF}"
BUILD_GROUP7="${BUILD_GROUP7:-OFF}"
BUILD_GROUP8="${BUILD_GROUP8:-OFF}"
BUILD_GROUP9="${BUILD_GROUP9:-OFF}"
BUILD_GROUP10="${BUILD_GROUP10:-OFF}"
BUILD_GROUP11="${BUILD_GROUP11:-OFF}"
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[*]}"
make -j8 "${targets[@]}" 2>&1 | tee "${log_file}"
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=/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_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_STANDARD=17 \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-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};/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 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}" \
-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