Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add commercial support, fix WASM and issues with Qt 6.7.+ #272

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The desired version of Qt to install.

You can also pass in SimpleSpec version numbers, for example `6.2.*`.

Default: `5.15.2` (Last Qt 5 LTS)
Default: `6.8.1` (Last Qt 6 LTS)

**Please note that for Linux builds, Qt 6+ requires Ubuntu 20.04 or later.**

Expand All @@ -32,14 +32,14 @@ This is the host platform of the Qt version you will be installing. It's unlikel

For example, if you are building on Linux and targeting desktop, you would set host to `linux`. If you are building on Linux and targeting android, you would set host to `linux` also. The host platform is the platform that your application will build on, not its target platform.

Possible values: `windows`, `mac`, or `linux`
Possible values: `windows`, `mac`, `linux` or `all_os`

Defaults to the current platform it is being run on.

### `target`
This is the target platform that you will be building for. You will want to set this if you are building for iOS or Android. Please note that iOS builds are supported only on macOS hosts and Win RT builds are only supported on Windows hosts.

Possible values: `desktop`, `android`, `ios`, or `winrt`
Possible values: `desktop`, `android`, `ios`, `winrt` or `wasm`

Default: `desktop`

Expand Down Expand Up @@ -74,6 +74,32 @@ When possible, access your Qt directory through the `QT_ROOT_DIR` environment va

Default: `$RUNNER_WORKSPACE` (this is one folder above the starting directory)

### `use-commercial` (since `v4.3.0`)
Whether or not to use `aqtinstall` to install Qt using its official online installer enabling the commercial versions for those owning a license.
For this to work, you need to also set `aqtsource` to `git+https://github.com/Kidev/aqtinstall.git@install_qt_commercial`.
The parameter `host` will then be ignored, as you can only install commercial Qt versions on the OS running the installer.
Example:
```yml
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '5.15.3'
target: 'desktop'
arch: 'win64_msvc2019_64'
aqtsource: 'git+https://github.com/Kidev/aqtinstall.git@install_qt_commercial'
use-commercial: true
user: '****@gmail.com'
password: '****'
```

Default: `false`

#### `user`
If `use-commercial` is true, will use this username/email to authenticate with Qt servers

#### `password`
If `use-commercial` is true, will use this password to authenticate with Qt servers

### `install-deps`
Whether or not to automatically install Qt dependencies on Linux through `apt`.

Expand Down Expand Up @@ -246,7 +272,7 @@ By default this is unset and ignored.

Version of [aqtinstall](https://github.com/miurahr/aqtinstall) to use, given in the format used by pip, for example: `==0.7.1`, `>=0.7.1`, `==0.7.*`. This is intended to be used to troubleshoot any bugs that might be caused or fixed by certain versions of aqtinstall.

Default: `==3.1.*`
Default: `==3.2.*`

### `py7zrversion`
Version of py7zr in the same style as the aqtversion and intended to be used for the same purpose.
Expand All @@ -264,10 +290,10 @@ Example value: `--external 7z`
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '5.15.2'
version: '6.8.1'
host: 'windows'
target: 'desktop'
arch: 'win64_msvc2019_64'
arch: 'win64_msvc2022_64'
dir: '${{ github.workspace }}/example/'
install-deps: 'true'
modules: 'qtcharts qtwebengine'
Expand All @@ -278,7 +304,7 @@ Example value: `--external 7z`
tools: 'tools_ifw tools_qtcreator,qt.tools.qtcreator'
set-env: 'true'
tools-only: 'false'
aqtversion: '==3.1.*'
aqtversion: '==3.2.*'
py7zrversion: '==0.20.*'
extra: '--external 7z'
```
Expand Down
22 changes: 17 additions & 5 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ inputs:
description: Directory to install Qt
version:
description: Version of Qt to install
default: "5.15.2"
default: "6.8.1"
host:
description: Host platform
target:
Expand Down Expand Up @@ -55,10 +55,10 @@ inputs:
description: Location to source aqtinstall from in case of issues
aqtversion:
description: Version of aqtinstall to use in case of issues
default: ==3.1.*
default: ==3.2.*
py7zrversion:
description: Version of py7zr to use in case of issues
default: ==0.20.*
default: ==0.22.*
extra:
description: Any extra arguments to append to the back
source:
Expand All @@ -80,14 +80,23 @@ inputs:
description: Space-separated list of .7z example archives to install. Used to reduce download/image sizes.
example-modules:
description: Space-separated list of additional example modules to install.
use-commercial:
default: false
description: Whether or not to use aqtinstall to install the commercial version of Qt
user:
default: 'username'
description: Your Qt username
password:
default: 'password'
description: Your Qt password
runs:
using: "composite"
steps:
- name: Setup Python
if: ${{ inputs.setup-python == 'true' }}
uses: actions/setup-python@v5
with:
python-version: '3.6.x - 3.11.x'
python-version: '3.6.x - 3.13.x'

- name: Setup and run aqtinstall
uses: ./action
Expand Down Expand Up @@ -118,4 +127,7 @@ runs:
examples: ${{ inputs.examples }}
example-archives: ${{ inputs.example-archives }}
example-modules: ${{ inputs.example-modules }}
extra: ${{ inputs.extra }}
extra: ${{ inputs.extra }}
use-commercial: ${{ inputs.use-commercial }}
user: ${{ inputs.user }}
password: ${{ inputs.password }}
15 changes: 12 additions & 3 deletions action/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ inputs:
description: Directory to install Qt
version:
description: Version of Qt to install
default: "5.15.2"
default: "6.8.1"
host:
description: Host platform
target:
Expand Down Expand Up @@ -52,10 +52,10 @@ inputs:
description: Location to source aqtinstall from in case of issues
aqtversion:
description: Version of aqtinstall to use in case of issues
default: ==3.1.*
default: ==3.2.*
py7zrversion:
description: Version of py7zr to use in case of issues
default: ==0.20.*
default: ==0.22.*
extra:
description: Any extra arguments to append to the back
source:
Expand All @@ -77,6 +77,15 @@ inputs:
description: Space-separated list of .7z example archives to install. Used to reduce download/image sizes.
example-modules:
description: Space-separated list of additional example modules to install.
use-commercial:
default: false
description: Whether or not to use aqtinstall to install the commercial version of Qt
user:
default: 'username'
description: Your Qt username
password:
default: 'password'
description: Your Qt password
runs:
using: node20
main: lib/main.js
114 changes: 94 additions & 20 deletions action/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const pythonCommand = (command: string, args: readonly string[]): string => {
const python = process.platform === "win32" ? "python" : "python3";
return `${python} -m ${command} ${args.join(" ")}`;
};

const execPython = async (command: string, args: readonly string[]): Promise<number> => {
return exec(pythonCommand(command, args));
};
Expand Down Expand Up @@ -97,15 +98,64 @@ const locateQtArchDir = (installDir: string): string => {
}
};

const locateQtWasmHostArchDir = (
installDir: string,
hostType: "windows" | "mac" | "linux" | "all_os",
target: "desktop" | "android" | "ios" | "wasm",
version: string
): string => {
// For WASM in all_os mode, use the host builder directory
if (hostType === "all_os" && target === "wasm") {
const versionDir = path.join(installDir, version);

switch (process.platform) {
case "win32": {
// Find mingw directories
const mingwPattern = /^win\d+_mingw\d+$/;
const mingwArches = glob
.sync(`${versionDir}/*/`)
.map((dir) => path.basename(dir))
.filter((dir) => mingwPattern.test(dir))
.sort((a, b) => {
const [aBits, aVer] = a
.match(/win(\d+)_mingw(\d+)/)
?.slice(1)
.map(Number) ?? [0, 0];
const [bBits, bVer] = b
.match(/win(\d+)_mingw(\d+)/)
?.slice(1)
.map(Number) ?? [0, 0];
if (aBits !== bBits) return bBits - aBits;
return bVer - aVer;
});

if (!mingwArches.length) {
throw Error(`Failed to locate a MinGW directory for WASM host in ${versionDir}`);
}
return path.join(versionDir, mingwArches[0]);
}
case "darwin":
return path.join(versionDir, "clang_64");
default:
return path.join(
versionDir,
compareVersions(version, ">=", "6.7.0") ? "linux_gcc_64" : "gcc_64"
);
}
}

return locateQtArchDir(installDir);
};

const isAutodesktopSupported = async (): Promise<boolean> => {
const rawOutput = await getPythonOutput("aqt", ["version"]);
const match = rawOutput.match(/aqtinstall\(aqt\)\s+v(\d+\.\d+\.\d+)/);
return match ? compareVersions(match[1], ">=", "3.0.0") : false;
};

class Inputs {
readonly host: "windows" | "mac" | "linux";
readonly target: "desktop" | "android" | "ios";
readonly host: "windows" | "mac" | "linux" | "all_os";
readonly target: "desktop" | "android" | "ios" | "wasm";
readonly version: string;
readonly arch: string;
readonly dir: string;
Expand Down Expand Up @@ -136,6 +186,10 @@ class Inputs {
readonly aqtVersion: string;
readonly py7zrVersion: string;

readonly useCommercial: boolean;
readonly user: string;
readonly password: string;

constructor() {
const host = core.getInput("host");
// Set host automatically if omitted
Expand All @@ -156,19 +210,19 @@ class Inputs {
}
} else {
// Make sure host is one of the allowed values
if (host === "windows" || host === "mac" || host === "linux") {
if (host === "windows" || host === "mac" || host === "linux" || host === "all_os") {
this.host = host;
} else {
throw TypeError(`host: "${host}" is not one of "windows" | "mac" | "linux"`);
throw TypeError(`host: "${host}" is not one of "windows" | "mac" | "linux" | "all_os"`);
}
}

const target = core.getInput("target");
// Make sure target is one of the allowed values
if (target === "desktop" || target === "android" || target === "ios") {
if (target === "desktop" || target === "android" || target === "ios" || target === "wasm") {
this.target = target;
} else {
throw TypeError(`target: "${target}" is not one of "desktop" | "android" | "ios"`);
throw TypeError(`target: "${target}" is not one of "desktop" | "android" | "ios" | "wasm"`);
}

// An attempt to sanitize non-straightforward version number input
Expand Down Expand Up @@ -242,6 +296,10 @@ class Inputs {

this.py7zrVersion = core.getInput("py7zrversion");

this.useCommercial = Inputs.getBoolInput("use-commercial");
this.user = core.getInput("user");
this.password = core.getInput("password");

this.src = Inputs.getBoolInput("source");
this.srcArchives = Inputs.getStringArrayInput("src-archives");

Expand All @@ -267,6 +325,7 @@ class Inputs {
this.py7zrVersion,
this.aqtSource,
this.aqtVersion,
this.useCommercial ? "commercial" : "",
],
this.modules,
this.archives,
Expand Down Expand Up @@ -386,19 +445,34 @@ const run = async (): Promise<void> => {

// Install Qt
if (inputs.isInstallQtBinaries) {
const qtArgs = [
inputs.host,
inputs.target,
inputs.version,
...(inputs.arch ? [inputs.arch] : []),
...autodesktop,
...["--outputdir", inputs.dir],
...flaggedList("--modules", inputs.modules),
...flaggedList("--archives", inputs.archives),
...inputs.extra,
];

await execPython("aqt install-qt", qtArgs);
if (inputs.useCommercial && inputs.user && inputs.password) {
const qtArgs = [
"install-qt-commercial",
inputs.target,
...(inputs.arch ? [inputs.arch] : []),
inputs.version,
...["--outputdir", inputs.dir],
...["--user", inputs.user],
...["--password", inputs.password],
...flaggedList("--modules", inputs.modules),
...inputs.extra,
];
await execPython("aqt", qtArgs);
} else {
const qtArgs = [
"install-qt",
inputs.host,
inputs.target,
inputs.version,
...(inputs.arch ? [inputs.arch] : []),
...autodesktop,
...["--outputdir", inputs.dir],
...flaggedList("--modules", inputs.modules),
...flaggedList("--archives", inputs.archives),
...inputs.extra,
];
await execPython("aqt", qtArgs);
}
}

const installSrcDocExamples = async (
Expand Down Expand Up @@ -455,7 +529,7 @@ const run = async (): Promise<void> => {
}
// Set environment variables/outputs for binaries
if (inputs.isInstallQtBinaries) {
const qtPath = locateQtArchDir(inputs.dir);
const qtPath = locateQtWasmHostArchDir(inputs.dir, inputs.host, inputs.target, inputs.version);
// Set outputs
core.setOutput("qtPath", qtPath);

Expand Down