From deef68ba93f50cba3e878a2a8880ff1f8ea54cde Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 17 Oct 2022 10:35:45 +0000 Subject: [PATCH 1/9] Update main.ts Fix dependencies for linux --- action/src/main.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action/src/main.ts b/action/src/main.ts index bd93700a..babfded3 100644 --- a/action/src/main.ts +++ b/action/src/main.ts @@ -243,7 +243,8 @@ const run = async (): Promise => { "libxcb-xfixes0", "libxcb-xinerama0", "libxcb1", - "libxkbcommon-x11-0", + "libxkbcommon-dev", + "libxcb-xkb-dev", ].join(" "); const updateCommand = "apt-get update"; const installCommand = `apt-get install ${dependencies} -y`; From e7b1548b297c9025f52196486b2c266559404818 Mon Sep 17 00:00:00 2001 From: Benjamin O Date: Wed, 14 Dec 2022 01:43:43 -0500 Subject: [PATCH 2/9] Test case for #165 --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b97d763..4ef09d13 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,7 @@ jobs: version: - "5.9.0" - "5.15.2" - - "6.2.0" + - "6" cache: - cached - uncached From 1f98f0fa1c3a60fae6d447876a339386b8b4c9ae Mon Sep 17 00:00:00 2001 From: Benjamin O Date: Wed, 14 Dec 2022 02:06:59 -0500 Subject: [PATCH 3/9] try to naively deal with weird input formats --- action/src/main.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/action/src/main.ts b/action/src/main.ts index babfded3..400bc272 100644 --- a/action/src/main.ts +++ b/action/src/main.ts @@ -85,7 +85,20 @@ class Inputs { throw TypeError(`target: "${target}" is not one of "desktop" | "android" | "ios"`); } - this.version = core.getInput("version"); + // An attempt to sanitize non-straightforward version number input + let version = core.getInput("version"); + const dots = version.match(/\./g).length; + const desiredDotCount = 2; + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + if (dots < desiredDotCount && version.slice(-1) !== "*") { + version = version.concat(".*"); + } else if (dots > desiredDotCount) { + throw TypeError( + `version: "${version}$ is a malformed semantic version: must be formatted like "6.2.0" or "6.*"` + ); + } + + this.version = version; this.arch = core.getInput("arch"); // Set arch automatically if omitted From b47881db4e4c0a543d66e3e575f47fd495d779a8 Mon Sep 17 00:00:00 2001 From: Benjamin O Date: Wed, 14 Dec 2022 02:09:49 -0500 Subject: [PATCH 4/9] this time it compiles! --- action/lib/main.js | 88 +++++++++++++++++++++++++--------------------- action/src/main.ts | 2 +- package-lock.json | 6 ++++ 3 files changed, 55 insertions(+), 41 deletions(-) create mode 100644 package-lock.json diff --git a/action/lib/main.js b/action/lib/main.js index 7cb2c343..a7516256 100644 --- a/action/lib/main.js +++ b/action/lib/main.js @@ -94,7 +94,18 @@ class Inputs { else { throw TypeError(`target: "${target}" is not one of "desktop" | "android" | "ios"`); } - this.version = core.getInput("version"); + // An attempt to sanitize non-straightforward version number input + let version = core.getInput("version"); + const dots = version.match(/\./g).length; + const desiredDotCount = 2; + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + if (dots < desiredDotCount && version.slice(-1) !== "*") { + version = version.concat(".*"); + } + else if (dots > desiredDotCount) { + throw TypeError(`version: "${version}$ is a malformed semantic version: must be formatted like "6.2.0" or "6.*"`); + } + this.version = version; this.arch = core.getInput("arch"); // Set arch automatically if omitted if (!this.arch) { @@ -113,7 +124,13 @@ class Inputs { } } else if (this.target === "android") { - this.arch = "android_armv7"; + if (compareVersions(this.version, ">=", "5.14.0") && + compareVersions(this.version, "<", "6.0.0")) { + this.arch = "android"; + } + else { + this.arch = "android_armv7"; + } } } const dir = core.getInput("dir") || process.env.RUNNER_WORKSPACE; @@ -163,7 +180,6 @@ class Inputs { } this.cache = Inputs.getBoolInput("cache"); this.cacheKeyPrefix = core.getInput("cache-key-prefix"); - this.manuallyCached = Inputs.getBoolInput("manually-cached"); this.toolsOnly = Inputs.getBoolInput("tools-only"); this.setEnv = Inputs.getBoolInput("set-env"); this.aqtVersion = core.getInput("aqtversion"); @@ -237,7 +253,8 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () { "libxcb-xfixes0", "libxcb-xinerama0", "libxcb1", - "libxkbcommon-x11-0", + "libxkbcommon-dev", + "libxcb-xkb-dev", ].join(" "); const updateCommand = "apt-get update"; const installCommand = `apt-get install ${dependencies} -y`; @@ -254,23 +271,17 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () { // Restore internal cache let internalCacheHit = false; if (inputs.cache) { - if (inputs.manuallyCached) { - core.warning("Automatic cache disabled because manual cache is enabled"); + const cacheHitKey = yield cache.restoreCache([inputs.dir], inputs.cacheKey); + if (cacheHitKey) { + core.info(`Automatic cache hit with key "${cacheHitKey}"`); + internalCacheHit = true; } else { - const cacheHitKey = yield cache.restoreCache([inputs.dir], inputs.cacheKey); - if (cacheHitKey) { - core.info(`Automatic cache hit with key "${cacheHitKey}"`); - internalCacheHit = true; - } - else { - core.info("Automatic cache miss, will cache this run"); - } + core.info("Automatic cache miss, will cache this run"); } } // Install Qt and tools if not cached - const hasCache = inputs.manuallyCached || internalCacheHit; - if (!hasCache) { + if (!internalCacheHit) { // 7-zip is required, and not included on macOS if (process.platform === "darwin") { yield (0, exec_1.exec)("brew install p7zip"); @@ -313,14 +324,9 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () { } } // Save automatic cache - if (!hasCache && inputs.cache) { - if (inputs.manuallyCached) { - core.warning("Automatic cache disabled because manual cache is enabled"); - } - else { - const cacheId = yield cache.saveCache([inputs.dir], inputs.cacheKey); - core.info(`Automatic cache saved with id ${cacheId}`); - } + if (!internalCacheHit && inputs.cache) { + const cacheId = yield cache.saveCache([inputs.dir], inputs.cacheKey); + core.info(`Automatic cache saved with id ${cacheId}`); } // Set environment variables const qtPath = nativePath(glob.sync(`${inputs.versionDir}/**/*`)[0]); @@ -328,23 +334,25 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () { if (inputs.tools.length) { core.exportVariable("IQTA_TOOLS", nativePath(`${inputs.dir}/Tools`)); } - if (process.platform === "linux") { - setOrAppendEnvVar("LD_LIBRARY_PATH", nativePath(`${qtPath}/lib`)); - } - if (process.platform !== "win32") { - setOrAppendEnvVar("PKG_CONFIG_PATH", nativePath(`${qtPath}/lib/pkgconfig`)); - } - // If less than qt6, set qt5_dir variable, otherwise set qt6_dir variable - if (compareVersions(inputs.version, "<", "6.0.0")) { - core.exportVariable("Qt5_Dir", qtPath); // Incorrect name that was fixed, but kept around so it doesn't break anything - core.exportVariable("Qt5_DIR", qtPath); - } - else { - core.exportVariable("Qt6_DIR", qtPath); + if (!inputs.toolsOnly) { + if (process.platform === "linux") { + setOrAppendEnvVar("LD_LIBRARY_PATH", nativePath(`${qtPath}/lib`)); + } + if (process.platform !== "win32") { + setOrAppendEnvVar("PKG_CONFIG_PATH", nativePath(`${qtPath}/lib/pkgconfig`)); + } + // If less than qt6, set qt5_dir variable, otherwise set qt6_dir variable + if (compareVersions(inputs.version, "<", "6.0.0")) { + core.exportVariable("Qt5_Dir", qtPath); // Incorrect name that was fixed, but kept around so it doesn't break anything + core.exportVariable("Qt5_DIR", qtPath); + } + else { + core.exportVariable("Qt6_DIR", qtPath); + } + core.exportVariable("QT_PLUGIN_PATH", nativePath(`${qtPath}/plugins`)); + core.exportVariable("QML2_IMPORT_PATH", nativePath(`${qtPath}/qml`)); + core.addPath(nativePath(`${qtPath}/bin`)); } - core.exportVariable("QT_PLUGIN_PATH", nativePath(`${qtPath}/plugins`)); - core.exportVariable("QML2_IMPORT_PATH", nativePath(`${qtPath}/qml`)); - core.addPath(nativePath(`${qtPath}/bin`)); } } catch (error) { diff --git a/action/src/main.ts b/action/src/main.ts index 400bc272..ddba846b 100644 --- a/action/src/main.ts +++ b/action/src/main.ts @@ -87,7 +87,7 @@ class Inputs { // An attempt to sanitize non-straightforward version number input let version = core.getInput("version"); - const dots = version.match(/\./g).length; + const dots = version.match(/\./g)!.length; const desiredDotCount = 2; // eslint-disable-next-line @typescript-eslint/no-magic-numbers if (dots < desiredDotCount && version.slice(-1) !== "*") { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..62b5e5c4 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "install-qt-action", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} From 6def958c8290110e7a50645c4f3e9bcdca35df6e Mon Sep 17 00:00:00 2001 From: Benjamin O Date: Wed, 14 Dec 2022 10:40:46 -0500 Subject: [PATCH 5/9] revert the tries to sanitize versions for now --- .github/workflows/test.yml | 2 +- action/src/main.ts | 14 +------------- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4ef09d13..4b97d763 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,7 @@ jobs: version: - "5.9.0" - "5.15.2" - - "6" + - "6.2.0" cache: - cached - uncached diff --git a/action/src/main.ts b/action/src/main.ts index ddba846b..5c101ddd 100644 --- a/action/src/main.ts +++ b/action/src/main.ts @@ -86,19 +86,7 @@ class Inputs { } // An attempt to sanitize non-straightforward version number input - let version = core.getInput("version"); - const dots = version.match(/\./g)!.length; - const desiredDotCount = 2; - // eslint-disable-next-line @typescript-eslint/no-magic-numbers - if (dots < desiredDotCount && version.slice(-1) !== "*") { - version = version.concat(".*"); - } else if (dots > desiredDotCount) { - throw TypeError( - `version: "${version}$ is a malformed semantic version: must be formatted like "6.2.0" or "6.*"` - ); - } - - this.version = version; + this.version = core.getInput("version"); this.arch = core.getInput("arch"); // Set arch automatically if omitted From 3f9567eb0d9ea73fcd8ebff68d889e35ea096cbe Mon Sep 17 00:00:00 2001 From: Dave Dalcino Date: Mon, 16 Jan 2023 11:28:11 -0800 Subject: [PATCH 6/9] locate qt directory properly --- .github/workflows/test.yml | 25 ++++++++++++++----------- action/src/main.ts | 32 +++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b97d763..49a0d9c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,10 +36,13 @@ jobs: - windows-2019 - macos-11 - macos-12 - version: - - "5.9.0" - - "5.15.2" - - "6.2.0" + qt: + - version: "5.9.0" + requested: "5.9.0" + - version: "5.15.2" + requested: "5.15" + - version: "6.3.2" # Qt 6.3 is not an LTS version, so '6.3.*' always resolves to '6.3.2' + requested: "6.3.*" cache: - cached - uncached @@ -47,7 +50,7 @@ jobs: # Ubuntu 18 is not a supported target for Qt 6: https://www.qt.io/blog/qt6-development-hosts-and-targets exclude: - os: ubuntu-18.04 - version: "6.2.0" + qt: {version: "6.3.2", requested: "6.3.*"} steps: - uses: actions/checkout@v3 @@ -67,28 +70,28 @@ jobs: npm run build - name: Install Qt5 with options - if: startsWith(matrix.version, '5') + if: startsWith(matrix.qt.version, '5') uses: ./ with: modules: qtwebengine - version: ${{ matrix.version }} + version: ${{ matrix.qt.requested }} tools: tools_ifw tools_qtcreator,qt.tools.qtcreator cache: ${{ matrix.cache == 'cached' }} - name: Install Qt6 with options - if: startsWith(matrix.version, '6.2') + if: startsWith(matrix.qt.version, '6.3') uses: ./ with: # In Qt 6.2.0, qtwebengine requires qtpositioning and qtwebchannel modules: qtwebengine qtpositioning qtwebchannel - version: ${{ matrix.version }} + version: ${{ matrix.qt.requested }} tools: tools_ifw tools_qtcreator,qt.tools.qtcreator cache: ${{ matrix.cache == 'cached' }} - name: Configure test project on windows if: startsWith(matrix.os, 'windows') env: - QT_VERSION: ${{ matrix.version }} + QT_VERSION: ${{ matrix.qt.version }} run: | cd tests/TestWithModules for /f "delims=" %%d in ( 'vswhere.exe -latest -property installationPath' ) do @( call "%%d\VC\Auxiliary\Build\vcvars64.bat" ) @@ -99,7 +102,7 @@ jobs: - name: Configure test project on unix if: (!startsWith(matrix.os, 'windows')) env: - QT_VERSION: ${{ matrix.version }} + QT_VERSION: ${{ matrix.qt.version }} run: | cd tests/TestWithModules if [[ $QT_VERSION == 6* ]]; then diff --git a/action/src/main.ts b/action/src/main.ts index 5c101ddd..3f4c8e23 100644 --- a/action/src/main.ts +++ b/action/src/main.ts @@ -30,6 +30,30 @@ const execPython = async (command: string, args: readonly string[]): Promise { + // For 6.4.2/gcc, qmake is at 'installDir/6.4.2/gcc_64/bin/qmake'. + // This makes a list of all the viable arch directories that contain a qmake file. + const qtArchDirs = glob + .sync(`${installDir}/[0-9]*/*/bin/qmake*`) + .map((s) => s.replace(/\/bin\/qmake[^/]*$/, "")); + + // For Qt6 mobile and wasm installations, a standard desktop Qt installation + // must exist alongside the requested architecture. + // In these cases, we must select the first item that ends with 'android*', 'ios', or 'wasm*'. + const requiresParallelDesktop = qtArchDirs.filter((p) => + p.match(/6\.\d+\.\d+\/(android[^/]*|ios|wasm[^/]*)$/) + ); + if (requiresParallelDesktop.length) { + // NOTE: if multiple mobile/wasm installations coexist, this may not select the desired directory + return requiresParallelDesktop[0]; + } else if (!qtArchDirs.length) { + throw Error(`Failed to locate a Qt installation directory in ${installDir}`); + } else { + // NOTE: if multiple Qt installations exist, this may not select the desired directory + return qtArchDirs[0]; + } +}; + class Inputs { readonly host: "windows" | "mac" | "linux"; readonly target: "desktop" | "android" | "ios"; @@ -172,12 +196,6 @@ class Inputs { this.py7zrVersion = core.getInput("py7zrversion"); } - public get versionDir(): string { - // Weird naming scheme exception for qt 5.9 - const version = this.version === "5.9.0" ? "5.9" : this.version; - return nativePath(`${this.dir}/${version}`); - } - public get cacheKey(): string { let cacheKey = this.cacheKeyPrefix; for (const keyStringArray of [ @@ -331,12 +349,12 @@ const run = async (): Promise => { } // Set environment variables - const qtPath = nativePath(glob.sync(`${inputs.versionDir}/**/*`)[0]); if (inputs.setEnv) { if (inputs.tools.length) { core.exportVariable("IQTA_TOOLS", nativePath(`${inputs.dir}/Tools`)); } if (!inputs.toolsOnly) { + const qtPath = nativePath(locateQtArchDir(inputs.dir)); if (process.platform === "linux") { setOrAppendEnvVar("LD_LIBRARY_PATH", nativePath(`${qtPath}/lib`)); } From 2dcc190fb064bc7b460f576387422f777f5f8a68 Mon Sep 17 00:00:00 2001 From: Dave Dalcino Date: Sat, 21 Jan 2023 10:00:52 -0800 Subject: [PATCH 7/9] fix check for Qt 6: patch number should not matter --- .github/workflows/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 49a0d9c5..d270fea5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -79,10 +79,10 @@ jobs: cache: ${{ matrix.cache == 'cached' }} - name: Install Qt6 with options - if: startsWith(matrix.qt.version, '6.3') + if: startsWith(matrix.qt.version, '6') uses: ./ with: - # In Qt 6.2.0, qtwebengine requires qtpositioning and qtwebchannel + # In Qt 6.2.0+, qtwebengine requires qtpositioning and qtwebchannel modules: qtwebengine qtpositioning qtwebchannel version: ${{ matrix.qt.requested }} tools: tools_ifw tools_qtcreator,qt.tools.qtcreator From a279d3ae14730ff83a9555fc62981b38cc3b6de2 Mon Sep 17 00:00:00 2001 From: Dave Dalcino Date: Sat, 28 Jan 2023 13:37:30 -0800 Subject: [PATCH 8/9] add test for tools-only --- .github/workflows/test.yml | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d270fea5..0d987228 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -43,6 +43,8 @@ jobs: requested: "5.15" - version: "6.3.2" # Qt 6.3 is not an LTS version, so '6.3.*' always resolves to '6.3.2' requested: "6.3.*" + - version: null # Tools-only build + requested: null cache: - cached - uncached @@ -70,7 +72,7 @@ jobs: npm run build - name: Install Qt5 with options - if: startsWith(matrix.qt.version, '5') + if: ${{ matrix.qt.version && startsWith(matrix.qt.version, '5') }} uses: ./ with: modules: qtwebengine @@ -79,7 +81,7 @@ jobs: cache: ${{ matrix.cache == 'cached' }} - name: Install Qt6 with options - if: startsWith(matrix.qt.version, '6') + if: ${{ matrix.qt.version && startsWith(matrix.qt.version, '6') }} uses: ./ with: # In Qt 6.2.0+, qtwebengine requires qtpositioning and qtwebchannel @@ -89,7 +91,7 @@ jobs: cache: ${{ matrix.cache == 'cached' }} - name: Configure test project on windows - if: startsWith(matrix.os, 'windows') + if: ${{ matrix.qt.version && startsWith(matrix.os, 'windows') }} env: QT_VERSION: ${{ matrix.qt.version }} run: | @@ -100,7 +102,7 @@ jobs: shell: cmd - name: Configure test project on unix - if: (!startsWith(matrix.os, 'windows')) + if: ${{ matrix.qt.version && !startsWith(matrix.os, 'windows') }} env: QT_VERSION: ${{ matrix.qt.version }} run: | @@ -112,3 +114,27 @@ jobs: fi qmake shell: bash + + - name: Install tools with options + if: ${{ !matrix.qt.version }} + uses: ./ + with: + tools-only: true + tools: tools_ifw tools_qtcreator,qt.tools.qtcreator + cache: ${{ matrix.cache == 'cached' }} + + - name: Test installed tools + if: ${{ !matrix.qt.version }} + env: + # Conditionally set qtcreator path based on os: + QTCREATOR_BIN_PATH: ${{ startsWith(matrix.os, 'macos') && '../Qt/Qt Creator.app/Contents/MacOS/' || '../Qt/Tools/QtCreator/bin/' }} + shell: bash + run: | + # Check if QtIFW is installed + ls ../Qt/Tools/QtInstallerFramework/*/bin/ + ../Qt/Tools/QtInstallerFramework/*/bin/archivegen --version + + # Check if QtCreator is installed: QtCreator includes the CLI program 'qbs' on all 3 platforms + ls "${QTCREATOR_BIN_PATH}" + [[ -f "${QTCREATOR_BIN_PATH}qbs" ]] && echo "qbs is installed" + "${QTCREATOR_BIN_PATH}qbs" --version || echo "qbs installed but fails to run" From 0f87477a4524a0d704c203d43825b8c53a008d69 Mon Sep 17 00:00:00 2001 From: David Dalcino Date: Fri, 10 Feb 2023 14:46:10 -0800 Subject: [PATCH 9/9] Remove Ubuntu 18.04 builds The Ubuntu 18.04 image is now deprecated, and soon it won't run on GitHub CI at all. Since Qt 6 does not support it, this makes the workflow a lot simpler. --- .github/workflows/test.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0d987228..bcb28d8f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,7 +31,6 @@ jobs: os: - ubuntu-22.04 - ubuntu-20.04 - - ubuntu-18.04 - windows-2022 - windows-2019 - macos-11 @@ -49,10 +48,6 @@ jobs: - cached - uncached - # Ubuntu 18 is not a supported target for Qt 6: https://www.qt.io/blog/qt6-development-hosts-and-targets - exclude: - - os: ubuntu-18.04 - qt: {version: "6.3.2", requested: "6.3.*"} steps: - uses: actions/checkout@v3 @@ -136,5 +131,4 @@ jobs: # Check if QtCreator is installed: QtCreator includes the CLI program 'qbs' on all 3 platforms ls "${QTCREATOR_BIN_PATH}" - [[ -f "${QTCREATOR_BIN_PATH}qbs" ]] && echo "qbs is installed" - "${QTCREATOR_BIN_PATH}qbs" --version || echo "qbs installed but fails to run" + "${QTCREATOR_BIN_PATH}qbs" --version