name: Build plugin on: push: branches: - main tags: - 'v*' pull_request: branches: - main env: PLUGIN_NAME: QodeAssist QT_VERSION: 6.8.3 QT_CREATOR_VERSION: 16.0.1 MACOS_DEPLOYMENT_TARGET: "11.0" CMAKE_VERSION: "3.29.6" NINJA_VERSION: "1.12.1" jobs: build: name: ${{ matrix.config.name }} runs-on: ${{ matrix.config.os }} outputs: tag: ${{ steps.git.outputs.tag }} strategy: matrix: config: - { name: "Windows Latest MSVC", artifact: "Windows-x64", os: windows-latest, platform: windows_x64, cc: "cl", cxx: "cl", environment_script: "C:/Program Files/Microsoft Visual Studio/2022/Enterprise/VC/Auxiliary/Build/vcvars64.bat", } - { name: "Ubuntu 22.04 GCC", artifact: "Linux-x64", os: ubuntu-22.04, platform: linux_x64, cc: "gcc", cxx: "g++" } - { name: "macOS Latest Clang", artifact: "macOS-universal", os: macos-latest, platform: mac_x64, cc: "clang", cxx: "clang++" } steps: - uses: actions/checkout@v4 - name: Checkout submodules id: git shell: cmake -P {0} run: | if (${{github.ref}} MATCHES "tags/v(.*)") file(APPEND "$ENV{GITHUB_OUTPUT}" "tag=${CMAKE_MATCH_1}") else() file(APPEND "$ENV{GITHUB_OUTPUT}" "tag=${{github.run_id}}") endif() - name: Download Ninja and CMake uses: lukka/get-cmake@latest with: cmakeVersion: ${{ env.CMAKE_VERSION }} ninjaVersion: ${{ env.NINJA_VERSION }} - name: Install dependencies shell: cmake -P {0} run: | if ("${{ matrix.config.platform }}" STREQUAL "linux_x64") execute_process( COMMAND sudo apt update ) execute_process( COMMAND sudo apt install # build dependencies libgl1-mesa-dev libgtest-dev libgmock-dev # runtime dependencies for tests (Qt is downloaded outside package manager, # thus minimal dependencies must be installed explicitly) libsecret-1-0 libxcb-cursor0 libxcb-icccm4 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-xfixes0 libxcb-xkb1 libxkbcommon-x11-0 xvfb RESULT_VARIABLE result ) if (NOT result EQUAL 0) message(FATAL_ERROR "Failed to install dependencies") endif() elseif ("${{ matrix.config.platform }}" STREQUAL "linux_arm64") execute_process(COMMAND sudo dpkg --add-architecture arm64) # TODO: Check to see if the azure.ubuntu added arm64 support execute_process(COMMAND sudo apt-get install -y bash curl apt-transport-https ca-certificates) execute_process(COMMAND sudo curl https://raw.githubusercontent.com/vegardit/fast-apt-mirror.sh/v1/fast-apt-mirror.sh -o /usr/local/bin/fast-apt-mirror.sh) execute_process(COMMAND sudo chmod 755 /usr/local/bin/fast-apt-mirror.sh) #execute_process(COMMAND sudo /usr/local/bin/fast-apt-mirror.sh set https://mirrors.ocf.berkeley.edu/ubuntu-ports/) execute_process(COMMAND sudo /usr/local/bin/fast-apt-mirror.sh set https://mirror.kumi.systems/ubuntu-ports/) execute_process( COMMAND sudo apt-get update ) execute_process( COMMAND sudo apt-get install -y crossbuild-essential-arm64 libgl1-mesa-dev:arm64 RESULT_VARIABLE result ) if (NOT result EQUAL 0) message(FATAL_ERROR "Failed to install dependencies") endif() endif() - name: Download Qt id: qt shell: cmake -P {0} run: | set(qt_version "$ENV{QT_VERSION}") function(download_qt platform export_qt_dir) string(REPLACE "." "" qt_version_dotless "${qt_version}") if (platform STREQUAL "windows_x64") set(url_os "windows_x86") set(compiler_id "win64_msvc2022_64") elseif (platform STREQUAL "windows_arm64") set(url_os "windows_x86") set(compiler_id "win64_msvc2022_arm64_cross_compiled") elseif (platform STREQUAL "linux_x64") set(url_os "linux_x64") set(compiler_id "linux_gcc_64") elseif (platform STREQUAL "linux_arm64") set(url_os "linux_arm64") set(compiler_id "linux_gcc_arm64") elseif (platform STREQUAL "mac_x64") set(url_os "mac_x64") set(compiler_id "clang_64") endif() set(qt_base_url "https://download.qt.io/online/qtsdkrepository/${url_os}/desktop/qt6_${qt_version_dotless}/qt6_${qt_version_dotless}") file(DOWNLOAD "${qt_base_url}/Updates.xml" ./Updates.xml SHOW_PROGRESS) file(READ ./Updates.xml updates_xml) # get the package sections, only for given compiler, without the "debug info" ones string(REGEX REPLACE "" ";" sections "${updates_xml}") list(FILTER sections EXCLUDE REGEX ".*debug.*") list(FILTER sections INCLUDE REGEX ".*${compiler_id}.*") # Save the path for other steps file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt/${platform}" qt_dir) if (export_qt_dir) file(APPEND "$ENV{GITHUB_OUTPUT}" "qt_dir=${qt_dir}") endif() function(get_sub_url outvar module) set(filtered ${sections}) list(FILTER filtered INCLUDE REGEX ".*${module}.*") list(LENGTH filtered count) if (count LESS 1) set(${outvar} "" PARENT_SCOPE) return() endif() list(GET filtered 0 section) string(REGEX MATCH "(.*)" match "${section}") set(name ${CMAKE_MATCH_1}) string(REGEX MATCH "(.*)" match "${section}") set(version ${CMAKE_MATCH_1}) string(REGEX MATCH ".*(${module}[^,]+).*" match "${section}") set(archive ${CMAKE_MATCH_1}) set(${outvar} "${name}/${version}${archive}" PARENT_SCOPE) endfunction() message("Downloading Qt to ${qt_dir}") function(downloadAndExtract module subdir) file(MAKE_DIRECTORY "${qt_dir}/${subdir}") set(archive "${module}.7z") get_sub_url(sub_url ${module}) set(url "${qt_base_url}/${sub_url}") message("Downloading ${module} from ${url}") message("... extracting to ${qt_dir}/${subdir}") file(DOWNLOAD "${url}" "$ENV{GITHUB_WORKSPACE}/${archive}" SHOW_PROGRESS) execute_process(COMMAND ${CMAKE_COMMAND} -E tar xvf "$ENV{GITHUB_WORKSPACE}/${archive}" WORKING_DIRECTORY "${qt_dir}/${subdir}") endfunction() foreach(package qtbase qtdeclarative qt5compat qtshadertools) downloadAndExtract(${package} "") endforeach() # uic depends on libicu*.so if ("${{ runner.os }}" STREQUAL "Linux") downloadAndExtract("icu" "lib") endif() execute_process(COMMAND ${qt_dir}/bin/qmake -query) endfunction() if ("${{ matrix.config.platform }}" STREQUAL "windows_x64") download_qt(windows_x64 TRUE) elseif ("${{ matrix.config.platform }}" STREQUAL "windows_arm64") download_qt(windows_x64 FALSE) download_qt(windows_arm64 TRUE) elseif ("${{ matrix.config.platform }}" STREQUAL "linux_x64") download_qt(linux_x64 TRUE) elseif ("${{ matrix.config.platform }}" STREQUAL "linux_arm64") download_qt(linux_x64 FALSE) download_qt(linux_arm64 TRUE) elseif ("${{ runner.os }}" STREQUAL "macOS") download_qt(mac_x64 TRUE) endif() - name: Download Qt Creator id: qt_creator uses: qt-creator/install-dev-package@v2.0 with: version: ${{ env.QT_CREATOR_VERSION }} unzip-to: 'qtcreator' platform: ${{ matrix.config.platform }} - name: Build shell: cmake -P {0} run: | set(ENV{CC} ${{ matrix.config.cc }}) set(ENV{CXX} ${{ matrix.config.cxx }}) set(ENV{MACOSX_DEPLOYMENT_TARGET} "${{ env.MACOS_DEPLOYMENT_TARGET }}") if ("${{ runner.os }}" STREQUAL "Windows" AND NOT "x${{ matrix.config.environment_script }}" STREQUAL "x") execute_process( COMMAND "${{ matrix.config.environment_script }}" && set OUTPUT_FILE environment_script_output.txt ) file(STRINGS environment_script_output.txt output_lines) foreach(line IN LISTS output_lines) if (line MATCHES "^([a-zA-Z0-9_-]+)=(.*)$") set(ENV{${CMAKE_MATCH_1}} "${CMAKE_MATCH_2}") endif() endforeach() endif() set(ENV{NINJA_STATUS} "[%f/%t %o/sec] ") if ("${{ runner.os }}" STREQUAL "macOS") set(ENV{CMAKE_OSX_ARCHITECTURES} "x86_64;arm64") endif() set(build_plugin_py "scripts/build_plugin.py") foreach(dir "share/qtcreator/scripts" "Qt Creator.app/Contents/Resources/scripts" "Contents/Resources/scripts") if(EXISTS "${{ steps.qt_creator.outputs.path }}/${dir}/build_plugin.py") set(build_plugin_py "${dir}/build_plugin.py") break() endif() endforeach() if ("${{ matrix.config.platform }}" STREQUAL "windows_arm64") file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt/windows_x64" qt_host_dir) set(additional_config "--add-config=-DQT_HOST_PATH=${qt_host_dir}") elseif ("${{ matrix.config.platform }}" STREQUAL "linux_arm64") file(TO_CMAKE_PATH "$ENV{GITHUB_WORKSPACE}/qt/linux_x64" qt_host_dir) set(additional_config "--add-config=-DQT_HOST_PATH=${qt_host_dir}") endif() execute_process( COMMAND python -u "${{ steps.qt_creator.outputs.path }}/${build_plugin_py}" --name "$ENV{PLUGIN_NAME}-$ENV{QT_CREATOR_VERSION}-${{ matrix.config.artifact }}" --src . --build build --qt-path "${{ steps.qt.outputs.qt_dir }}" --qtc-path "${{ steps.qt_creator.outputs.path }}" --output-path "$ENV{GITHUB_WORKSPACE}" ${additional_config} RESULT_VARIABLE result ) if (NOT result EQUAL 0) string(REGEX MATCH "FAILED:.*$" error_message "${output}") string(REPLACE "\n" "%0A" error_message "${error_message}") message("::error::${error_message}") message(FATAL_ERROR "Build failed") endif() - name: Upload uses: actions/upload-artifact@v4 with: path: ./${{ env.PLUGIN_NAME }}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}.7z name: ${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-${{ matrix.config.artifact }}.7z # The json is the same for all platforms, but we need to save one - name: Upload plugin json if: matrix.config.platform == 'linux_x64' uses: actions/upload-artifact@v4 with: name: ${{ env.PLUGIN_NAME }}.json path: ./build/build/${{ env.PLUGIN_NAME }}.json - name: Run unit tests if: startsWith(matrix.config.os, 'ubuntu') run: | xvfb-run ./build/build/test/QodeAssistTest release: if: contains(github.ref, 'tags/v') runs-on: ubuntu-22.04 needs: [build] steps: - name: Download artifacts uses: actions/download-artifact@v4 with: path: release-with-dirs - name: Fixup artifacts run: | mkdir release mv release-with-dirs/*/* release/ - name: Create Release id: create_release uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: v${{ needs.build.outputs.tag }} files: | release/${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-Linux-x64.7z release/${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-macOS-universal.7z release/${{ env.PLUGIN_NAME}}-${{ env.QT_CREATOR_VERSION }}-Windows-x64.7z draft: false prerelease: false