#!/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 # - 3 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 # ----------------------------------------------------------------------------- usage() { cat <<'EOF' Usage: ./build.sh [ON|OFF] [options] BUILD_RTI: First positional argument may be: ON Enable BUILD_RTI OFF Disable BUILD_RTI 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 targets build Test execution: --no-ctest Skip ctest execution --tests-only Run only ctest, skip all make build groups --integration-test Run only Z-module integration tests (test_z_*) 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_GROUP1=ON|OFF BUILD_GROUP2=ON|OFF BUILD_GROUP3=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_GROUP1=ON BUILD_GROUP2=ON BUILD_GROUP3=ON 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: ./build.sh ./build.sh OFF ./build.sh --no-group3 ./build.sh --no-group1 --group2 --no-group3 ./build.sh --no-ctest ./build.sh --tests-only ./build.sh --build-prebuilt-image --docker-image qt-migration-builder:latest ./build.sh --use-prebuilt-image --docker-image qt-migration-builder:latest ./build.sh --build-prebuilt-image --use-prebuilt-image --docker-image qt-migration-builder:latest ./build.sh --delete-prebuilt-image --docker-image qt-migration-builder:latest ./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 libkf6texttemplate-dev libqt6core6 libqt6gui6 libqt6widgets6 qt6-base-dev qt6-tools-dev-tools qt6-tools-dev qt6-l10n-tools libgtest-dev libpq-dev postgresql-server-dev-all libvlc-dev vlc-plugin-base git ) GROUP1_TARGETS=( ddscore ddsftccore ddsQoS ddsconnector ddsfts ) GROUP2_TARGETS=( migration_tests ) GROUP3_TARGETS=( NGLLogger nglapplication nglcompression nglcoreapplication ngldb nglguiapplication nglsettings nglsingleapplication nglsinglecoreapplication ngltools ngltranslator nglwidgets qtsingleapplication qtsinglecoreapplication wms_json_ds tcpserver ) 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" < "${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_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}" APT_PACKAGES_STRING="${APT_PACKAGES_STRING:-}" log_info() { printf 'INFO: %s\n' "$*" } 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" 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 fi export RTI_LICENSE_FILE=/workspace/rti_license.dat export QT_QPA_PLATFORM=offscreen cd /workspace/qt-migration-legatus/qt6-after/qt6-migrated-legatus rm -rf build4 mkdir -p build4 cd build4 cmake .. \ -DBUILD_RTI="${BUILD_RTI}" \ -DBUILD_ARCGIS=OFF \ -DCMAKE_CXX_STANDARD=17 \ -DCMAKE_BUILD_TYPE=Release read -r -a GROUP1_ARRAY <<< "${GROUP1_TARGETS}" read -r -a GROUP2_ARRAY <<< "${GROUP2_TARGETS}" read -r -a GROUP3_ARRAY <<< "${GROUP3_TARGETS}" if [[ "${TESTS_ONLY}" != "ON" ]]; then run_build_group "Group 1" "${BUILD_GROUP1}" "group1_build.log" "${GROUP1_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[@]}" else log_info "TESTS_ONLY enabled - skipping all build groups" fi if [[ "${RUN_CTEST}" == "ON" ]]; then if [[ "${INTEGRATION_TEST}" == "ON" ]]; then log_info "Running Z-module integration tests only" ctest --test-dir . --output-on-failure -R "test_z_" 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_GROUP1 \ -e BUILD_GROUP2 \ -e BUILD_GROUP3 \ -e RUN_CTEST \ -e TESTS_ONLY \ -e INTEGRATION_TEST \ -e USE_PREBUILT_IMAGE \ -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}" \ -v "${WORKSPACE_ROOT_HOST}:/workspace" \ -v "${RTI_LICENSE_FILE_HOST}:/workspace/rti_license.dat" \ -v "${CONTAINER_SCRIPT_HOST}:/tmp/run-build-inside-container.sh:ro" \ "${DOCKER_IMAGE}" \ bash /tmp/run-build-inside-container.sh