diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b7cbf5d2..035ae208 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,6 +37,8 @@ jobs: - macos-12 aqtversion: - null # use whatever the default is + src-doc-examples: + - false qt: - version: "5.9.0" requested: "5.9.0" @@ -48,12 +50,31 @@ jobs: requested: "6.3.*" # In Qt 6.2.0+, qtwebengine requires qtpositioning and qtwebchannel modules: qtwebengine qtpositioning qtwebchannel - - version: null # Tools-only build - requested: null + - tools-only-build: true cache: - cached - uncached include: + - os: ubuntu-20.04 + src-doc-examples: true + source: true + src-archives: qtcharts + check-dir: ../Qt/5.15.2/Src + check: qtcharts/src/src.pro + - os: ubuntu-20.04 + src-doc-examples: true + documentation: true + doc-archives: qmake + doc-modules: qtcharts qtwebengine + check-dir: ../Qt/Docs/Qt-5.15.2 + check: qmake/qmake-tutorial.html qtcharts/qtcharts-index.html qtwebengine/qtwebengine-index.html + - os: ubuntu-20.04 + src-doc-examples: true + examples: true + example-archives: qtsensors + example-modules: qtcharts qtwebengine + check-dir: ../Qt/Examples/Qt-5.15.2 + check: charts/charts.pro sensors/sensors.pro webengine/webengine.pro - os: ubuntu-22.04 aqtversion: "==3.1.*" qt: @@ -124,8 +145,44 @@ jobs: qmake shell: bash + - name: Install source + if: ${{ matrix.source }} + uses: ./ + with: + version: "5.15.2" + source: true + no-qt-binaries: true + src-archives: ${{ matrix.src-archives }} + + - name: Install docs + if: ${{ matrix.documentation }} + uses: ./ + with: + version: "5.15.2" + documentation: true + no-qt-binaries: true + doc-archives: ${{ matrix.doc-archives }} + doc-modules: ${{ matrix.doc-modules }} + + - name: Install examples + if: ${{ matrix.examples }} + uses: ./ + with: + version: "5.15.2" + examples: true + no-qt-binaries: true + example-archives: ${{ matrix.example-archives }} + example-modules: ${{ matrix.example-modules }} + + - name: Test source, docs, examples + if: ${{ matrix.src-doc-examples }} + shell: bash + run: | + cd ${{ matrix.check-dir }} + ls ${{ matrix.check }} + - name: Install tools with options - if: ${{ !matrix.qt.version }} + if: ${{ matrix.qt.tools-only-build }} uses: ./ with: tools-only: true @@ -133,7 +190,7 @@ jobs: cache: ${{ matrix.cache == 'cached' }} - name: Test installed tools - if: ${{ !matrix.qt.version }} + if: ${{ matrix.qt.tools-only-build }} 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/' }} diff --git a/README.md b/README.md index 49d659f0..d727b2d4 100644 --- a/README.md +++ b/README.md @@ -118,14 +118,95 @@ For example, this value will install the most recent versions of QtIFW and QtCre You can find a full list of tools easily by using [this awesome website](https://ddalcino.github.io/aqt-list-server/). +### `source` + +Set this to `true` to install Qt source code. Incompatible with `aqtinstall < 2.0.4`. + +Default: `false` + +### `src-archives` + +String with whitespace delimited list of source archives to install, with each entry separated by a space. +Has no effect unless `source` is set to `true`. +Useful to limit download size. + +See the `--archives` flag for [aqt install-src](https://aqtinstall.readthedocs.io/en/latest/cli.html#install-src-command) for more details. +Use [aqt list-src](https://aqtinstall.readthedocs.io/en/latest/cli.html#list-src-command) to see available options. + +Default: none + +### `documentation` + +Set this to `true` to install Qt documentation files. Incompatible with `aqtinstall < 2.0.4`. + +Default: `false` + +### `doc-archives` + +String with whitespace delimited list of documentation archives to install, with each entry separated by a space. +Has no effect unless `documentation` is set to `true`. +Useful to limit download size. + +See the `--archives` flag for [aqt install-doc](https://aqtinstall.readthedocs.io/en/latest/cli.html#install-doc-command) for more details. +Use [aqt list-doc](https://aqtinstall.readthedocs.io/en/latest/cli.html#list-doc-command) to see available options. + +Default: none + +### `doc-modules` + +String with whitespace delimited list of documentation modules to install, with each entry separated by a space. +Has no effect unless `documentation` is set to `true`. +Each module contains extra documentation not included with the base installation. + +See the `--modules` flag for [aqt install-doc](https://aqtinstall.readthedocs.io/en/latest/cli.html#install-doc-command) for more details. +Use [aqt list-doc](https://aqtinstall.readthedocs.io/en/latest/cli.html#list-doc-command) to see available options. + +Default: none + +### `examples` + +Set this to `true` to install Qt example code. Incompatible with `aqtinstall < 2.0.4`. + +Default: `false` + +### `example-archives` + +String with whitespace delimited list of example archives to install, with each entry separated by a space. +Has no effect unless `examples` is set to `true`. +Useful to limit download size. + +See the `--archives` flag for [aqt install-example](https://aqtinstall.readthedocs.io/en/latest/cli.html#install-example-command) for more details. +Use [aqt list-example](https://aqtinstall.readthedocs.io/en/latest/cli.html#list-example-command) to see available options. + +Default: none + +### `example-modules` + +String with whitespace delimited list of example modules to install, with each entry separated by a space. +Has no effect unless `examples` is set to `true`. +Each module contains extra examples not included with the base installation. + +See the `--modules` flag for [aqt install-example](https://aqtinstall.readthedocs.io/en/latest/cli.html#install-example-command) for more details. +Use [aqt list-example](https://aqtinstall.readthedocs.io/en/latest/cli.html#list-example-command) to see available options. + +Default: none + ### `set-env` Set this to false if you want to avoid setting environment variables for whatever reason. Default: `true` +### `no-qt-binaries` + +Set this to true if you want to skip installing Qt. +This option is useful if you want to install tools, source, documentation, or examples. + +Default: `false` + ### `tools-only` -Set this to true if you only want to install tools, and not Qt. +This is a synonym for `no-qt-binaries`. It only exists to preserve backwards compatibility. +If you set either `no-qt-binaries` or `tools-only` to `true`, you will skip installation of Qt. Default: `false` diff --git a/action.yml b/action.yml index 436f525f..ad272669 100644 --- a/action.yml +++ b/action.yml @@ -42,8 +42,11 @@ inputs: set-env: default: true description: Whether or not to set environment variables after running aqtinstall + no-qt-binaries: + description: Turns off installation of Qt. Useful for installing tools, source, documentation, or examples. + default: false tools-only: - description: Whether or not to actually install Qt or just the tools from the tools argument + description: Synonym for `no-qt-binaries`, used for backwards compatibility. default: false aqtversion: description: Version of aqtinstall to use in case of issues @@ -53,6 +56,25 @@ inputs: default: ==0.19.* extra: description: Any extra arguments to append to the back + source: + default: false + description: Whether or not to install Qt source code. + src-archives: + description: Space-separated list of .7z source archives to install. Used to reduce download/image sizes. + documentation: + default: false + description: Whether or not to install Qt documentation. + doc-archives: + description: Space-separated list of .7z docs archives to install. Used to reduce download/image sizes. + doc-modules: + description: Space-separated list of additional documentation modules to install. + examples: + default: false + description: Whether or not to install Qt example code. + example-archives: + 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. runs: using: "composite" steps: @@ -77,7 +99,16 @@ runs: cache-key-prefix: ${{ inputs.cache-key-prefix }} tools: ${{ inputs.tools }} set-env: ${{ inputs.set-env }} + no-qt-binaries: ${{ inputs.no-qt-binaries }} tools-only: ${{ inputs.tools-only }} aqtversion: ${{ inputs.aqtversion }} py7zrversion: ${{ inputs.py7zrversion }} + source: ${{ inputs.source }} + src-archives: ${{ inputs.src-archives }} + documentation: ${{ inputs.documentation }} + doc-archives: ${{ inputs.doc-archives }} + doc-modules: ${{ inputs.doc-modules }} + examples: ${{ inputs.examples }} + example-archives: ${{ inputs.example-archives }} + example-modules: ${{ inputs.example-modules }} extra: ${{ inputs.extra }} \ No newline at end of file diff --git a/action/action.yml b/action/action.yml index 29416e9e..d9ae75fe 100644 --- a/action/action.yml +++ b/action/action.yml @@ -39,8 +39,11 @@ inputs: set-env: default: true description: Whether or not to set environment variables after running aqtinstall + no-qt-binaries: + description: Turns off installation of Qt. Useful for installing tools, source, documentation, or examples. + default: false tools-only: - description: Whether or not to actually install Qt or just the tools from the tools argument + description: Synonym for `no-qt-binaries`, used for backwards compatibility. default: false aqtversion: description: Version of aqtinstall to use in case of issues @@ -50,6 +53,25 @@ inputs: default: ==0.19.* extra: description: Any extra arguments to append to the back + source: + default: false + description: Whether or not to install Qt source code. + src-archives: + description: Space-separated list of .7z source archives to install. Used to reduce download/image sizes. + documentation: + default: false + description: Whether or not to install Qt documentation. + doc-archives: + description: Space-separated list of .7z docs archives to install. Used to reduce download/image sizes. + doc-modules: + description: Space-separated list of additional documentation modules to install. + examples: + default: false + description: Whether or not to install Qt example code. + example-archives: + 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. runs: using: node16 main: lib/main.js diff --git a/action/src/main.ts b/action/src/main.ts index bbeaddca..9d00abed 100644 --- a/action/src/main.ts +++ b/action/src/main.ts @@ -30,6 +30,10 @@ const execPython = async (command: string, args: readonly string[]): Promise { + return listArgs.length ? [flag, ...listArgs] : []; +}; + const locateQtArchDir = (installDir: string): string => { // 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. @@ -65,10 +69,21 @@ class Inputs { readonly tools: string[]; readonly extra: string[]; + readonly src: boolean; + readonly srcArchives: string[]; + + readonly doc: boolean; + readonly docArchives: string[]; + readonly docModules: string[]; + + readonly example: boolean; + readonly exampleArchives: string[]; + readonly exampleModules: string[]; + readonly installDeps: boolean | "nosudo"; readonly cache: boolean; readonly cacheKeyPrefix: string; - readonly toolsOnly: boolean; + readonly isInstallQtBinaries: boolean; readonly setEnv: boolean; readonly aqtVersion: string; @@ -143,38 +158,17 @@ class Inputs { } this.dir = `${dir}/Qt`; - const modules = core.getInput("modules"); - if (modules) { - this.modules = modules.split(" "); - } else { - this.modules = []; - } + this.modules = Inputs.getStringArrayInput("modules"); - const archives = core.getInput("archives"); - if (archives) { - this.archives = archives.split(" "); - } else { - this.archives = []; - } + this.archives = Inputs.getStringArrayInput("archives"); - const tools = core.getInput("tools"); - if (tools) { - this.tools = []; - for (const tool of tools.split(" ")) { - // The tools inputs have the tool name, variant, and arch delimited by a comma - // aqt expects spaces instead - this.tools.push(tool.replace(/,/g, " ")); - } - } else { - this.tools = []; - } + this.tools = Inputs.getStringArrayInput("tools").map( + // The tools inputs have the tool name, variant, and arch delimited by a comma + // aqt expects spaces instead + (tool: string): string => tool.replace(/,/g, " ") + ); - const extra = core.getInput("extra"); - if (extra) { - this.extra = extra.split(" "); - } else { - this.extra = []; - } + this.extra = Inputs.getStringArrayInput("extra"); const installDeps = core.getInput("install-deps").toLowerCase(); if (installDeps === "nosudo") { @@ -187,13 +181,25 @@ class Inputs { this.cacheKeyPrefix = core.getInput("cache-key-prefix"); - this.toolsOnly = Inputs.getBoolInput("tools-only"); + this.isInstallQtBinaries = + !Inputs.getBoolInput("tools-only") && !Inputs.getBoolInput("no-qt-binaries"); this.setEnv = Inputs.getBoolInput("set-env"); this.aqtVersion = core.getInput("aqtversion"); this.py7zrVersion = core.getInput("py7zrversion"); + + this.src = Inputs.getBoolInput("source"); + this.srcArchives = Inputs.getStringArrayInput("src-archives"); + + this.doc = Inputs.getBoolInput("documentation"); + this.docModules = Inputs.getStringArrayInput("doc-modules"); + this.docArchives = Inputs.getStringArrayInput("doc-archives"); + + this.example = Inputs.getBoolInput("examples"); + this.exampleModules = Inputs.getStringArrayInput("example-modules"); + this.exampleArchives = Inputs.getStringArrayInput("example-archives"); } public get cacheKey(): string { @@ -213,6 +219,14 @@ class Inputs { this.archives, this.extra, this.tools, + this.src ? "src" : "", + this.srcArchives, + this.doc ? "doc" : "", + this.docArchives, + this.docModules, + this.example ? "example" : "", + this.exampleArchives, + this.exampleModules, ]) { for (const keyString of keyStringArray) { if (keyString) { @@ -234,6 +248,10 @@ class Inputs { private static getBoolInput(name: string): boolean { return core.getInput(name).toLowerCase() === "true"; } + private static getStringArrayInput(name: string): string[] { + const content = core.getInput(name); + return content ? content.split(" ") : []; + } } const run = async (): Promise => { @@ -303,34 +321,49 @@ const run = async (): Promise => { await execPython("pip install", [`"aqtinstall${inputs.aqtVersion}"`]); // Install Qt - if (!inputs.toolsOnly) { - const qtArgs = [inputs.host, inputs.target, inputs.version]; - - if (inputs.arch) { - qtArgs.push(inputs.arch); - } - - qtArgs.push("--outputdir", inputs.dir); - - if (inputs.modules.length) { - qtArgs.push("--modules"); - for (const module of inputs.modules) { - qtArgs.push(module); - } - } - - if (inputs.archives.length) { - qtArgs.push("--archives"); - for (const archive of inputs.archives) { - qtArgs.push(archive); - } - } - - qtArgs.push(...inputs.extra); + if (inputs.isInstallQtBinaries) { + const qtArgs = [ + inputs.host, + inputs.target, + inputs.version, + ...(inputs.arch ? [inputs.arch] : []), + ...["--outputdir", inputs.dir], + ...flaggedList("--modules", inputs.modules), + ...flaggedList("--archives", inputs.archives), + ...inputs.extra, + ]; await execPython("aqt install-qt", qtArgs); } + const installSrcDocExamples = async ( + flavor: "src" | "doc" | "example", + archives: readonly string[], + modules: readonly string[] + ): Promise => { + const qtArgs = [ + inputs.host, + // Aqtinstall < 2.0.4 requires `inputs.target` here, but that's deprecated + inputs.version, + ...["--outputdir", inputs.dir], + ...flaggedList("--archives", archives), + ...flaggedList("--modules", modules), + ...inputs.extra, + ]; + await execPython(`aqt install-${flavor}`, qtArgs); + }; + + // Install source, docs, & examples + if (inputs.src) { + await installSrcDocExamples("src", inputs.srcArchives, []); + } + if (inputs.doc) { + await installSrcDocExamples("doc", inputs.docArchives, inputs.docModules); + } + if (inputs.example) { + await installSrcDocExamples("example", inputs.exampleArchives, inputs.exampleModules); + } + // Install tools for (const tool of inputs.tools) { const toolArgs = [inputs.host, inputs.target, tool]; @@ -351,7 +384,7 @@ const run = async (): Promise => { if (inputs.tools.length) { core.exportVariable("IQTA_TOOLS", nativePath(`${inputs.dir}/Tools`)); } - if (!inputs.toolsOnly) { + if (inputs.isInstallQtBinaries) { const qtPath = nativePath(locateQtArchDir(inputs.dir)); if (process.platform === "linux") { setOrAppendEnvVar("LD_LIBRARY_PATH", nativePath(`${qtPath}/lib`));