diff --git a/.github/actions/build-config/action.yml b/.github/actions/build-config/action.yml new file mode 100644 index 000000000000..93bca43375e9 --- /dev/null +++ b/.github/actions/build-config/action.yml @@ -0,0 +1,144 @@ +name: Build Config +description: Read build toolchain versions from .github/build-config.json + +outputs: + qt_version: + description: Qt version + value: ${{ steps.read.outputs.qt_version }} + qt_minimum_version: + description: Qt minimum supported version + value: ${{ steps.read.outputs.qt_minimum_version }} + qt_modules: + description: Qt modules (desktop) + value: ${{ steps.read.outputs.qt_modules }} + qt_modules_ios: + description: Qt modules (iOS, excludes qtserialport/qtscxml) + value: ${{ steps.read.outputs.qt_modules_ios }} + gstreamer_version: + description: GStreamer version (macOS/Linux) + value: ${{ steps.read.outputs.gstreamer_version }} + gstreamer_android_version: + description: GStreamer version (Android) + value: ${{ steps.read.outputs.gstreamer_android_version }} + gstreamer_windows_version: + description: GStreamer version (Windows) + value: ${{ steps.read.outputs.gstreamer_windows_version }} + ndk_version: + description: Android NDK version (short form) + value: ${{ steps.read.outputs.ndk_version }} + ndk_full_version: + description: Android NDK version (full form for sdkmanager) + value: ${{ steps.read.outputs.ndk_full_version }} + java_version: + description: Java version + value: ${{ steps.read.outputs.java_version }} + android_platform: + description: Android platform/API level + value: ${{ steps.read.outputs.android_platform }} + android_min_sdk: + description: Android minimum SDK version + value: ${{ steps.read.outputs.android_min_sdk }} + android_build_tools: + description: Android build tools version + value: ${{ steps.read.outputs.android_build_tools }} + android_cmdline_tools: + description: Android command line tools version + value: ${{ steps.read.outputs.android_cmdline_tools }} + xcode_version: + description: Xcode version (macOS) + value: ${{ steps.read.outputs.xcode_version }} + xcode_ios_version: + description: Xcode version (iOS) + value: ${{ steps.read.outputs.xcode_ios_version }} + cmake_minimum_version: + description: CMake minimum version + value: ${{ steps.read.outputs.cmake_minimum_version }} + ccache_version: + description: ccache version + value: ${{ steps.read.outputs.ccache_version }} + ccache_max_size: + description: ccache max cache size + value: ${{ steps.read.outputs.ccache_max_size }} + clang_format_version: + description: clang-format version + value: ${{ steps.read.outputs.clang_format_version }} + node_version: + description: Node.js version + value: ${{ steps.read.outputs.node_version }} + flatpak_gnome_version: + description: GNOME version for Flatpak + value: ${{ steps.read.outputs.flatpak_gnome_version }} + +runs: + using: composite + steps: + - name: Validate and read build config + id: read + shell: bash + run: | + CONFIG_FILE="${GITHUB_WORKSPACE}/.github/build-config.json" + if [[ ! -f "$CONFIG_FILE" ]]; then + echo "::error::Build config not found: $CONFIG_FILE" + exit 1 + fi + if ! jq empty "$CONFIG_FILE" 2>/dev/null; then + echo "::error::Invalid JSON in $CONFIG_FILE" + exit 1 + fi + + # Read all values (no fallbacks - config is authoritative) + QT_VERSION=$(jq -r '.qt_version' "$CONFIG_FILE") + QT_MIN_VERSION=$(jq -r '.qt_minimum_version' "$CONFIG_FILE") + QT_MODULES=$(jq -r '.qt_modules' "$CONFIG_FILE") + QT_MODULES_IOS=$(echo "$QT_MODULES" | sed 's/qtserialport//g; s/qtscxml//g; s/ */ /g; s/^ *//; s/ *$//') + GST_VERSION=$(jq -r '.gstreamer_version' "$CONFIG_FILE") + GST_ANDROID_VERSION=$(jq -r '.gstreamer_android_version' "$CONFIG_FILE") + GST_WIN_VERSION=$(jq -r '.gstreamer_windows_version' "$CONFIG_FILE") + NDK_VERSION=$(jq -r '.ndk_version' "$CONFIG_FILE") + NDK_FULL_VERSION=$(jq -r '.ndk_full_version' "$CONFIG_FILE") + JAVA_VERSION=$(jq -r '.java_version' "$CONFIG_FILE") + ANDROID_PLATFORM=$(jq -r '.android_platform' "$CONFIG_FILE") + ANDROID_MIN_SDK=$(jq -r '.android_min_sdk' "$CONFIG_FILE") + ANDROID_BUILD_TOOLS=$(jq -r '.android_build_tools' "$CONFIG_FILE") + ANDROID_CMDLINE_TOOLS=$(jq -r '.android_cmdline_tools' "$CONFIG_FILE") + XCODE_VERSION=$(jq -r '.xcode_version' "$CONFIG_FILE") + XCODE_IOS_VERSION=$(jq -r '.xcode_ios_version' "$CONFIG_FILE") + CMAKE_MIN_VERSION=$(jq -r '.cmake_minimum_version' "$CONFIG_FILE") + CCACHE_VERSION=$(jq -r '.ccache_version' "$CONFIG_FILE") + CCACHE_MAX_SIZE=$(jq -r '.ccache_max_size' "$CONFIG_FILE") + CLANG_FORMAT_VERSION=$(jq -r '.clang_format_version' "$CONFIG_FILE") + NODE_VERSION=$(jq -r '.node_version' "$CONFIG_FILE") + FLATPAK_GNOME_VERSION=$(jq -r '.flatpak_gnome_version' "$CONFIG_FILE") + + { + echo "qt_version=$QT_VERSION" + echo "qt_minimum_version=$QT_MIN_VERSION" + echo "qt_modules=$QT_MODULES" + echo "qt_modules_ios=$QT_MODULES_IOS" + echo "gstreamer_version=$GST_VERSION" + echo "gstreamer_android_version=$GST_ANDROID_VERSION" + echo "gstreamer_windows_version=$GST_WIN_VERSION" + echo "ndk_version=$NDK_VERSION" + echo "ndk_full_version=$NDK_FULL_VERSION" + echo "java_version=$JAVA_VERSION" + echo "android_platform=$ANDROID_PLATFORM" + echo "android_min_sdk=$ANDROID_MIN_SDK" + echo "android_build_tools=$ANDROID_BUILD_TOOLS" + echo "android_cmdline_tools=$ANDROID_CMDLINE_TOOLS" + echo "xcode_version=$XCODE_VERSION" + echo "xcode_ios_version=$XCODE_IOS_VERSION" + echo "cmake_minimum_version=$CMAKE_MIN_VERSION" + echo "ccache_version=$CCACHE_VERSION" + echo "ccache_max_size=$CCACHE_MAX_SIZE" + echo "clang_format_version=$CLANG_FORMAT_VERSION" + echo "node_version=$NODE_VERSION" + echo "flatpak_gnome_version=$FLATPAK_GNOME_VERSION" + } >> "$GITHUB_OUTPUT" + + # Only set commonly-used variables as environment variables to avoid polluting the env. + # All values are available as step outputs (e.g., steps.config.outputs.ndk_version). + - name: Set environment variables + shell: bash + run: | + echo "QT_VERSION=${{ steps.read.outputs.qt_version }}" >> "$GITHUB_ENV" + echo "GSTREAMER_VERSION=${{ steps.read.outputs.gstreamer_version }}" >> "$GITHUB_ENV" diff --git a/.github/build-config.json b/.github/build-config.json new file mode 100644 index 000000000000..13ede7f617a9 --- /dev/null +++ b/.github/build-config.json @@ -0,0 +1,29 @@ +{ + "qt_version": "6.10.1", + "qt_minimum_version": "6.10.0", + "qt_modules": "qtcharts qtlocation qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors qtscxml", + + "gstreamer_version": "1.24.13", + "gstreamer_android_version": "1.22.12", + "gstreamer_windows_version": "1.22.12", + + "ndk_version": "r27c", + "ndk_full_version": "27.2.12829759", + "java_version": "17", + "android_platform": "35", + "android_min_sdk": "28", + "android_build_tools": "35.0.0", + "android_cmdline_tools": "13114758", + + "xcode_version": "16.x", + "xcode_ios_version": "latest-stable", + + "cmake_minimum_version": "3.25", + + "ccache_version": "4.11.3", + "ccache_max_size": "2G", + "clang_format_version": "17", + "node_version": "22", + + "flatpak_gnome_version": "47" +} diff --git a/.github/workflows/docker-linux.yml b/.github/workflows/docker-linux.yml index 7db2a1d64b43..c62332413e9a 100644 --- a/.github/workflows/docker-linux.yml +++ b/.github/workflows/docker-linux.yml @@ -12,8 +12,10 @@ on: pull_request: paths: - '.github/workflows/docker-linux.yml' + - '.github/build-config.json' - 'deploy/docker/**' - 'deploy/linux/**' + - 'tools/setup/**' - 'src/**' - 'CMakeLists.txt' - 'cmake/**' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 62121cbb2eb5..743ba89760e0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -47,6 +47,7 @@ repos: rev: v0.11.0.1 hooks: - id: shellcheck + args: ['-e', 'SC1091'] # Don't warn about not following sourced files # YAML validation - repo: https://github.com/adrienverge/yamllint diff --git a/cmake/BuildConfig.cmake b/cmake/BuildConfig.cmake new file mode 100644 index 000000000000..1cec3d518808 --- /dev/null +++ b/cmake/BuildConfig.cmake @@ -0,0 +1,37 @@ +# ============================================================================ +# BuildConfig.cmake - Read .github/build-config.json +# ============================================================================ + +set(QGC_BUILD_CONFIG_FILE "${CMAKE_SOURCE_DIR}/.github/build-config.json") + +if(NOT EXISTS "${QGC_BUILD_CONFIG_FILE}") + message(FATAL_ERROR "BuildConfig: Config file not found: ${QGC_BUILD_CONFIG_FILE}") +endif() + +# Read the JSON file +file(READ "${QGC_BUILD_CONFIG_FILE}" QGC_BUILD_CONFIG_CONTENT) + +# Extract value from JSON (simple regex for flat JSON) +# NOTE: All values in build-config.json must be quoted strings for this parser +macro(qgc_config_get_value VAR_NAME JSON_KEY) + string(REGEX MATCH "\"${JSON_KEY}\"[ \t\n]*:[ \t\n]*\"([^\"]*)\"" _match "${QGC_BUILD_CONFIG_CONTENT}") + if(_match) + set(${VAR_NAME} "${CMAKE_MATCH_1}" CACHE STRING "${JSON_KEY}") + else() + message(FATAL_ERROR "BuildConfig: Key '${JSON_KEY}' not found in ${QGC_BUILD_CONFIG_FILE}") + endif() +endmacro() + +qgc_config_get_value(QGC_CONFIG_QT_VERSION "qt_version") +qgc_config_get_value(QGC_CONFIG_QT_MINIMUM_VERSION "qt_minimum_version") +qgc_config_get_value(QGC_CONFIG_GSTREAMER_VERSION "gstreamer_version") +qgc_config_get_value(QGC_CONFIG_GSTREAMER_ANDROID_VERSION "gstreamer_android_version") +qgc_config_get_value(QGC_CONFIG_GSTREAMER_WIN_VERSION "gstreamer_windows_version") +qgc_config_get_value(QGC_CONFIG_NDK_VERSION "ndk_version") +qgc_config_get_value(QGC_CONFIG_NDK_FULL_VERSION "ndk_full_version") +qgc_config_get_value(QGC_CONFIG_JAVA_VERSION "java_version") +qgc_config_get_value(QGC_CONFIG_ANDROID_PLATFORM "android_platform") +qgc_config_get_value(QGC_CONFIG_ANDROID_MIN_SDK "android_min_sdk") +qgc_config_get_value(QGC_CONFIG_CMAKE_MINIMUM "cmake_minimum_version") + +message(STATUS "BuildConfig: Qt ${QGC_CONFIG_QT_VERSION}, GStreamer ${QGC_CONFIG_GSTREAMER_VERSION}, NDK ${QGC_CONFIG_NDK_VERSION}") diff --git a/cmake/CustomOptions.cmake b/cmake/CustomOptions.cmake index 789f7a2f64ce..177ed0b882eb 100644 --- a/cmake/CustomOptions.cmake +++ b/cmake/CustomOptions.cmake @@ -5,6 +5,9 @@ include(CMakeDependentOption) +# Load centralized build configuration from .github/build-config.json +include(BuildConfig) + # ============================================================================ # Application Metadata # ============================================================================ @@ -138,8 +141,8 @@ set(QGC_WINDOWS_RESOURCE_FILE_PATH "${CMAKE_SOURCE_DIR}/deploy/windows/QGroundCo # Qt Configuration # ============================================================================ -set(QGC_QT_MINIMUM_VERSION "6.10.0" CACHE STRING "Minimum supported Qt version") -set(QGC_QT_MAXIMUM_VERSION "6.10.1" CACHE STRING "Maximum supported Qt version") +set(QGC_QT_MINIMUM_VERSION "${QGC_CONFIG_QT_MINIMUM_VERSION}" CACHE STRING "Minimum supported Qt version") +set(QGC_QT_MAXIMUM_VERSION "${QGC_CONFIG_QT_VERSION}" CACHE STRING "Maximum supported Qt version") set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml" CACHE PATH "QML output directory") set(QML_IMPORT_PATH "${QT_QML_OUTPUT_DIRECTORY}" CACHE STRING "Additional QML import paths") diff --git a/cmake/find-modules/FindGStreamer.cmake b/cmake/find-modules/FindGStreamer.cmake index af3a1c208231..0cae1b364f9f 100644 --- a/cmake/find-modules/FindGStreamer.cmake +++ b/cmake/find-modules/FindGStreamer.cmake @@ -10,12 +10,16 @@ # Default Configuration # ---------------------------------------------------------------------------- -# Set default version based on platform +# Set default version based on platform (from build-config.json) if(NOT DEFINED GStreamer_FIND_VERSION) if(LINUX) set(GStreamer_FIND_VERSION 1.20) + elseif(WIN32) + set(GStreamer_FIND_VERSION ${QGC_CONFIG_GSTREAMER_WIN_VERSION}) + elseif(ANDROID) + set(GStreamer_FIND_VERSION ${QGC_CONFIG_GSTREAMER_ANDROID_VERSION}) else() - set(GStreamer_FIND_VERSION 1.22.12) + set(GStreamer_FIND_VERSION ${QGC_CONFIG_GSTREAMER_VERSION}) endif() endif() diff --git a/cmake/platform/Android.cmake b/cmake/platform/Android.cmake index 79eb0d2c94fb..f911ba9cb593 100644 --- a/cmake/platform/Android.cmake +++ b/cmake/platform/Android.cmake @@ -9,10 +9,14 @@ endif() # ---------------------------------------------------------------------------- # Android NDK Version Validation # ---------------------------------------------------------------------------- -if(Qt6_VERSION VERSION_EQUAL "6.10.1") - if(NOT CMAKE_ANDROID_NDK_VERSION VERSION_EQUAL "27.2") - message(FATAL_ERROR "QGC: Invalid NDK Version: ${CMAKE_ANDROID_NDK_VERSION}. Qt 6.10.1 requires NDK 27.2") +# CMAKE_ANDROID_NDK_VERSION format varies: "27.2" or "27.2.12829759" +# Extract major.minor from ndk_full_version for reliable comparison +if(DEFINED QGC_CONFIG_NDK_FULL_VERSION AND Qt6_VERSION VERSION_GREATER_EQUAL "${QGC_CONFIG_QT_MINIMUM_VERSION}") + string(REGEX MATCH "^([0-9]+\\.[0-9]+)" _ndk_major_minor "${QGC_CONFIG_NDK_FULL_VERSION}") + if(_ndk_major_minor AND NOT CMAKE_ANDROID_NDK_VERSION VERSION_GREATER_EQUAL "${_ndk_major_minor}") + message(FATAL_ERROR "QGC: NDK ${CMAKE_ANDROID_NDK_VERSION} is too old. Qt ${Qt6_VERSION} requires NDK ${_ndk_major_minor}+ (${QGC_CONFIG_NDK_VERSION})") endif() + unset(_ndk_major_minor) endif() # ---------------------------------------------------------------------------- diff --git a/deploy/docker/Dockerfile-build-android b/deploy/docker/Dockerfile-build-android index 7057a6771e6c..7bb78fd56022 100644 --- a/deploy/docker/Dockerfile-build-android +++ b/deploy/docker/Dockerfile-build-android @@ -2,32 +2,47 @@ FROM ubuntu:24.04 ENV DEBIAN_FRONTEND=noninteractive +# Copy build config and setup scripts +COPY .github/build-config.json /tmp/qt/ COPY tools/setup/install-dependencies-debian.sh /tmp/qt/ +COPY tools/setup/read-config.sh /tmp/qt/ RUN chmod +x /tmp/qt/*.sh && /tmp/qt/install-dependencies-debian.sh -# Set environment variables for Android SDK, NDK, and paths -ENV ANDROID_SDK_ROOT=/opt/android-sdk -ENV ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/26.1.10909125 -ENV ANDROID_HOME=$ANDROID_SDK_ROOT -ENV ANDROID_BUILD_TOOLS=$ANDROID_SDK_ROOT/build-tools/35.0.0 +# Read all versions from centralized config +RUN apt-get update && apt-get install -y jq && \ + CONFIG=/tmp/qt/build-config.json && \ + echo "export QT_VERSION=$(jq -r '.qt_version' $CONFIG)" >> /etc/profile.d/qgc.sh && \ + echo "export QT_MODULES=\"$(jq -r '.qt_modules' $CONFIG)\"" >> /etc/profile.d/qgc.sh && \ + echo "export JAVA_VERSION=$(jq -r '.java_version' $CONFIG)" >> /etc/profile.d/qgc.sh && \ + echo "export NDK_FULL_VERSION=$(jq -r '.ndk_full_version' $CONFIG)" >> /etc/profile.d/qgc.sh && \ + echo "export ANDROID_PLATFORM=$(jq -r '.android_platform' $CONFIG)" >> /etc/profile.d/qgc.sh && \ + echo "export ANDROID_BUILD_TOOLS=$(jq -r '.android_build_tools' $CONFIG)" >> /etc/profile.d/qgc.sh && \ + echo "export ANDROID_CMDLINE_TOOLS=$(jq -r '.android_cmdline_tools' $CONFIG)" >> /etc/profile.d/qgc.sh && \ + chmod +x /etc/profile.d/qgc.sh -RUN apt-get update && apt-get install -y openjdk-17-jdk +RUN . /etc/profile.d/qgc.sh && apt-get install -y openjdk-${JAVA_VERSION}-jdk -# Set JAVA_HOME and update PATH -ENV JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 +ENV ANDROID_SDK_ROOT=/opt/android-sdk +ENV ANDROID_HOME=$ANDROID_SDK_ROOT # Install Android SDK and NDK -RUN mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/latest && \ - wget https://dl.google.com/android/repository/commandlinetools-linux-12266719_latest.zip -O /opt/cmdline-tools.zip && \ +RUN . /etc/profile.d/qgc.sh && \ + mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/latest && \ + wget "https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_CMDLINE_TOOLS}_latest.zip" -O /opt/cmdline-tools.zip && \ unzip /opt/cmdline-tools.zip -d $ANDROID_SDK_ROOT/cmdline-tools && \ mv $ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools/* $ANDROID_SDK_ROOT/cmdline-tools/latest/ && \ rm -rf $ANDROID_SDK_ROOT/cmdline-tools/cmdline-tools && \ rm /opt/cmdline-tools.zip && \ yes | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT --licenses && \ - $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT "platform-tools" "platforms;android-35" "build-tools;35.0.0" "ndk;26.1.10909125" + $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager --sdk_root=$ANDROID_SDK_ROOT \ + "platform-tools" \ + "platforms;android-${ANDROID_PLATFORM}" \ + "build-tools;${ANDROID_BUILD_TOOLS}" \ + "ndk;${NDK_FULL_VERSION}" && \ + echo "export ANDROID_NDK_ROOT=$ANDROID_SDK_ROOT/ndk/${NDK_FULL_VERSION}" >> /etc/profile.d/qgc.sh && \ + echo "export ANDROID_BUILD_TOOLS_DIR=$ANDROID_SDK_ROOT/build-tools/${ANDROID_BUILD_TOOLS}" >> /etc/profile.d/qgc.sh -# Qt setup and environment variables -ENV QT_VERSION="6.10.1" +# Qt setup ENV QT_PATH="/opt/Qt" ENV QT_HOST="linux" ENV QT_HOST_ARCH="gcc_64" @@ -35,48 +50,46 @@ ENV QT_HOST_ARCH_DIR="linux_gcc_64" ENV QT_TARGET="android" ENV QT_TARGET_ARCH_ARMV7="android_armv7" ENV QT_TARGET_ARCH_ARM64="android_arm64_v8a" -ENV QT_MODULES="qtcharts qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors qtlocation" # Install aqtinstall and download Qt for both host and target architectures -RUN python3 -m pip install aqtinstall && \ +RUN . /etc/profile.d/qgc.sh && \ + python3 -m pip install aqtinstall && \ mkdir -p $QT_PATH && \ aqt install-qt $QT_HOST desktop $QT_VERSION $QT_HOST_ARCH -O $QT_PATH -m $QT_MODULES && \ aqt install-qt $QT_HOST $QT_TARGET $QT_VERSION $QT_TARGET_ARCH_ARMV7 -O $QT_PATH -m $QT_MODULES --autodesktop && \ - aqt install-qt $QT_HOST $QT_TARGET $QT_VERSION $QT_TARGET_ARCH_ARM64 -O $QT_PATH -m $QT_MODULES --autodesktop + aqt install-qt $QT_HOST $QT_TARGET $QT_VERSION $QT_TARGET_ARCH_ARM64 -O $QT_PATH -m $QT_MODULES --autodesktop && \ + echo "export QT_ROOT_DIR_ARMV7=$QT_PATH/$QT_VERSION/$QT_TARGET_ARCH_ARMV7" >> /etc/profile.d/qgc.sh && \ + echo "export QT_ROOT_DIR_ARM64=$QT_PATH/$QT_VERSION/$QT_TARGET_ARCH_ARM64" >> /etc/profile.d/qgc.sh && \ + echo "export QT_HOST_PATH=$QT_PATH/$QT_VERSION/$QT_HOST_ARCH_DIR" >> /etc/profile.d/qgc.sh -# Set Qt-related environment variables for ARMv7 and ARM64 architectures -ENV QT_ROOT_DIR_ARMV7=$QT_PATH/$QT_VERSION/$QT_TARGET_ARCH_ARMV7 -ENV QT_ROOT_DIR_ARM64=$QT_PATH/$QT_VERSION/$QT_TARGET_ARCH_ARM64 -ENV QT_HOST_PATH=$QT_PATH/$QT_VERSION/$QT_HOST_ARCH_DIR -ENV QT_PLUGIN_PATH_ARMV7=$QT_ROOT_DIR_ARMV7/plugins -ENV QT_PLUGIN_PATH_ARM64=$QT_ROOT_DIR_ARM64/plugins -ENV QML2_IMPORT_PATH_ARMV7=$QT_ROOT_DIR_ARMV7/qml -ENV QML2_IMPORT_PATH_ARM64=$QT_ROOT_DIR_ARM64/qml -ENV PKG_CONFIG_PATH_ARMV7=$QT_ROOT_DIR_ARMV7/lib/pkgconfig:$PKG_CONFIG_PATH -ENV PKG_CONFIG_PATH_ARM64=$QT_ROOT_DIR_ARM64/lib/pkgconfig:$PKG_CONFIG_PATH -ENV LD_LIBRARY_PATH_ARMV7=$QT_ROOT_DIR_ARMV7/lib:$LD_LIBRARY_PATH -ENV LD_LIBRARY_PATH_ARM64=$QT_ROOT_DIR_ARM64/lib:$LD_LIBRARY_PATH +RUN . /etc/profile.d/qgc.sh && \ + echo "export JAVA_HOME=/usr/lib/jvm/java-${JAVA_VERSION}-openjdk-amd64" >> /etc/profile.d/qgc.sh # Consolidate PATH settings -ENV PATH=$JAVA_HOME/bin:/usr/lib/ccache:$QT_HOST_PATH/bin:$QT_ROOT_DIR_ARMV7/bin:$QT_ROOT_DIR_ARM64/bin:$PATH:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_BUILD_TOOLS:$ANDROID_NDK_ROOT +RUN echo 'export PATH=$JAVA_HOME/bin:/usr/lib/ccache:$QT_HOST_PATH/bin:$QT_ROOT_DIR_ARMV7/bin:$QT_ROOT_DIR_ARM64/bin:$PATH:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$ANDROID_BUILD_TOOLS_DIR:$ANDROID_NDK_ROOT' >> /etc/profile.d/qgc.sh RUN locale-gen en_US.UTF-8 && update-locale LANG=en_US.UTF-8 RUN git config --global --add safe.directory /project/source +# Use login shell for profile sourcing +SHELL ["/bin/bash", "-lc"] + # Set working directory WORKDIR /project/build -# Build the project -CMD mkdir -p /workspace/build/build && \ +# Build the project (uses environment from /etc/profile.d/qgc.sh) +CMD ["bash", "-lc", "\ + mkdir -p /workspace/build/build && \ cd /workspace/build/build && \ qt-cmake -S /project/source -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DQT_HOST_PATH=$QT_HOST_PATH \ -DQT_ANDROID_BUILD_ALL_ABIS=OFF \ - -DQT_ANDROID_ABIS="armeabi-v7a;arm64-v8a" \ - -DANDROID_BUILD_TOOLS=$ANDROID_SDK_ROOT/build-tools/35.0.0 \ + -DQT_ANDROID_ABIS=\"armeabi-v7a;arm64-v8a\" \ + -DANDROID_BUILD_TOOLS=$ANDROID_BUILD_TOOLS_DIR \ -DANDROID_SDK_ROOT=$ANDROID_SDK_ROOT \ -DQT_ANDROID_SIGN_APK=OFF \ -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_ROOT/build/cmake/android.toolchain.cmake && \ - cmake --build . --target all --config Release --parallel + cmake --build . --target all --config Release --parallel \ +"] diff --git a/deploy/docker/Dockerfile-build-ubuntu b/deploy/docker/Dockerfile-build-ubuntu index 3558ec1063a1..f77860f197a2 100644 --- a/deploy/docker/Dockerfile-build-ubuntu +++ b/deploy/docker/Dockerfile-build-ubuntu @@ -29,17 +29,24 @@ ENV LANG=en_US.UTF-8 \ LANGUAGE=en_US:en \ LC_ALL=en_US.UTF-8 -# ---------- Bring in the helper scripts ---------- -# They must be in the build context next to this Dockerfile. +# ---------- Bring in the helper scripts and config ---------- +COPY .github/build-config.json /tmp/qt/ COPY tools/setup/install-dependencies-debian.sh /tmp/qt/ -COPY tools/setup/install-qt-debian.sh /tmp/qt/ +COPY tools/setup/install-qt-debian.sh /tmp/qt/ +COPY tools/setup/read-config.sh /tmp/qt/ RUN chmod +x /tmp/qt/*.sh && \ /tmp/qt/install-dependencies-debian.sh && \ - /tmp/qt/install-qt-debian.sh && \ - rm -rf /tmp/qt # keep the image slim + /tmp/qt/install-qt-debian.sh -ENV QT_ROOT_DIR=/opt/Qt/6.10.1/gcc_64 -ENV PATH=$QT_ROOT_DIR/bin:$PATH +# Extract Qt version and set environment (scripts install to /opt/Qt//gcc_64) +RUN QT_VERSION=$(/tmp/qt/read-config.sh --get qt_version) && \ + echo "export QT_ROOT_DIR=/opt/Qt/${QT_VERSION}/gcc_64" >> /etc/profile.d/qt.sh && \ + echo 'export PATH=$QT_ROOT_DIR/bin:$PATH' >> /etc/profile.d/qt.sh && \ + chmod +x /etc/profile.d/qt.sh && \ + rm -rf /tmp/qt + +# Source qt.sh in bash login shells; for non-login, find Qt dynamically +SHELL ["/bin/bash", "-lc"] # ---------- Git safe directory (avoids “detected dubious ownership”) ---------- RUN git config --global --add safe.directory /project/source diff --git a/deploy/linux/appimagecraft.yml b/deploy/linux/appimagecraft.yml index b8b2c5397ba3..84123068750f 100644 --- a/deploy/linux/appimagecraft.yml +++ b/deploy/linux/appimagecraft.yml @@ -8,7 +8,8 @@ build: cmake: source_dir: src/ extra_variables: - - Qt6_ROOT=/home/runner/work/_temp/Qt/6.10.1/gcc_64 + # Qt6_ROOT should be set via environment variable from centralized config + - Qt6_ROOT=${QT_ROOT_DIR:-/opt/Qt/gcc_64} environment: BUILD_TYPE: Release diff --git a/deploy/vagrant/.vagrantconfig.yml b/deploy/vagrant/.vagrantconfig.yml index ed7ecd7541bb..0f86d6b8f06d 100644 --- a/deploy/vagrant/.vagrantconfig.yml +++ b/deploy/vagrant/.vagrantconfig.yml @@ -1,12 +1,9 @@ +# Vagrant configuration for QGroundControl development VM +# NOTE: Qt version is read from .github/build-config.json by Vagrantfile configs: dev: 'qt_deps_unpack_parent_dir': '/home/vagrant' - 'qt_deps_unpack_dir': '/home/vagrant/Qt' - 'qt_deps_bin_unpack_dir': '/home/vagrant/Qt/6.10.1/gcc_64/bin' - 'qt_deps_lib_unpack_dir': '/home/vagrant/Qt/6.10.1/gcc_64/lib' - 'qt_deps_plugins_unpack_dir': '/home/vagrant/Qt/6.10.1/gcc_64/plugins' - 'qt_deps_qml_unpack_dir': '/home/vagrant/Qt/6.10.1/gcc_64/qml' 'project_root_dir': '/vagrant' diff --git a/deploy/vagrant/Vagrantfile b/deploy/vagrant/Vagrantfile index 68eb3f24a54d..e33cfafa84ed 100644 --- a/deploy/vagrant/Vagrantfile +++ b/deploy/vagrant/Vagrantfile @@ -2,11 +2,16 @@ # vi: set ft=ruby : require 'yaml' +require 'json' current_dir = File.dirname(File.expand_path(__FILE__)) configfile = YAML.load_file("#{current_dir}/.vagrantconfig.yml") yaml_config = configfile['configs']['dev'] +# Load centralized build config +build_config_path = File.join(current_dir, '../../.github/build-config.json') +build_config = JSON.parse(File.read(build_config_path)) + env_global = [ 'JOBS=4', 'SHADOW_BUILD_DIR=/tmp/shadow_build_dir', @@ -91,10 +96,10 @@ Vagrant.configure(2) do |config| apt-get install -y patchelf dir="%{qt_deps_unpack_dir}" - version="6.10.1" + version="%{qt_version}" host="linux" target="desktop" - modules="qtcharts qtlocation qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors qtscxml" + modules="%{qt_modules}" su - vagrant -c "rm -rf ${dir}" su - vagrant -c "mkdir -p ${dir}" su - vagrant -c "python3 -m aqt install-qt -O ${dir} ${host} ${target} ${version} -m ${modules}" @@ -144,7 +149,6 @@ echo '* soft nofile 2048' >/etc/security/limits.d/file config.vm.provision "dev", type: "shell", inline: $config_shell % { :shadow_build_dir => yaml_config['shadow_build_dir'], - :qt_deps_tarball => yaml_config['qt_deps_tarball'], :spec => yaml_config['spec'], :apt_pkgs => (packages).join(' '), :build_env => env_global.select { |item| item.is_a?(String) }.join(' '), @@ -152,16 +156,15 @@ echo '* soft nofile 2048' >/etc/security/limits.d/file :project_root_dir => yaml_config['project_root_dir'], :qt_deps_unpack_parent_dir => yaml_config['qt_deps_unpack_parent_dir'], :qt_deps_unpack_dir => yaml_config['qt_deps_unpack_dir'], - :qt_deps_bin_unpack_dir => yaml_config['qt_deps_bin_unpack_dir'], - :qt_deps_lib_unpack_dir => yaml_config['qt_deps_lib_unpack_dir'], - :qt_deps_plugins_unpack_dir => yaml_config['qt_deps_plugins_unpack_dir'], - :qt_deps_qml_unpack_dir => yaml_config['qt_deps_qml_unpack_dir'], :qt_deps_dir => yaml_config['qt_deps_dir'], :qt_deps_bin_dir => yaml_config['qt_deps_bin_dir'], :qt_deps_lib_dir => yaml_config['qt_deps_lib_dir'], :qt_deps_plugins_dir => yaml_config['qt_deps_plugins_dir'], :qt_deps_qml_dir => yaml_config['qt_deps_qml_dir'], + + :qt_version => build_config['qt_version'], + :qt_modules => build_config['qt_modules'], } diff --git a/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt b/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt index 40d318671e2d..877d1da3b19d 100644 --- a/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt +++ b/src/VideoManager/VideoReceiver/GStreamer/gstqml6gl/CMakeLists.txt @@ -9,10 +9,9 @@ qt_add_library(gstqml6gl STATIC) # Platform-Specific GStreamer Linking # ---------------------------------------------------------------------------- if(MACOS) - # NOTE: Using FindGStreamer.cmake is currently bypassed on macOS - # Using hardwired framework path as a workaround + # macOS uses framework path directly (FindGStreamer.cmake bypassed) find_library(GSTREAMER_FRAMEWORK GStreamer) - set(GST_REQUIRED_FRAMEWORK_VERSION 1.24.13) + set(GST_REQUIRED_FRAMEWORK_VERSION ${QGC_CONFIG_GSTREAMER_VERSION}) set(GST_PLUGINS_VERSION ${GST_REQUIRED_FRAMEWORK_VERSION}) set(GSTREAMER_FRAMEWORK_PATH "/Library/Frameworks/GStreamer.framework") if(NOT EXISTS "${GSTREAMER_FRAMEWORK_PATH}") diff --git a/tools/setup/install-dependencies-osx.sh b/tools/setup/install-dependencies-osx.sh index 36e2b658a943..5be8111ecd41 100755 --- a/tools/setup/install-dependencies-osx.sh +++ b/tools/setup/install-dependencies-osx.sh @@ -1,5 +1,22 @@ #! /usr/bin/env bash +set -e + +# Source build config (required - no fallbacks) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [[ -f "$SCRIPT_DIR/read-config.sh" ]]; then + source "$SCRIPT_DIR/read-config.sh" +else + echo "Error: read-config.sh not found" >&2 + exit 1 +fi + +# Verify required variables are set +if [[ -z "${GSTREAMER_VERSION:-}" ]]; then + echo "Error: GSTREAMER_VERSION must be set (check build-config.json)" >&2 + exit 1 +fi + if ! command -v brew &> /dev/null then # install Homebrew if not installed yet @@ -12,7 +29,7 @@ brew install cmake ninja ccache git pkgconf create-dmg mold # Install GStreamer GST_URL=https://gstreamer.freedesktop.org/data/pkg/osx -GST_VERSION=1.24.13 +GST_VERSION="$GSTREAMER_VERSION" GST_PKG=gstreamer-1.0-$GST_VERSION-universal.pkg GST_DEV_PKG=gstreamer-1.0-devel-$GST_VERSION-universal.pkg pushd "$TMPDIR" || exit diff --git a/tools/setup/install-dependencies-windows.ps1 b/tools/setup/install-dependencies-windows.ps1 index d87111fab839..0d2b0738eed1 100644 --- a/tools/setup/install-dependencies-windows.ps1 +++ b/tools/setup/install-dependencies-windows.ps1 @@ -3,17 +3,35 @@ Install GStreamer (x64 only) and the latest Vulkan SDK on Windows. .DESCRIPTION - • Must run elevated. - • Downloads installers to $env:TEMP and removes them afterwards. - • Sets the required environment variables and updates PATH. + - Must run elevated. + - Downloads installers to $env:TEMP and removes them afterwards. + - Sets the required environment variables and updates PATH. #> +# ──────────────────────────────── +# 0) Source build config (required - no fallbacks) +# ──────────────────────────────── +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$configScript = Join-Path $scriptDir "read-config.ps1" +if (Test-Path $configScript) { + . $configScript +} else { + Write-Error "read-config.ps1 not found" + exit 1 +} + +# Verify required variables are set (GStreamer Windows version) +if (-not $env:GSTREAMER_WINDOWS_VERSION) { + Write-Error "GSTREAMER_WINDOWS_VERSION must be set (check build-config.json)" + exit 1 +} + # ──────────────────────────────── # 1) Elevation # ──────────────────────────────── if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { - Write-Warning "Restarting with Administrator privileges…" + Write-Warning "Restarting with Administrator privileges..." Start-Process pwsh.exe -Verb RunAs -ArgumentList "-NoProfile","-ExecutionPolicy Bypass","-File `"$PSCommandPath`"" exit } @@ -27,9 +45,9 @@ Write-Host "`n==> Detected architecture: $arch" # 2) GStreamer config (x64 only) # ──────────────────────────────── # Note: Must Use QtMultimedia VideoReceiver or build GStreamer manually for Arm64 -$installGst = $arch -eq 'AMD64' # treat “x64/AMD64” as the only GS­treamer target +$installGst = $arch -eq 'AMD64' # treat "x64/AMD64" as the only GStreamer target if ($installGst) { - $gstVersion = '1.22.12' + $gstVersion = $env:GSTREAMER_WINDOWS_VERSION $gstPrefix = 'C:\gstreamer\1.0\msvc_x86_64' $gstBaseUrl = "https://gstreamer.freedesktop.org/data/pkg/windows/$gstVersion/msvc" $gstRuntime = Join-Path $tempDir 'gstreamer-runtime.msi' diff --git a/tools/setup/install-qt-debian.sh b/tools/setup/install-qt-debian.sh index 8831fc356a9d..68cdb80f264c 100755 --- a/tools/setup/install-qt-debian.sh +++ b/tools/setup/install-qt-debian.sh @@ -2,15 +2,29 @@ set -e -QT_VERSION="${QT_VERSION:-6.10.1}" +# Source build config (required - no fallbacks) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [[ -f "$SCRIPT_DIR/read-config.sh" ]]; then + source "$SCRIPT_DIR/read-config.sh" +else + echo "Error: read-config.sh not found" >&2 + exit 1 +fi + +# Verify required variables are set +if [[ -z "${QT_VERSION:-}" ]] || [[ -z "${QT_MODULES:-}" ]]; then + echo "Error: QT_VERSION and QT_MODULES must be set (check build-config.json)" >&2 + exit 1 +fi + +# Platform defaults (can be overridden via environment) QT_PATH="${QT_PATH:-/opt/Qt}" QT_HOST="${QT_HOST:-linux}" QT_TARGET="${QT_TARGET:-desktop}" QT_ARCH="${QT_ARCH:-linux_gcc_64}" QT_ARCH_DIR="${QT_ARCH_DIR:-gcc_64}" QT_ROOT_DIR="${QT_ROOT_DIR:-${QT_PATH}/${QT_VERSION}/${QT_ARCH_DIR}}" -QT_MODULES_STR="${QT_MODULES:-qtcharts qtlocation qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors qtscxml}" -IFS=' ' read -r -a QT_MODULES <<< "$QT_MODULES_STR" +IFS=' ' read -r -a QT_MODULES_ARR <<< "$QT_MODULES" echo "QT_VERSION $QT_VERSION" echo "QT_PATH $QT_PATH" @@ -19,7 +33,7 @@ echo "QT_TARGET $QT_TARGET" echo "QT_ARCH $QT_ARCH" echo "QT_ARCH_DIR $QT_ARCH_DIR" echo "QT_ROOT_DIR $QT_ROOT_DIR" -echo "QT_MODULES ${QT_MODULES[*]}" +echo "QT_MODULES ${QT_MODULES_ARR[*]}" apt-get update -y --quiet apt-get install python3 python3-pip pipx -y @@ -29,15 +43,15 @@ pipx install ninja pipx ensurepath USER_BASE_BIN="$(python3 -m site --user-base)/bin" export PATH="$USER_BASE_BIN:$PATH" -aqt install-qt "${QT_HOST}" "${QT_TARGET}" "${QT_VERSION}" "${QT_ARCH}" -O "${QT_PATH}" -m "${QT_MODULES[@]}" +aqt install-qt "${QT_HOST}" "${QT_TARGET}" "${QT_VERSION}" "${QT_ARCH}" -O "${QT_PATH}" -m "${QT_MODULES_ARR[@]}" QT_ROOT_DIR=$(readlink -e "${QT_ROOT_DIR}") export QT_ROOT_DIR PATH=$(readlink -e "${QT_ROOT_DIR}/bin/"):$PATH export PATH -PKG_CONFIG_PATH=$(readlink -e "${QT_ROOT_DIR}/lib/pkgconfig"):$PKG_CONFIG_PATH +PKG_CONFIG_PATH=$(readlink -e "${QT_ROOT_DIR}/lib/pkgconfig"):${PKG_CONFIG_PATH:-} export PKG_CONFIG_PATH -LD_LIBRARY_PATH=$(readlink -e "${QT_ROOT_DIR}/lib"):$LD_LIBRARY_PATH +LD_LIBRARY_PATH=$(readlink -e "${QT_ROOT_DIR}/lib"):${LD_LIBRARY_PATH:-} export LD_LIBRARY_PATH QT_PLUGIN_PATH=$(readlink -e "${QT_ROOT_DIR}/plugins") export QT_PLUGIN_PATH diff --git a/tools/setup/install-qt-macos.sh b/tools/setup/install-qt-macos.sh index de5f579944e8..9558231818dc 100755 --- a/tools/setup/install-qt-macos.sh +++ b/tools/setup/install-qt-macos.sh @@ -1,22 +1,35 @@ #!/usr/bin/env bash -# Set defaults appropriate for macOS. -QT_VERSION="${QT_VERSION:-6.10.1}" +set -e + +# Source build config (required - no fallbacks) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +if [[ -f "$SCRIPT_DIR/read-config.sh" ]]; then + source "$SCRIPT_DIR/read-config.sh" +else + echo "Error: read-config.sh not found" >&2 + exit 1 +fi + +# Verify required variables are set +if [[ -z "${QT_VERSION:-}" ]] || [[ -z "${QT_MODULES:-}" ]]; then + echo "Error: QT_VERSION and QT_MODULES must be set (check build-config.json)" >&2 + exit 1 +fi + +# Platform defaults (can be overridden via environment) QT_PATH="${QT_PATH:-/opt/Qt}" QT_HOST="${QT_HOST:-mac}" QT_TARGET="${QT_TARGET:-desktop}" QT_ARCH="${QT_ARCH:-mac}" -QT_MODULES_STR="${QT_MODULES:-qtcharts qtlocation qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors qtscxml}" -IFS=' ' read -r -a QT_MODULES <<< "$QT_MODULES_STR" - -set -e +IFS=' ' read -r -a QT_MODULES_ARR <<< "$QT_MODULES" echo "QT_VERSION: $QT_VERSION" echo "QT_PATH: $QT_PATH" echo "QT_HOST: $QT_HOST" echo "QT_TARGET: $QT_TARGET" echo "QT_ARCH: $QT_ARCH" -echo "QT_MODULES: ${QT_MODULES[*]}" +echo "QT_MODULES: ${QT_MODULES_ARR[*]}" # Update Homebrew and install Python 3 (if needed) brew update @@ -26,7 +39,7 @@ brew install python3 pip3 install --upgrade setuptools wheel py7zr ninja cmake aqtinstall # Use aqtinstall to download and install Qt. -aqt install-qt "${QT_HOST}" "${QT_TARGET}" "${QT_VERSION}" "${QT_ARCH}" -O "${QT_PATH}" -m "${QT_MODULES[@]}" +aqt install-qt "${QT_HOST}" "${QT_TARGET}" "${QT_VERSION}" "${QT_ARCH}" -O "${QT_PATH}" -m "${QT_MODULES_ARR[@]}" # macOS does not support GNU readlink -e. # We use realpath instead (or substitute with greadlink -f if needed). @@ -34,9 +47,9 @@ aqt install-qt "${QT_HOST}" "${QT_TARGET}" "${QT_VERSION}" "${QT_ARCH}" -O "${QT QT_BIN_DIR=$(realpath "${QT_PATH}/${QT_VERSION}/${QT_ARCH}/bin") export PATH="$QT_BIN_DIR:$PATH" QT_PKGCONFIG_DIR=$(realpath "${QT_PATH}/${QT_VERSION}/${QT_ARCH}/lib/pkgconfig") -export PKG_CONFIG_PATH="$QT_PKGCONFIG_DIR:$PKG_CONFIG_PATH" +export PKG_CONFIG_PATH="$QT_PKGCONFIG_DIR:${PKG_CONFIG_PATH:-}" QT_LIB_DIR=$(realpath "${QT_PATH}/${QT_VERSION}/${QT_ARCH}/lib") -export DYLD_LIBRARY_PATH="$QT_LIB_DIR:$DYLD_LIBRARY_PATH" +export DYLD_LIBRARY_PATH="$QT_LIB_DIR:${DYLD_LIBRARY_PATH:-}" QT_ROOT_DIR=$(realpath "${QT_PATH}/${QT_VERSION}/${QT_ARCH}") export QT_ROOT_DIR QT_PLUGIN_PATH=$(realpath "${QT_PATH}/${QT_VERSION}/${QT_ARCH}/plugins") diff --git a/tools/setup/install-qt-windows.ps1 b/tools/setup/install-qt-windows.ps1 index 68d84e485e25..9a41b1561dc9 100644 --- a/tools/setup/install-qt-windows.ps1 +++ b/tools/setup/install-qt-windows.ps1 @@ -5,19 +5,36 @@ .DESCRIPTION - Uses Python + pip to install helper packages (setuptools, wheel, py7zr, ninja, cmake, aqtinstall). - Runs `aqt install-qt` with the same modules list. - - Adjusts PATH and Qt‑related env vars for the current session. + - Adjusts PATH and Qt-related env vars for the current session. #> # ———————————————————————————————— -# 1) Defaults (env overrides supported) +# 0) Source build config (required - no fallbacks) # ———————————————————————————————— -$QT_VERSION = $env:QT_VERSION -or '6.10.1' -$QT_PATH = $env:QT_PATH -or 'C:\Qt' -$QT_HOST = $env:QT_HOST -or 'windows' -$QT_TARGET = $env:QT_TARGET -or 'desktop' -# Windows arch must be one of: win64_msvc2017_64, win64_msvc2019_64, win64_mingw81, etc. :contentReference[oaicite:0]{index=0} -$QT_ARCH = $env:QT_ARCH -or 'win64_msvc2022_64' -$QT_MODULES = $env:QT_MODULES -or 'qtcharts qtlocation qtpositioning qtspeech qt5compat qtmultimedia qtserialport qtimageformats qtshadertools qtconnectivity qtquick3d qtsensors qtscxml' +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$configScript = Join-Path $scriptDir "read-config.ps1" +if (Test-Path $configScript) { + . $configScript +} else { + Write-Error "read-config.ps1 not found" + exit 1 +} + +# Verify required variables are set +if (-not $env:QT_VERSION -or -not $env:QT_MODULES) { + Write-Error "QT_VERSION and QT_MODULES must be set (check build-config.json)" + exit 1 +} + +# ———————————————————————————————— +# 1) Platform defaults (can be overridden via environment) +# ———————————————————————————————— +$QT_VERSION = $env:QT_VERSION +$QT_PATH = if ($env:QT_PATH) { $env:QT_PATH } else { 'C:\Qt' } +$QT_HOST = if ($env:QT_HOST) { $env:QT_HOST } else { 'windows' } +$QT_TARGET = if ($env:QT_TARGET) { $env:QT_TARGET } else { 'desktop' } +$QT_ARCH = if ($env:QT_ARCH) { $env:QT_ARCH } else { 'win64_msvc2022_64' } +$QT_MODULES = $env:QT_MODULES Write-Host "Using:" Write-Host " QT_VERSION = $QT_VERSION" diff --git a/tools/setup/read-config.ps1 b/tools/setup/read-config.ps1 new file mode 100644 index 000000000000..cfc361945e56 --- /dev/null +++ b/tools/setup/read-config.ps1 @@ -0,0 +1,128 @@ +<# +.SYNOPSIS + Read build configuration from .github/build-config.json + +.DESCRIPTION + This script reads version variables from the centralized config file. + Dot-source this script to get the variables, or call with -Get to retrieve a single value. + +.PARAMETER Get + Get a single value by key name + +.EXAMPLE + . .\read-config.ps1 # Import all variables + .\read-config.ps1 -Get qt_version # Get single value +#> + +param( + [string]$Get +) + +# Find the repo root (location of .github/build-config.json) +function Find-RepoRoot { + param([string]$StartPath) + $dir = $StartPath + while ($dir -and $dir -ne [System.IO.Path]::GetPathRoot($dir)) { + $configPath = Join-Path $dir ".github\build-config.json" + if (Test-Path $configPath) { + return $dir + } + $dir = Split-Path $dir -Parent + } + return $null +} + +# Locate config file +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$localConfig = Join-Path $scriptDir "build-config.json" + +if (Test-Path $localConfig) { + $configFile = $localConfig +} else { + $repoRoot = Find-RepoRoot $scriptDir + if ($repoRoot) { + $configFile = Join-Path $repoRoot ".github\build-config.json" + } else { + Write-Error "Could not find build-config.json" + exit 1 + } +} + +# Read JSON config +try { + $config = Get-Content $configFile -Raw | ConvertFrom-Json +} catch { + Write-Error "Failed to parse JSON from $configFile : $_" + exit 1 +} + +# If -Get specified, return single value +if ($Get) { + $value = $config.PSObject.Properties[$Get].Value + if ($null -eq $value) { + Write-Error "Key '$Get' not found in config" + exit 1 + } + Write-Output $value + exit 0 +} + +# Export all configuration variables (only if not already set) +if (-not $env:QT_VERSION) { $env:QT_VERSION = $config.qt_version } +if (-not $env:QT_MODULES) { $env:QT_MODULES = $config.qt_modules } +if (-not $env:QT_MINIMUM_VERSION) { $env:QT_MINIMUM_VERSION = $config.qt_minimum_version } +if (-not $env:GSTREAMER_VERSION) { $env:GSTREAMER_VERSION = $config.gstreamer_version } +if (-not $env:GSTREAMER_WINDOWS_VERSION) { $env:GSTREAMER_WINDOWS_VERSION = $config.gstreamer_windows_version } +if (-not $env:NDK_VERSION) { $env:NDK_VERSION = $config.ndk_version } +if (-not $env:NDK_FULL_VERSION) { $env:NDK_FULL_VERSION = $config.ndk_full_version } +if (-not $env:JAVA_VERSION) { $env:JAVA_VERSION = $config.java_version } +if (-not $env:ANDROID_PLATFORM) { $env:ANDROID_PLATFORM = $config.android_platform } +if (-not $env:ANDROID_MIN_SDK) { $env:ANDROID_MIN_SDK = $config.android_min_sdk } +if (-not $env:ANDROID_BUILD_TOOLS) { $env:ANDROID_BUILD_TOOLS = $config.android_build_tools } +if (-not $env:ANDROID_CMDLINE_TOOLS) { $env:ANDROID_CMDLINE_TOOLS = $config.android_cmdline_tools } +if (-not $env:XCODE_VERSION) { $env:XCODE_VERSION = $config.xcode_version } +if (-not $env:CCACHE_VERSION) { $env:CCACHE_VERSION = $config.ccache_version } +if (-not $env:CCACHE_MAX_SIZE) { $env:CCACHE_MAX_SIZE = $config.ccache_max_size } +if (-not $env:CLANG_FORMAT_VERSION) { $env:CLANG_FORMAT_VERSION = $config.clang_format_version } +if (-not $env:NODE_VERSION) { $env:NODE_VERSION = $config.node_version } + +# Also set script-scope variables for dot-sourcing +$script:QT_VERSION = $env:QT_VERSION +$script:QT_MODULES = $env:QT_MODULES +$script:QT_MINIMUM_VERSION = $env:QT_MINIMUM_VERSION +$script:GSTREAMER_VERSION = $env:GSTREAMER_VERSION +$script:GSTREAMER_WINDOWS_VERSION = $env:GSTREAMER_WINDOWS_VERSION +$script:NDK_VERSION = $env:NDK_VERSION +$script:NDK_FULL_VERSION = $env:NDK_FULL_VERSION +$script:JAVA_VERSION = $env:JAVA_VERSION +$script:ANDROID_PLATFORM = $env:ANDROID_PLATFORM +$script:ANDROID_MIN_SDK = $env:ANDROID_MIN_SDK +$script:ANDROID_BUILD_TOOLS = $env:ANDROID_BUILD_TOOLS +$script:ANDROID_CMDLINE_TOOLS = $env:ANDROID_CMDLINE_TOOLS +$script:XCODE_VERSION = $env:XCODE_VERSION +$script:CCACHE_VERSION = $env:CCACHE_VERSION +$script:CCACHE_MAX_SIZE = $env:CCACHE_MAX_SIZE +$script:CLANG_FORMAT_VERSION = $env:CLANG_FORMAT_VERSION +$script:NODE_VERSION = $env:NODE_VERSION + +# Print config if running directly +if ($MyInvocation.InvocationName -ne '.') { + Write-Host "Build Configuration (from $configFile):" + Write-Host " QT_VERSION = $env:QT_VERSION" + Write-Host " QT_MODULES = $env:QT_MODULES" + Write-Host " QT_MINIMUM_VERSION = $env:QT_MINIMUM_VERSION" + Write-Host " GSTREAMER_VERSION = $env:GSTREAMER_VERSION" + Write-Host " GSTREAMER_WINDOWS_VERSION = $env:GSTREAMER_WINDOWS_VERSION" + Write-Host " NDK_VERSION = $env:NDK_VERSION" + Write-Host " NDK_FULL_VERSION = $env:NDK_FULL_VERSION" + Write-Host " JAVA_VERSION = $env:JAVA_VERSION" + Write-Host " ANDROID_PLATFORM = $env:ANDROID_PLATFORM" + Write-Host " ANDROID_MIN_SDK = $env:ANDROID_MIN_SDK" + Write-Host " ANDROID_BUILD_TOOLS = $env:ANDROID_BUILD_TOOLS" + Write-Host " ANDROID_CMDLINE_TOOLS = $env:ANDROID_CMDLINE_TOOLS" + Write-Host " XCODE_VERSION = $env:XCODE_VERSION" + Write-Host " CCACHE_VERSION = $env:CCACHE_VERSION" + Write-Host " CCACHE_MAX_SIZE = $env:CCACHE_MAX_SIZE" + Write-Host " CLANG_FORMAT_VERSION = $env:CLANG_FORMAT_VERSION" + Write-Host " NODE_VERSION = $env:NODE_VERSION" +} diff --git a/tools/setup/read-config.sh b/tools/setup/read-config.sh new file mode 100755 index 000000000000..633e783c9ec3 --- /dev/null +++ b/tools/setup/read-config.sh @@ -0,0 +1,125 @@ +#!/usr/bin/env bash +# +# Read build configuration from .github/build-config.json +# +# This script exports version variables from the centralized config file. +# Source this script to get the variables, or call with --get to retrieve a single value. +# +# Usage: +# source read-config.sh # Export all variables +# ./read-config.sh # Print all config values +# ./read-config.sh --get qt_version # Get single value +# +# Exports: +# QT_VERSION, QT_MINIMUM_VERSION, QT_MODULES, +# GSTREAMER_VERSION, GSTREAMER_ANDROID_VERSION, GSTREAMER_WINDOWS_VERSION, +# XCODE_VERSION, NDK_VERSION, NDK_FULL_VERSION, JAVA_VERSION, +# ANDROID_PLATFORM, ANDROID_MIN_SDK, ANDROID_BUILD_TOOLS, ANDROID_CMDLINE_TOOLS, +# CCACHE_VERSION, CCACHE_MAX_SIZE, CLANG_FORMAT_VERSION, NODE_VERSION + +set -euo pipefail + +# Find the repo root (location of .github/build-config.json) +find_repo_root() { + local dir="$1" + while [[ "$dir" != "/" ]]; do + if [[ -f "$dir/.github/build-config.json" ]]; then + echo "$dir" + return 0 + fi + dir=$(dirname "$dir") + done + return 1 +} + +# Get a value from the JSON config +# Uses jq if available, falls back to Python for portability +get_config_value() { + local key="$1" + local config_file="$2" + + if command -v jq &> /dev/null; then + jq -r ".$key // empty" "$config_file" + elif command -v python3 &> /dev/null; then + python3 -c "import json,sys; print(json.load(open(sys.argv[1])).get(sys.argv[2], ''))" "$config_file" "$key" + else + echo "Error: Either jq or python3 is required" >&2 + exit 1 + fi +} + +# Main logic +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Check for config file in multiple locations: +# 1. Same directory as this script (for Docker builds where config is copied) +# 2. Repo root/.github/ (for normal builds) +if [[ -f "$SCRIPT_DIR/build-config.json" ]]; then + CONFIG_FILE="$SCRIPT_DIR/build-config.json" +elif REPO_ROOT=$(find_repo_root "$SCRIPT_DIR" 2>/dev/null); then + CONFIG_FILE="$REPO_ROOT/.github/build-config.json" +else + echo "Error: Could not find build-config.json" >&2 + exit 1 +fi + +# If called with --get, just print the value and exit +if [[ "${1:-}" == "--get" ]]; then + if [[ -z "${2:-}" ]]; then + echo "Usage: $0 --get " >&2 + echo "" >&2 + echo "Available keys:" >&2 + echo " qt_version, qt_modules, qt_minimum_version," >&2 + echo " gstreamer_version, gstreamer_android_version, gstreamer_windows_version," >&2 + echo " ndk_version, ndk_full_version, java_version," >&2 + echo " android_platform, android_min_sdk, android_build_tools, android_cmdline_tools," >&2 + echo " xcode_version, xcode_ios_version, ccache_version, ccache_max_size," >&2 + echo " clang_format_version, node_version, flatpak_gnome_version" >&2 + exit 1 + fi + get_config_value "$2" "$CONFIG_FILE" + exit 0 +fi + +# Export all configuration variables (only if not already set) +export QT_VERSION="${QT_VERSION:-$(get_config_value qt_version "$CONFIG_FILE")}" +export QT_MINIMUM_VERSION="${QT_MINIMUM_VERSION:-$(get_config_value qt_minimum_version "$CONFIG_FILE")}" +export QT_MODULES="${QT_MODULES:-$(get_config_value qt_modules "$CONFIG_FILE")}" +export GSTREAMER_VERSION="${GSTREAMER_VERSION:-$(get_config_value gstreamer_version "$CONFIG_FILE")}" +export GSTREAMER_ANDROID_VERSION="${GSTREAMER_ANDROID_VERSION:-$(get_config_value gstreamer_android_version "$CONFIG_FILE")}" +export GSTREAMER_WINDOWS_VERSION="${GSTREAMER_WINDOWS_VERSION:-$(get_config_value gstreamer_windows_version "$CONFIG_FILE")}" +export XCODE_VERSION="${XCODE_VERSION:-$(get_config_value xcode_version "$CONFIG_FILE")}" +export NDK_VERSION="${NDK_VERSION:-$(get_config_value ndk_version "$CONFIG_FILE")}" +export NDK_FULL_VERSION="${NDK_FULL_VERSION:-$(get_config_value ndk_full_version "$CONFIG_FILE")}" +export JAVA_VERSION="${JAVA_VERSION:-$(get_config_value java_version "$CONFIG_FILE")}" +export ANDROID_PLATFORM="${ANDROID_PLATFORM:-$(get_config_value android_platform "$CONFIG_FILE")}" +export ANDROID_MIN_SDK="${ANDROID_MIN_SDK:-$(get_config_value android_min_sdk "$CONFIG_FILE")}" +export ANDROID_BUILD_TOOLS="${ANDROID_BUILD_TOOLS:-$(get_config_value android_build_tools "$CONFIG_FILE")}" +export ANDROID_CMDLINE_TOOLS="${ANDROID_CMDLINE_TOOLS:-$(get_config_value android_cmdline_tools "$CONFIG_FILE")}" +export CCACHE_VERSION="${CCACHE_VERSION:-$(get_config_value ccache_version "$CONFIG_FILE")}" +export CCACHE_MAX_SIZE="${CCACHE_MAX_SIZE:-$(get_config_value ccache_max_size "$CONFIG_FILE")}" +export CLANG_FORMAT_VERSION="${CLANG_FORMAT_VERSION:-$(get_config_value clang_format_version "$CONFIG_FILE")}" +export NODE_VERSION="${NODE_VERSION:-$(get_config_value node_version "$CONFIG_FILE")}" + +# Print config if running directly (not sourced) +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + echo "Build Configuration (from $CONFIG_FILE):" + echo " QT_VERSION=$QT_VERSION" + echo " QT_MINIMUM_VERSION=$QT_MINIMUM_VERSION" + echo " QT_MODULES=$QT_MODULES" + echo " GSTREAMER_VERSION=$GSTREAMER_VERSION" + echo " GSTREAMER_ANDROID_VERSION=$GSTREAMER_ANDROID_VERSION" + echo " GSTREAMER_WINDOWS_VERSION=$GSTREAMER_WINDOWS_VERSION" + echo " XCODE_VERSION=$XCODE_VERSION" + echo " NDK_VERSION=$NDK_VERSION" + echo " NDK_FULL_VERSION=$NDK_FULL_VERSION" + echo " JAVA_VERSION=$JAVA_VERSION" + echo " ANDROID_PLATFORM=$ANDROID_PLATFORM" + echo " ANDROID_MIN_SDK=$ANDROID_MIN_SDK" + echo " ANDROID_BUILD_TOOLS=$ANDROID_BUILD_TOOLS" + echo " ANDROID_CMDLINE_TOOLS=$ANDROID_CMDLINE_TOOLS" + echo " CCACHE_VERSION=$CCACHE_VERSION" + echo " CCACHE_MAX_SIZE=$CCACHE_MAX_SIZE" + echo " CLANG_FORMAT_VERSION=$CLANG_FORMAT_VERSION" + echo " NODE_VERSION=$NODE_VERSION" +fi