diff options
Diffstat (limited to 'share/qbs')
-rw-r--r-- | share/qbs/imports/qbs/base/AndroidApk.qbs | 2 | ||||
-rw-r--r-- | share/qbs/imports/qbs/base/Application.qbs | 2 | ||||
-rw-r--r-- | share/qbs/module-providers/Qt/templates/android_support.qbs | 6 | ||||
-rw-r--r-- | share/qbs/modules/Android/sdk/sdk.qbs | 65 | ||||
-rw-r--r-- | share/qbs/modules/Android/sdk/utils.js | 90 |
5 files changed, 130 insertions, 35 deletions
diff --git a/share/qbs/imports/qbs/base/AndroidApk.qbs b/share/qbs/imports/qbs/base/AndroidApk.qbs index 5f86d8457..70cf6aa93 100644 --- a/share/qbs/imports/qbs/base/AndroidApk.qbs +++ b/share/qbs/imports/qbs/base/AndroidApk.qbs @@ -32,7 +32,7 @@ import qbs.File import qbs.FileInfo Product { - type: ["android.apk"] + type: ["android.package"] qbs.targetPlatform: "android" Depends { name: "Android.sdk" } } diff --git a/share/qbs/imports/qbs/base/Application.qbs b/share/qbs/imports/qbs/base/Application.qbs index 63ffc6283..1e4f805a8 100644 --- a/share/qbs/imports/qbs/base/Application.qbs +++ b/share/qbs/imports/qbs/base/Application.qbs @@ -29,7 +29,7 @@ ****************************************************************************/ NativeBinary { - type: isForAndroid && !consoleApplication ? ["android.apk"] : ["application"] + type: isForAndroid && !consoleApplication ? ["android.package"] : ["application"] property bool usesNativeCode diff --git a/share/qbs/module-providers/Qt/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs index 342018321..2835a9336 100644 --- a/share/qbs/module-providers/Qt/templates/android_support.qbs +++ b/share/qbs/module-providers/Qt/templates/android_support.qbs @@ -18,7 +18,7 @@ Module { property string _androidDeployQtFilePath: FileInfo.joinPaths(_qtInstallDir, "bin", "androiddeployqt") property string _qtInstallDir - property bool _enableSdkSupport: product.type && product.type.contains("android.apk") + property bool _enableSdkSupport: product.type && product.type.contains("android.package") && !consoleApplication property bool _enableNdkSupport: !product.aggregate || product.multiplexConfigurationId property string _templatesBaseDir: FileInfo.joinPaths(_qtInstallDir, "src", "android") @@ -312,7 +312,7 @@ Module { File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml", outputs["android.manifest_final"][0].filePath); var libsDir = product.Qt.android_support._deployQtOutDir + "/libs"; - var libDir = product.Android.sdk.apkContentsDir + "/lib"; + var libDir = product.Android.sdk.packageContentsDir + "/lib"; var listFilePath = outputs["android.deployqt_list"][0].filePath; var oldLibs = []; try { @@ -364,7 +364,7 @@ Module { for (var i in inputs["android.nativelibrary"]) architectures.push(inputs["android.nativelibrary"][i].Android.ndk.abi); for (var i in architectures) { - var abiDirPath = FileInfo.joinPaths(product.Android.sdk.apkContentsDir, + var abiDirPath = FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib", architectures[i]); var files = File.directoryEntries(abiDirPath, File.Files); for (var i = 0; i < files.length; ++i) { diff --git a/share/qbs/modules/Android/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs index 681b3da94..31f3ed465 100644 --- a/share/qbs/modules/Android/sdk/sdk.qbs +++ b/share/qbs/modules/Android/sdk/sdk.qbs @@ -50,6 +50,14 @@ Module { environmentPaths: (ndkDir ? [ndkDir] : []).concat(base) } + Probes.PathProbe { + id: bundletoolProbe + platformSearchPaths: [Android.sdk.sdkDir] + names: ["bundletool-all"] + nameSuffixes: ["-0.11.0.jar", "-0.12.0.jar", "-0.13.0.jar", "-0.13.3.jar", "-0.13.4.jar", + "-0.14.0.jar", "-0.15.0.jar"] + } + property path sdkDir: sdkProbe.path property path ndkDir: ndkProbe.path property path ndkSamplesDir: ndkProbe.samplesDir @@ -60,6 +68,8 @@ Module { property int buildToolsVersionPatch: buildToolsVersionParts[2] property string platform: sdkProbe.platform + property path bundletoolFilePath: bundletoolProbe.filePath + // Product-specific properties and files property string packageName: { var idx = product.name.indexOf(".") @@ -146,6 +156,12 @@ Module { } property path aaptFilePath: FileInfo.joinPaths(buildToolsDir, aaptName) readonly property bool _enableAapt2: aaptName === "aapt2" + property string packageType: "apk" + PropertyOptions { + name: "packageType" + allowedValues: ["apk", "aab"] + } + readonly property bool _generateAab: packageType == "aab" property path apksignerFilePath: FileInfo.joinPaths(buildToolsDir, "apksigner") property path aidlFilePath: FileInfo.joinPaths(buildToolsDir, "aidl") @@ -160,7 +176,7 @@ Module { (packageName || "").split('.').join('/')) property path compiledResourcesDir: FileInfo.joinPaths(product.buildDirectory, "compiled_resources") - property string apkContentsDir: FileInfo.joinPaths(product.buildDirectory, "bin") + property string packageContentsDir: FileInfo.joinPaths(product.buildDirectory, packageType) property string debugKeyStorePath: FileInfo.joinPaths( Environment.getEnv(qbs.hostOS.contains("windows") ? "USERPROFILE" : "HOME"), @@ -186,6 +202,14 @@ Module { + "ANDROID_HOME environment variable to a valid " + "Android SDK location."); } + if (!bundletoolFilePath && _generateAab) { + throw ModUtils.ModuleError("Could not find Android bundletool at the following " + + "location:\n\t" + Android.sdk.sdkDir + + "\nInstall the Android bundletool to the above location, " + + "or set the Android.sdk.bundletoolFilePath property.\n" + + "Android bundletool can be downloaded from " + + "https://github.com/google/bundletool"); + } } FileTagger { @@ -366,12 +390,13 @@ Module { condition: _enableRules && _enableAapt2 multiplex: true inputs: ["android.resources_compiled", "android.assets", "android.manifest_final"] - outputFileTags: ["java.java", "android.apk_base"] + outputFileTags: ["java.java", "android.apk_resources"] outputArtifacts: { var artifacts = []; artifacts.push({ - filePath: product.Android.sdk.apkBaseName + ".apk_base", - fileTags: ["android.apk_base"] + filePath: product.Android.sdk.apkBaseName + (product.Android.sdk._generateAab ? + ".apk_aab" : ".apk_apk"), + fileTags: ["android.apk_resources"] }); var resources = inputs["android.resources_compiled"]; if (resources && resources.length) { @@ -419,7 +444,10 @@ Module { inputs: ["java.class"] inputsFromDependencies: ["java.jar"] Artifact { - filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "classes.dex") + filePath: product.Android.sdk._generateAab ? + FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "dex", + "classes.dex") : + FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "classes.dex") fileTags: ["android.dex"] } prepare: SdkUtils.prepareDex.apply(SdkUtils, arguments) @@ -431,7 +459,7 @@ Module { inputsFromDependencies: inputTags inputs: product.aggregate ? [] : inputTags Artifact { - filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", + filePath: FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib", input.Android.ndk.abi, input.fileName) fileTags: "android.nativelibrary_deployed" } @@ -475,7 +503,7 @@ Module { } Rule { - condition: _enableRules && !_enableAapt2 + condition: _enableRules && !_enableAapt2 && !_generateAab multiplex: true inputs: [ "android.resources", "android.assets", "android.manifest_final", @@ -484,23 +512,38 @@ Module { ] Artifact { filePath: product.Android.sdk.apkBaseName + ".apk" - fileTags: "android.apk" + fileTags: "android.package" } prepare: SdkUtils.prepareAaptPackage.apply(SdkUtils, arguments) } Rule { - condition: _enableRules && _enableAapt2 + condition: _enableRules && _enableAapt2 && !_generateAab multiplex: true inputs: [ - "android.apk_base", "android.manifest_final", + "android.apk_resources", "android.manifest_final", "android.dex", "android.stl_deployed", "android.nativelibrary_deployed", "android.keystore" ] Artifact { filePath: product.Android.sdk.apkBaseName + ".apk" - fileTags: "android.apk" + fileTags: "android.package" } prepare: SdkUtils.prepareApkPackage.apply(SdkUtils, arguments) } + + Rule { + condition: _enableRules && _enableAapt2 && _generateAab + multiplex: true + inputs: [ + "android.apk_resources", "android.manifest_final", + "android.dex", "android.stl_deployed", + "android.nativelibrary_deployed" + ] + Artifact { + filePath: product.Android.sdk.apkBaseName + ".aab" + fileTags: "android.package" + } + prepare: SdkUtils.prepareBundletoolPackage.apply(SdkUtils, arguments) + } } diff --git a/share/qbs/modules/Android/sdk/utils.js b/share/qbs/modules/Android/sdk/utils.js index b1c929e68..63bf1f5c4 100644 --- a/share/qbs/modules/Android/sdk/utils.js +++ b/share/qbs/modules/Android/sdk/utils.js @@ -79,7 +79,7 @@ function prepareDex(project, product, inputs, outputs, input, output, explicitly args = args.concat(jarFiles); var cmd = new Command(dxFilePath, args); - cmd.description = "Creating " + output.fileName; + cmd.description = "creating " + output.fileName; return [cmd]; } @@ -183,13 +183,12 @@ function prepareAapt2CompileResource(project, product, inputs, outputs, input, o function prepareAapt2Link(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; + var baseOutputFilePath = outputs["android.apk_resources"][0].filePath; var manifestFilePath = inputs["android.manifest_final"][0].filePath; var compilesResourcesDir = product.Android.sdk.compiledResourcesDir; - var apkOutputFilePath = outputs["android.apk_base"][0].filePath; var compiledResources = inputs["android.resources_compiled"]; - var args = ["link", "-o", apkOutputFilePath, "-I", product.Android.sdk.androidJarFilePath]; - //For aab: args.push("link", "--proto-format"); + var args = ["link", "-o", baseOutputFilePath, "-I", product.Android.sdk.androidJarFilePath]; var i = 0; if (compiledResources) { for (i = 0; i < compiledResources.length; ++i) @@ -217,9 +216,10 @@ function prepareAapt2Link(project, product, inputs, outputs, input, output, expl args.push("-A", assetDirs[i]); if (product.qbs.buildVariant === "debug") args.push("-v"); - + if (product.Android.sdk._generateAab) + args.push("--proto-format"); var cmd = new Command(product.Android.sdk.aaptFilePath, args); - cmd.description = "Linking resources"; + cmd.description = "linking resources"; cmd.workingDirectory = product.buildDirectory; cmds.push(cmd); @@ -234,18 +234,18 @@ function prepareAaptGenerate(project, product, inputs, outputs, input, output, if (resources && resources.length) args.push("-J", ModUtils.moduleProperty(product, "generatedJavaFilesBaseDir")); var cmd = new Command(product.Android.sdk.aaptFilePath, args); - cmd.description = "Processing resources"; + cmd.description = "processing resources"; return [cmd]; } function prepareAaptPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; - var apkOutput = outputs["android.apk"][0]; + var apkOutput = outputs["android.package"][0]; var args = commonAaptPackageArgs.apply(this, arguments); args.push("-F", apkOutput.filePath + ".unaligned"); - args.push(product.Android.sdk.apkContentsDir); + args.push(product.Android.sdk.packageContentsDir); var cmd = new Command(product.Android.sdk.aaptFilePath, args); - cmd.description = "Generating " + apkOutput.filePath; + cmd.description = "generating " + apkOutput.fileName; cmds.push(cmd); if (!product.Android.sdk.useApksigner) { @@ -255,7 +255,7 @@ function prepareAaptPackage(project, product, inputs, outputs, input, output, ex apkOutput.filePath + ".unaligned", "androiddebugkey"]; cmd = new Command(product.java.jarsignerFilePath, args); - cmd.description = "Signing " + apkOutput.fileName; + cmd.description = "signing " + apkOutput.fileName; cmds.push(cmd); } @@ -277,7 +277,7 @@ function prepareAaptPackage(project, product, inputs, outputs, input, output, ex "--ks-pass", "pass:android", apkOutput.filePath]; cmd = new Command(product.Android.sdk.apksignerFilePath, args); - cmd.description = "Signing " + apkOutput.fileName; + cmd.description = "signing " + apkOutput.fileName; cmds.push(cmd); } @@ -286,9 +286,9 @@ function prepareAaptPackage(project, product, inputs, outputs, input, output, ex function prepareApkPackage(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; - var apkInputFilePath = inputs["android.apk_base"][0].filePath; - var apkOutput = outputs["android.apk"][0]; - var apkOutputFilePathUnaligned = outputs["android.apk"][0].filePath + ".unaligned"; + var apkInputFilePath = inputs["android.apk_resources"][0].filePath; + var apkOutput = outputs["android.package"][0]; + var apkOutputFilePathUnaligned = outputs["android.package"][0].filePath + ".unaligned"; var dexFilePath = inputs["android.dex"][0].filePath; var copyCmd = new JavaScriptCommand(); @@ -301,7 +301,7 @@ function prepareApkPackage(project, product, inputs, outputs, input, output, exp cmds.push(copyCmd); var jarArgs = ["-uvf", apkOutputFilePathUnaligned, "."]; - var libPath = FileInfo.joinPaths(product.Android.sdk.apkContentsDir); + var libPath = FileInfo.joinPaths(product.Android.sdk.packageContentsDir); var jarCmd = new Command(product.java.jarFilePath, jarArgs); jarCmd.description = "packaging files"; jarCmd.workingDirectory = libPath; @@ -314,7 +314,7 @@ function prepareApkPackage(project, product, inputs, outputs, input, output, exp apkOutputFilePathUnaligned, "androiddebugkey"]; cmd = new Command(product.java.jarsignerFilePath, args); - cmd.description = "Signing " + apkOutput.fileName; + cmd.description = "signing " + apkOutput.fileName; cmds.push(cmd); } @@ -336,13 +336,65 @@ function prepareApkPackage(project, product, inputs, outputs, input, output, exp "--ks-pass", "pass:android", apkOutput.filePath]; cmd = new Command(product.Android.sdk.apksignerFilePath, args); - cmd.description = "Signing " + apkOutput.fileName; + cmd.description = "signing " + apkOutput.fileName; cmds.push(cmd); } return cmds; } +function prepareBundletoolPackage(project, product, inputs, outputs, input, output, + explicitlyDependsOn) { + var cmds = []; + var baseModuleDir = product.Android.sdk.packageContentsDir; + var manifestDirName = FileInfo.joinPaths(baseModuleDir, "manifest"); + var pkgBaseFileName = inputs["android.apk_resources"][0].filePath; + + var jarResourcesArgs = ["xf", pkgBaseFileName]; + var jarResourcesCmd = new Command(product.java.jarFilePath, jarResourcesArgs); + jarResourcesCmd.description = "extracting resources apk"; + jarResourcesCmd.workingDirectory = baseModuleDir; + cmds.push(jarResourcesCmd); + + var moveManifestCmd = new JavaScriptCommand(); + moveManifestCmd.description = "moving manifest in manifest directory"; + moveManifestCmd.path = manifestDirName; + moveManifestCmd.manifestFilePath = baseModuleDir + "/AndroidManifest.xml"; + moveManifestCmd.sourceCode = function() { + if (!File.exists(path)) + File.makePath(path); + if (File.exists(manifestFilePath)) + File.move(manifestFilePath, path + "/AndroidManifest.xml"); + } + cmds.push(moveManifestCmd); + + var baseFilePath = FileInfo.joinPaths(product.buildDirectory, "base.zip"); + var jarBaseArgs = ["cfM", baseFilePath, "."]; + var jarBaseCmd = new Command(product.java.jarFilePath, jarBaseArgs); + jarBaseCmd.description = "compressing base module"; + jarBaseCmd.workingDirectory = baseModuleDir; + cmds.push(jarBaseCmd); + + var aabFilePath = outputs["android.package"][0].filePath; + var removeCmd = new JavaScriptCommand(); + removeCmd.description = "removing previous aab"; + removeCmd.filePath = aabFilePath; + removeCmd.sourceCode = function() { + if (File.exists(filePath)) + File.remove(filePath); + } + cmds.push(removeCmd); + + var args = ["-jar", product.Android.sdk.bundletoolFilePath, "build-bundle"]; + args.push("--modules=" + baseFilePath); + args.push("--output=" + aabFilePath); + var cmd = new Command(product.java.interpreterFilePath, args); + cmd.description = "generating " + outputs["android.package"][0].fileName; + cmds.push(cmd); + + return cmds; +} + function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath) { var args = ["-genkey", "-keystore", keystoreFilePath, "-alias", "androiddebugkey", "-storepass", "android", "-keypass", "android", "-keyalg", "RSA", @@ -365,7 +417,7 @@ function stlDeploymentData(product, inputs, type) uniqueFilePaths.push(currentInput.filePath); data.uniqueInputs.push(currentInput); var outputFileName = currentInput.fileName; - data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", + data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.packageContentsDir, "lib", currentInput.Android.ndk.abi, outputFileName)); } |