diff options
Diffstat (limited to 'share/qbs/modules')
48 files changed, 756 insertions, 321 deletions
diff --git a/share/qbs/modules/Android/ndk/ndk.qbs b/share/qbs/modules/Android/ndk/ndk.qbs index 226423d61..94211ea39 100644 --- a/share/qbs/modules/Android/ndk/ndk.qbs +++ b/share/qbs/modules/Android/ndk/ndk.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils @@ -146,8 +145,6 @@ Module { return toolchainVersion; } - property string gdbserverFileName: "gdbserver" - property string armMode: abi && abi.startsWith("armeabi") ? (qbs.buildVariant === "debug" ? "arm" : "thumb") : undefined; @@ -168,7 +165,8 @@ Module { + "ANDROID_NDK_ROOT environment variable to a valid " + "Android NDK location."); } - + if (product.aggregate && !product.multiplexConfigurationId) + return; var validator = new ModUtils.PropertyValidator("Android.ndk"); validator.setRequiredProperty("abi", abi); validator.setRequiredProperty("appStl", appStl); diff --git a/share/qbs/modules/Android/ndk/utils.js b/share/qbs/modules/Android/ndk/utils.js index 7d1f7d6d0..a2e342897 100644 --- a/share/qbs/modules/Android/ndk/utils.js +++ b/share/qbs/modules/Android/ndk/utils.js @@ -63,25 +63,13 @@ function androidAbi(arch) { function commonCompilerFlags(toolchain, buildVariant, abi, armMode) { var flags = ["-ffunction-sections", "-funwind-tables", - "-Wa,--noexecstack", "-Werror=format-security"]; + "-Wa,--noexecstack", "-Werror=format-security", "-fstack-protector-strong"]; - if (buildVariant === "debug") - flags.push("-fno-omit-frame-pointer", "-fno-strict-aliasing"); - if (buildVariant === "release") - flags.push("-fomit-frame-pointer"); - - if (abi === "arm64-v8a") { - flags.push("-fpic", "-fstack-protector") - if (!toolchain.contains("clang")) - flags.push("-finline-limit=300", "-funswitch-loops"); - if (buildVariant === "release") - flags.push("-fstrict-aliasing"); - } + if (abi === "arm64-v8a") + flags.push("-fpic"); if (abi === "armeabi" || abi === "armeabi-v7a") { - flags.push("-fpic", "-fstack-protector"); - if (!toolchain.contains("clang")) - flags.push("-finline-limit=64"); + flags.push("-fpic"); if (abi === "armeabi") flags.push("-mtune=xscale", "-msoft-float"); @@ -90,29 +78,16 @@ function commonCompilerFlags(toolchain, buildVariant, abi, armMode) { flags.push("-mfpu=vfpv3-d16"); flags.push("-mfloat-abi=softfp"); } - - if (buildVariant === "release") - flags.push("-fno-strict-aliasing"); } if (abi === "mips" || abi === "mips64") { flags.push("-fpic", "-finline-functions", "-fmessage-length=0", "-fno-inline-functions-called-once", "-fgcse-after-reload", "-frerun-cse-after-loop", "-frename-registers"); - if (buildVariant === "release") { - flags.push("-fno-strict-aliasing"); - if (!toolchain.contains("clang")) - flags.push("-funswitch-loops", "-finline-limit=300"); - } } - if (abi === "x86" || abi === "x86_64") { - flags.push("-fstack-protector"); - if (!toolchain.contains("clang")) - flags.push("-funswitch-loops", "-finline-limit=300"); - if (buildVariant === "release") - flags.push("-fstrict-aliasing"); - } + if ((abi === "x86" || abi === "x86_64") && toolchain.contains("clang")) + flags.push("-fPIC"); if (armMode) flags.push("-m" + armMode); diff --git a/share/qbs/modules/Android/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs index 84cee56e9..79ec9ad81 100644 --- a/share/qbs/modules/Android/sdk/sdk.qbs +++ b/share/qbs/modules/Android/sdk/sdk.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.Environment import qbs.File import qbs.FileInfo @@ -36,6 +35,7 @@ import qbs.ModUtils import qbs.Probes import qbs.TextFile import qbs.Utilities +import qbs.Xml import "utils.js" as SdkUtils Module { @@ -60,6 +60,58 @@ Module { property int buildToolsVersionPatch: buildToolsVersionParts[2] property string platform: sdkProbe.platform + // Product-specific properties and files + property string packageName: product.name + property string apkBaseName: packageName + property bool automaticSources: true + property bool legacyLayout: false + property string sourceSetDir: legacyLayout + ? product.sourceDirectory + : FileInfo.joinPaths(product.sourceDirectory, "src/main") + property string resourcesDir: FileInfo.joinPaths(sourceSetDir, "res") + property string assetsDir: FileInfo.joinPaths(sourceSetDir, "assets") + property string sourcesDir: FileInfo.joinPaths(sourceSetDir, legacyLayout ? "src" : "java") + property string manifestFile: defaultManifestFile + readonly property string defaultManifestFile: FileInfo.joinPaths(sourceSetDir, + "AndroidManifest.xml") + + property bool _enableRules: !product.multiplexConfigurationId && !!packageName + + Group { + name: "java sources" + condition: Android.sdk.automaticSources + prefix: Android.sdk.sourcesDir + '/' + files: "**/*.java" + } + + Group { + name: "android resources" + condition: Android.sdk.automaticSources + fileTags: ["android.resources"] + prefix: Android.sdk.resourcesDir + '/' + files: "**/*" + } + + Group { + name: "android assets" + condition: Android.sdk.automaticSources + fileTags: ["android.assets"] + prefix: Android.sdk.assetsDir + '/' + files: "**/*" + } + + Group { + name: "manifest" + condition: Android.sdk.automaticSources + fileTags: ["android.manifest"] + files: Android.sdk.manifestFile + && Android.sdk.manifestFile !== Android.sdk.defaultManifestFile + ? [Android.sdk.manifestFile] + : (File.exists(Android.sdk.defaultManifestFile) + ? [Android.sdk.defaultManifestFile] : []) + } + + // Internal properties. property int platformVersion: { if (platform) { @@ -84,9 +136,11 @@ Module { property path zipalignFilePath: FileInfo.joinPaths(buildToolsDir, "zipalign") property path androidJarFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, "android.jar") + property path frameworkAidlFilePath: FileInfo.joinPaths(sdkDir, "platforms", platform, + "framework.aidl") property path generatedJavaFilesBaseDir: FileInfo.joinPaths(product.buildDirectory, "gen") property path generatedJavaFilesDir: FileInfo.joinPaths(generatedJavaFilesBaseDir, - (product.packageName || "").split('.').join('/')) + (packageName || "").split('.').join('/')) property string apkContentsDir: FileInfo.joinPaths(product.buildDirectory, "bin") property string debugKeyStorePath: FileInfo.joinPaths( Environment.getEnv(qbs.hostOS.contains("windows") @@ -94,11 +148,15 @@ Module { ".android", "debug.keystore") property bool useApksigner: buildToolsVersion && Utilities.versionCompare( buildToolsVersion, "24.0.3") >= 0 + property stringList aidlSearchPaths - Depends { name: "java" } - java.languageVersion: platformJavaVersion - java.runtimeVersion: platformJavaVersion - java.bootClassPaths: androidJarFilePath + Depends { name: "java"; condition: _enableRules } + Properties { + condition: _enableRules + java.languageVersion: platformJavaVersion + java.runtimeVersion: platformJavaVersion + java.bootClassPaths: androidJarFilePath + } validate: { if (!sdkDir) { @@ -156,6 +214,7 @@ Module { } Rule { + condition: _enableRules inputs: ["android.aidl"] Artifact { filePath: FileInfo.joinPaths(Utilities.getHash(input.filePath), @@ -164,16 +223,51 @@ Module { } prepare: { - var aidl = ModUtils.moduleProperty(product, "aidlFilePath"); - cmd = new Command(aidl, [input.filePath, output.filePath]); + var aidl = product.Android.sdk.aidlFilePath; + var args = ["-p" + product.Android.sdk.frameworkAidlFilePath]; + var aidlSearchPaths = input.Android.sdk.aidlSearchPaths; + for (var i = 0; i < (aidlSearchPaths ? aidlSearchPaths.length : 0); ++i) + args.push("-I" + aidlSearchPaths[i]); + args.push(input.filePath, output.filePath); + cmd = new Command(aidl, args); cmd.description = "Processing " + input.fileName; return [cmd]; } } + property bool customManifestProcessing: false + Group { + condition: !Android.sdk.customManifestProcessing + fileTagsFilter: "android.manifest_processed" + fileTags: "android.manifest_final" + } Rule { + condition: _enableRules + inputs: "android.manifest" + Artifact { + filePath: FileInfo.joinPaths("processed_manifest", input.fileName) + fileTags: "android.manifest_processed" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "Ensuring correct package name in Android manifest file"; + cmd.sourceCode = function() { + var manifestData = new Xml.DomDocument(); + manifestData.load(input.filePath); + var rootElem = manifestData.documentElement(); + if (!rootElem || !rootElem.isElement() || rootElem.tagName() != "manifest") + throw "No manifest tag found in '" + input.filePath + "'."; + rootElem.setAttribute("package", product.Android.sdk.packageName); + manifestData.save(output.filePath, 4); + } + return cmd; + } + } + + Rule { + condition: _enableRules multiplex: true - inputs: ["android.resources", "android.assets", "android.manifest"] + inputs: ["android.resources", "android.assets", "android.manifest_final"] outputFileTags: ["java.java"] outputArtifacts: { @@ -181,9 +275,8 @@ Module { var resources = inputs["android.resources"]; if (resources && resources.length) { artifacts.push({ - filePath: FileInfo.joinPaths( - ModUtils.moduleProperty(product, "generatedJavaFilesDir"), - "R.java"), + filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, + "R.java"), fileTags: ["java.java"] }); } @@ -195,11 +288,11 @@ Module { } Rule { + condition: _enableRules multiplex: true - condition: !!product.packageName Artifact { - filePath: FileInfo.joinPaths(ModUtils.moduleProperty(product, "generatedJavaFilesDir"), + filePath: FileInfo.joinPaths(product.Android.sdk.generatedJavaFilesDir, "BuildConfig.java") fileTags: ["java.java"] } @@ -208,10 +301,9 @@ Module { var cmd = new JavaScriptCommand(); cmd.description = "Generating BuildConfig.java"; cmd.sourceCode = function() { - var debugValue = product.moduleProperty("qbs", "buildVariant") === "debug" - ? "true" : "false"; + var debugValue = product.qbs.buildVariant === "debug" ? "true" : "false"; var ofile = new TextFile(output.filePath, TextFile.WriteOnly); - ofile.writeLine("package " + product.packageName + ";") + ofile.writeLine("package " + product.Android.sdk.packageName + ";") ofile.writeLine("public final class BuildConfig {"); ofile.writeLine(" public final static boolean DEBUG = " + debugValue + ";"); ofile.writeLine("}"); @@ -222,6 +314,7 @@ Module { } Rule { + condition: _enableRules multiplex: true inputs: ["java.class"] inputsFromDependencies: ["java.jar"] @@ -233,71 +326,97 @@ Module { } Rule { + condition: _enableRules + property stringList inputTags: "android.nativelibrary" + inputsFromDependencies: inputTags + inputs: product.aggregate ? [] : inputTags + Artifact { + filePath: FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", + input.Android.ndk.abi, input.fileName) + fileTags: "android.nativelibrary_deployed" + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "copying " + input.fileName + " for packaging"; + cmd.sourceCode = function() { File.copy(input.filePath, output.filePath); }; + return cmd; + } + } + + Rule { + condition: _enableRules multiplex: true - inputsFromDependencies: [ - "android.gdbserver-info", "android.stl-info", "android.nativelibrary" - ] - outputFileTags: ["android.gdbserver", "android.stl", "android.nativelibrary-deployed"] + property stringList inputTags: "android.gdbserver" + inputsFromDependencies: inputTags + inputs: product.aggregate ? [] : inputTags + outputFileTags: "android.gdbserver_deployed" outputArtifacts: { - var libArtifacts = []; - if (inputs["android.nativelibrary"]) { - for (var i = 0; i < inputs["android.nativelibrary"].length; ++i) { - var inp = inputs["android.nativelibrary"][i]; - var destDir = FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", - inp.moduleProperty("Android.ndk", "abi")); - libArtifacts.push({ - filePath: FileInfo.joinPaths(destDir, inp.fileName), - fileTags: ["android.nativelibrary-deployed"] - }); - } + var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, + "gdbserver"); + var outputs = []; + for (i = 0; i < deploymentData.outputFilePaths.length; ++i) { + outputs.push({filePath: deploymentData.outputFilePaths[i], + fileTags: "android.gdbserver_deployed"}); } - var gdbServerArtifacts = SdkUtils.outputArtifactsFromInfoFiles(inputs, - product, "android.gdbserver-info", "android.gdbserver"); - var stlArtifacts = SdkUtils.outputArtifactsFromInfoFiles(inputs, product, - "android.stl-info", "android.deployed-stl"); - return libArtifacts.concat(gdbServerArtifacts).concat(stlArtifacts); + return outputs; } prepare: { - var cmd = new JavaScriptCommand(); - cmd.description = "Pre-packaging native binaries"; + var cmd = new JavaScriptCommand; + cmd.description = "deploying gdbserver binaries"; cmd.sourceCode = function() { - if (inputs["android.nativelibrary"]) { - for (var i = 0; i < inputs["android.nativelibrary"].length; ++i) { - for (var j = 0; j < outputs["android.nativelibrary-deployed"].length; ++j) { - var inp = inputs["android.nativelibrary"][i]; - var outp = outputs["android.nativelibrary-deployed"][j]; - var inpAbi = inp.moduleProperty("Android.ndk", "abi"); - var outpAbi = FileInfo.fileName(outp.baseDir); - if (inp.fileName === outp.fileName && inpAbi === outpAbi) { - File.copy(inp.filePath, outp.filePath); - break; - } - } - } + var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, + "gdbserver"); + for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) { + File.copy(deploymentData.uniqueInputs[i].filePath, + deploymentData.outputFilePaths[i]); } - var pathsSpecs = SdkUtils.sourceAndTargetFilePathsFromInfoFiles(inputs, product, - "android.gdbserver-info"); - for (i = 0; i < pathsSpecs.sourcePaths.length; ++i) - File.copy(pathsSpecs.sourcePaths[i], pathsSpecs.targetPaths[i]); - pathsSpecs = SdkUtils.sourceAndTargetFilePathsFromInfoFiles(inputs, product, - "android.stl-info"); - for (i = 0; i < pathsSpecs.sourcePaths.length; ++i) - File.copy(pathsSpecs.sourcePaths[i], pathsSpecs.targetPaths[i]); }; - return [cmd]; + return cmd; + } + } + + Rule { + condition: _enableRules + multiplex: true + property stringList inputTags: "android.stl" + inputsFromDependencies: inputTags + inputs: product.aggregate ? [] : inputTags + outputFileTags: "android.stl_deployed" + outputArtifacts: { + var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs, "stl"); + var outputs = []; + for (i = 0; i < deploymentData.outputFilePaths.length; ++i) { + outputs.push({filePath: deploymentData.outputFilePaths[i], + fileTags: "android.stl_deployed"}); + } + return outputs; + } + prepare: { + var cmds = []; + var deploymentData = SdkUtils.gdbserverOrStlDeploymentData(product, inputs); + for (var i = 0; i < deploymentData.uniqueInputs.length; ++i) { + var input = deploymentData.uniqueInputs[i]; + var stripArgs = ["--strip-unneeded", "-o", deploymentData.outputFilePaths[i], + input.filePath]; + var cmd = new Command(input.cpp.stripPath, stripArgs); + cmd.description = "deploying " + input.fileName; + cmds.push(cmd); + } + return cmds; } } Rule { + condition: _enableRules multiplex: true inputs: [ - "android.resources", "android.assets", "android.manifest", - "android.dex", "android.gdbserver", "android.stl", - "android.nativelibrary-deployed", "android.keystore" + "android.resources", "android.assets", "android.manifest_final", + "android.dex", "android.gdbserver_deployed", "android.stl_deployed", + "android.nativelibrary_deployed", "android.keystore" ] Artifact { - filePath: product.targetName + ".apk" - fileTags: ["android.apk"] + filePath: product.Android.sdk.apkBaseName + ".apk" + fileTags: "android.apk" } prepare: SdkUtils.prepareAaptPackage.apply(SdkUtils, arguments) } diff --git a/share/qbs/modules/Android/sdk/utils.js b/share/qbs/modules/Android/sdk/utils.js index 6d9fff65c..6a89fd5f2 100644 --- a/share/qbs/modules/Android/sdk/utils.js +++ b/share/qbs/modules/Android/sdk/utils.js @@ -34,34 +34,6 @@ var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); var Utilities = require("qbs.Utilities"); -function sourceAndTargetFilePathsFromInfoFiles(inputs, product, inputTag) -{ - var sourceFilePaths = []; - var targetFilePaths = []; - var inputsLength = inputs[inputTag] ? inputs[inputTag].length : 0; - for (var i = 0; i < inputsLength; ++i) { - var infoFile = new TextFile(inputs[inputTag][i].filePath, TextFile.ReadOnly); - var sourceFilePath = infoFile.readLine(); - var targetFilePath = FileInfo.joinPaths(product.Android.sdk.apkContentsDir, - infoFile.readLine()); - if (!targetFilePaths.contains(targetFilePath)) { - sourceFilePaths.push(sourceFilePath); - targetFilePaths.push(targetFilePath); - } - infoFile.close(); - } - return { sourcePaths: sourceFilePaths, targetPaths: targetFilePaths }; -} - -function outputArtifactsFromInfoFiles(inputs, product, inputTag, outputTag) -{ - var pathSpecs = sourceAndTargetFilePathsFromInfoFiles(inputs, product, inputTag) - var artifacts = []; - for (i = 0; i < pathSpecs.targetPaths.length; ++i) - artifacts.push({filePath: pathSpecs.targetPaths[i], fileTags: [outputTag]}); - return artifacts; -} - function availableSdkPlatforms(sdkDir) { var re = /^android-([0-9]+)$/; var platforms = File.directoryEntries(FileInfo.joinPaths(sdkDir, "platforms"), @@ -129,19 +101,56 @@ function prepareDex(project, product, inputs, outputs, input, output, explicitly return [cmd]; } +function findParentDir(filePath, parentDirName) +{ + var lastDir; + var currentDir = FileInfo.path(filePath); + while (lastDir !== currentDir) { + if (FileInfo.fileName(currentDir) === parentDirName) + return currentDir; + lastDir = currentDir; + currentDir = FileInfo.path(currentDir); + } +} + function commonAaptPackageArgs(project, product, inputs, outputs, input, output, explicitlyDependsOn) { - var manifestFilePath = inputs["android.manifest"][0].filePath; + var manifestFilePath = inputs["android.manifest_final"][0].filePath; var args = ["package", "-f", "-M", manifestFilePath, "-I", product.Android.sdk.androidJarFilePath]; var resources = inputs["android.resources"]; - if (resources && resources.length) - args.push("-S", product.resourcesDir); + var resourceDirs = []; + if (resources) { + for (var i = 0; i < resources.length; ++i) { + var resDir = findParentDir(resources[i].filePath, "res"); + if (!resDir) { + throw "File '" + resources[i].filePath + "' is tagged as an Android resource, " + + "but is not located under a directory called 'res'."; + } + if (!resourceDirs.contains(resDir)) + resourceDirs.push(resDir); + } + } + for (i = 0; i < resourceDirs.length; ++i) + args.push("-S", resourceDirs[i]); + var assets = inputs["android.assets"]; + var assetDirs = []; + if (assets) { + for (i = 0; i < assets.length; ++i) { + var assetDir = findParentDir(assets[i].filePath, "assets"); + if (!assetDir) { + throw "File '" + assets[i].filePath + "' is tagged as an Android asset, " + + "but is not located under a directory called 'assets'."; + } + if (!assetDirs.contains(assetDir)) + assetDirs.push(assetDir); + } + } + for (i = 0; i < assetDirs.length; ++i) + args.push("-A", assetDirs[i]); if (product.qbs.buildVariant === "debug") args.push("--debug-mode"); - if (File.exists(product.assetsDir)) - args.push("-A", product.assetsDir); return args; } @@ -210,3 +219,24 @@ function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath) { "CN=Android Debug,O=Android,C=US"]; return Process.shellQuote(keytoolFilePath, args); } + +function gdbserverOrStlDeploymentData(product, inputs, type) +{ + var data = { uniqueInputs: [], outputFilePaths: []}; + var uniqueFilePaths = []; + var theInputs = inputs[type === "gdbserver" ? "android.gdbserver" : "android.stl"]; + if (!theInputs) + return data; + for (var i = 0; i < theInputs.length; ++i) { + var currentInput = theInputs[i]; + if (uniqueFilePaths.contains(currentInput.filePath)) + continue; + uniqueFilePaths.push(currentInput.filePath); + data.uniqueInputs.push(currentInput); + var outputFileName = type === "gdbserver" ? "libgdbserver.so" : currentInput.fileName; + data.outputFilePaths.push(FileInfo.joinPaths(product.Android.sdk.apkContentsDir, "lib", + currentInput.Android.ndk.abi, + outputFileName)); + } + return data; +} diff --git a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs index aecad6126..8cc55f885 100644 --- a/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs +++ b/share/qbs/modules/Exporter/pkgconfig/pkgconfig.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.FileInfo import qbs.TextFile diff --git a/share/qbs/modules/Exporter/qbs/qbsexporter.qbs b/share/qbs/modules/Exporter/qbs/qbsexporter.qbs index 351edfefe..861483ef0 100644 --- a/share/qbs/modules/Exporter/qbs/qbsexporter.qbs +++ b/share/qbs/modules/Exporter/qbs/qbsexporter.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.FileInfo import qbs.TextFile diff --git a/share/qbs/modules/archiver/archiver.qbs b/share/qbs/modules/archiver/archiver.qbs index c70b57bf4..6ae53dd37 100644 --- a/share/qbs/modules/archiver/archiver.qbs +++ b/share/qbs/modules/archiver/archiver.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.Environment import qbs.File import qbs.FileInfo @@ -52,7 +51,7 @@ Module { Probes.BinaryProbe { id: sevenZipProbe names: ["7z"] - platformPaths: { + platformSearchPaths: { var paths = base; if (qbs.hostOS.contains("windows")) { var env32 = Environment.getEnv("PROGRAMFILES(X86)"); diff --git a/share/qbs/modules/autotest/autotest.qbs b/share/qbs/modules/autotest/autotest.qbs new file mode 100644 index 000000000..ba280169e --- /dev/null +++ b/share/qbs/modules/autotest/autotest.qbs @@ -0,0 +1,5 @@ +Module { + property stringList arguments + property bool allowFailure: false + property string workingDir +} diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs index 7752ee65e..ec0062347 100644 --- a/share/qbs/modules/bundle/BundleModule.qbs +++ b/share/qbs/modules/bundle/BundleModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.BundleTools import qbs.DarwinTools import qbs.Environment @@ -264,7 +263,8 @@ Module { Rule { condition: qbs.targetOS.contains("darwin") multiplex: true - inputs: ["qbs", "infoplist", "partial_infoplist"] + requiresInputs: false // TODO: The resources property should probably be a tag instead. + inputs: ["infoplist", "partial_infoplist"] outputFileTags: ["bundle.input", "aggregate_infoplist"] outputArtifacts: { @@ -518,7 +518,7 @@ Module { "bundle.symlink.headers", "bundle.symlink.private-headers", "bundle.symlink.resources", "bundle.symlink.executable", "bundle.symlink.version", "bundle.hpp", "bundle.resource", - "bundle.provisioningprofile"] + "bundle.provisioningprofile", "bundle.content.copied", "bundle.application-executable"] outputArtifacts: { var i, artifacts = []; if (ModUtils.moduleProperty(product, "isBundle")) { diff --git a/share/qbs/modules/cli/CLIModule.qbs b/share/qbs/modules/cli/CLIModule.qbs index 866580029..d0ca120ef 100644 --- a/share/qbs/modules/cli/CLIModule.qbs +++ b/share/qbs/modules/cli/CLIModule.qbs @@ -1,5 +1,4 @@ // base for Common Language Infrastructure modules -import qbs import qbs.FileInfo import qbs.ModUtils import "cli.js" as CLI diff --git a/share/qbs/modules/cli/mono.qbs b/share/qbs/modules/cli/mono.qbs index c679c4bf0..f04956a5e 100644 --- a/share/qbs/modules/cli/mono.qbs +++ b/share/qbs/modules/cli/mono.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.File import qbs.Probes @@ -13,7 +12,7 @@ CLIModule { Probes.PathProbe { id: monoProbe names: ["mono"] - platformPaths: { + platformSearchPaths: { var paths = []; if (qbs.hostOS.contains("macos")) paths.push("/Library/Frameworks/Mono.framework/Commands"); diff --git a/share/qbs/modules/cli/windows-dotnet.qbs b/share/qbs/modules/cli/windows-dotnet.qbs index b1b29d7a9..6fde50b85 100644 --- a/share/qbs/modules/cli/windows-dotnet.qbs +++ b/share/qbs/modules/cli/windows-dotnet.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.Utilities CLIModule { diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs index c26be036d..01b0f8af9 100644 --- a/share/qbs/modules/cpp/CppModule.qbs +++ b/share/qbs/modules/cpp/CppModule.qbs @@ -178,6 +178,7 @@ Module { property string debugInfoSuffix: "" property string debugInfoBundleSuffix: "" property string variantSuffix: "" + property string dynamicLibraryImportSuffix: ".lib" property bool createSymlinks: true property stringList dynamicLibraries // list of names, will be linked with -lname property stringList staticLibraries // list of static library files @@ -353,7 +354,7 @@ Module { property stringList targetDriverFlags property stringList targetLinkerFlags - property bool _skipAllChecks: false // Internal, for testing only. + property bool _skipAllChecks: false // Internal property bool validateTargetTriple: true diff --git a/share/qbs/modules/cpp/DarwinGCC.qbs b/share/qbs/modules/cpp/DarwinGCC.qbs index 16176b4eb..0bd294fb4 100644 --- a/share/qbs/modules/cpp/DarwinGCC.qbs +++ b/share/qbs/modules/cpp/DarwinGCC.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.DarwinTools import qbs.File import qbs.FileInfo @@ -50,7 +49,7 @@ UnixGCC { id: lipoProbe condition: !_skipAllChecks names: [lipoName] - platformPaths: { + platformSearchPaths: { var paths = (xcode.present && xcode.devicePlatformPath) ? [xcode.devicePlatformPath + "/Developer/usr/bin"] : []; @@ -211,7 +210,8 @@ UnixGCC { inputsFromDependencies: ["application"] multiplex: true - outputFileTags: ["bundle.input", "application", "primary", "debuginfo_app"] + outputFileTags: ["bundle.input", "application", "primary", "debuginfo_app", + "debuginfo_bundle", "bundle.variant_symlink", "debuginfo_plist"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "application", "app") prepare: Darwin.prepareLipo.apply(Darwin, arguments) @@ -235,7 +235,8 @@ UnixGCC { multiplex: true outputFileTags: ["bundle.input", "dynamiclibrary", "dynamiclibrary_symbols", "primary", - "debuginfo_dll"] + "debuginfo_dll","debuginfo_bundle","bundle.variant_symlink", + "debuginfo_plist"] outputArtifacts: Darwin.lipoOutputArtifacts(product, inputs, "dynamiclibrary", "dll") prepare: Darwin.prepareLipo.apply(Darwin, arguments) diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 4e68dc267..972555ed7 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils @@ -389,7 +388,7 @@ CppModule { || product.multiplexConfigurationId Rule { - id: dynamicLibraryLinker + name: "dynamicLibraryLinker" condition: product.cpp.shouldLink multiplex: true inputs: { @@ -400,11 +399,12 @@ CppModule { } return tags; } - inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary"] + inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary", "dynamiclibrary_import"] outputFileTags: [ "bundle.input", - "dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_symbols", "debuginfo_dll" + "dynamiclibrary", "dynamiclibrary_symlink", "dynamiclibrary_symbols", "debuginfo_dll", + "debuginfo_bundle","dynamiclibrary_import", "debuginfo_plist", ] outputArtifacts: { var artifacts = [{ @@ -416,7 +416,14 @@ CppModule { + PathTools.bundleExecutableFilePath(product) } }]; - if (!product.qbs.toolchain.contains("mingw")) { + if (product.qbs.toolchain.contains("mingw")) { + artifacts.push({ + fileTags: ["dynamiclibrary_import"], + filePath: FileInfo.joinPaths(product.destinationDirectory, + PathTools.importLibraryFilePath(product)), + alwaysUpdated: false + }); + } else { // List of libfoo's public symbols for smart re-linking. artifacts.push({ filePath: product.destinationDirectory + "/.sosymbols/" @@ -451,11 +458,11 @@ CppModule { } Rule { - id: staticLibraryLinker + name: "staticLibraryLinker" condition: product.cpp.shouldLink multiplex: true inputs: ["obj", "linkerscript"] - inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary"] + inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"] outputFileTags: ["bundle.input", "staticlibrary", "c_staticlibrary", "cpp_staticlibrary"] outputArtifacts: { @@ -487,13 +494,14 @@ CppModule { var cmd = new Command(product.cpp.archiverPath, args); cmd.description = 'creating ' + output.fileName; cmd.highlight = 'linker' + cmd.jobPool = "linker"; cmd.responseFileUsagePrefix = '@'; return cmd; } } Rule { - id: loadableModuleLinker + name: "loadableModuleLinker" condition: product.cpp.shouldLink multiplex: true inputs: { @@ -504,9 +512,10 @@ CppModule { } return tags; } - inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary"] + inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"] - outputFileTags: ["bundle.input", "loadablemodule", "debuginfo_loadablemodule"] + outputFileTags: ["bundle.input", "loadablemodule", "debuginfo_loadablemodule", + "debuginfo_bundle","debuginfo_plist"] outputArtifacts: { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, @@ -530,7 +539,7 @@ CppModule { } Rule { - id: applicationLinker + name: "applicationLinker" condition: product.cpp.shouldLink multiplex: true inputs: { @@ -541,9 +550,10 @@ CppModule { } return tags; } - inputsFromDependencies: ["dynamiclibrary_symbols", "staticlibrary"] + inputsFromDependencies: ["dynamiclibrary_symbols", "dynamiclibrary_import", "staticlibrary"] - outputFileTags: ["bundle.input", "application", "debuginfo_app"] + outputFileTags: ["bundle.input", "application", "debuginfo_app","debuginfo_bundle", + "debuginfo_plist"] outputArtifacts: { var app = { filePath: FileInfo.joinPaths(product.destinationDirectory, @@ -566,14 +576,18 @@ CppModule { } Rule { - id: compiler + name: "compiler" inputs: ["cpp", "c", "objcpp", "objc", "asm_cpp"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch", "objc_pch", "objcpp_pch"] - outputFileTags: ["obj", "c_obj", "cpp_obj"] + outputFileTags: ["obj", "c_obj", "cpp_obj", "intermediate_obj"] outputArtifacts: { - var tags = ["obj"]; + var tags; + if (input.fileTags.contains("cpp_intermediate_object")) + tags = ["intermediate_obj"]; + else + tags = ["obj"]; if (inputs.c || inputs.objc) tags.push("c_obj"); if (inputs.cpp || inputs.objcpp) @@ -591,7 +605,7 @@ CppModule { } Rule { - id: assembler + name: "assembler" inputs: ["asm"] Artifact { diff --git a/share/qbs/modules/cpp/LinuxGCC.qbs b/share/qbs/modules/cpp/LinuxGCC.qbs index 6af648c40..14fb0a7e9 100644 --- a/share/qbs/modules/cpp/LinuxGCC.qbs +++ b/share/qbs/modules/cpp/LinuxGCC.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.Process UnixGCC { diff --git a/share/qbs/modules/cpp/UnixGCC.qbs b/share/qbs/modules/cpp/UnixGCC.qbs index ec26cffb6..e5b99cd98 100644 --- a/share/qbs/modules/cpp/UnixGCC.qbs +++ b/share/qbs/modules/cpp/UnixGCC.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.File GenericGCC { diff --git a/share/qbs/modules/cpp/android-gcc.qbs b/share/qbs/modules/cpp/android-gcc.qbs index b5dc367ee..e20f1e198 100644 --- a/share/qbs/modules/cpp/android-gcc.qbs +++ b/share/qbs/modules/cpp/android-gcc.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils @@ -90,9 +89,18 @@ LinuxGCC { Group { name: "Android STL" - condition: product.cpp.sharedStlFilePath + condition: product.cpp.sharedStlFilePath && product.cpp.shouldLink files: product.cpp.sharedStlFilePath ? [product.cpp.sharedStlFilePath] : [] - fileTags: ["android.unstripped-stl"] + fileTags: "android.stl" + } + + Group { + name: "gdbserver" + condition: qbs.buildVariant !== "release" && product.cpp.shouldLink + files: FileInfo.joinPaths(Android.ndk.ndkDir, "prebuilt", + "android-" + NdkUtils.abiNameToDirName(Android.ndk.abi), + "gdbserver", "gdbserver") + fileTags: "android.gdbserver" } toolchainInstallPath: FileInfo.joinPaths(Android.ndk.ndkDir, "toolchains", @@ -222,82 +230,24 @@ LinuxGCC { endianness: "little" Rule { - inputs: ["android.unstripped-stl"] + condition: shouldLink + inputs: "dynamiclibrary" Artifact { - filePath: FileInfo.joinPaths("stripped-libs", input.fileName); - fileTags: ["android.stripped-stl"] + filePath: FileInfo.joinPaths("stripped-libs", input.fileName) + fileTags: "android.nativelibrary" } prepare: { - var args = ["--strip-unneeded", "-o", output.filePath, input.filePath]; - var cmd = new Command(product.cpp.stripPath, args); - cmd.description = "stripping " + input.fileName; - return [cmd]; + var stripArgs = ["--strip-unneeded", "-o", output.filePath, input.filePath]; + var stripCmd = new Command(product.cpp.stripPath, stripArgs); + stripCmd.description = "Stripping unneeded symbols from " + input.fileName; + return stripCmd; } } - Rule { - inputs: ["dynamiclibrary"] - explicitlyDependsOn: ["android.stripped-stl"]; - outputFileTags: ["android.nativelibrary", "android.gdbserver-info", "android.stl-info"] - outputArtifacts: { - var artifacts = [{ - filePath: FileInfo.joinPaths("stripped-libs", - inputs["dynamiclibrary"][0].fileName), - fileTags: ["android.nativelibrary"] - }]; - if (product.moduleProperty("qbs", "buildVariant") === "debug") { - artifacts.push({ - filePath: "android.gdbserver-info.txt", - fileTags: ["android.gdbserver-info"] - }); - } - if (explicitlyDependsOn["android.stripped-stl"]) - artifacts.push({filePath: "android.stl-info.txt", fileTags: ["android.stl-info"]}); - return artifacts; - } - - prepare: { - var copyCmd = new JavaScriptCommand(); - copyCmd.silent = true; - copyCmd.sourceCode = function() { - File.copy(inputs["dynamiclibrary"][0].filePath, - outputs["android.nativelibrary"][0].filePath); - var arch = product.moduleProperty("Android.ndk", "abi"); - var destDir = FileInfo.joinPaths("lib", arch); - if (product.moduleProperty("qbs", "buildVariant") === "debug") { - arch = NdkUtils.abiNameToDirName(arch); - var srcPath = FileInfo.joinPaths( - product.moduleProperty("Android.ndk", "ndkDir"), - "prebuilt/android-" + arch, "gdbserver/gdbserver"); - var targetPath = FileInfo.joinPaths(destDir, - product.moduleProperty("Android.ndk", "gdbserverFileName")); - var infoFile = new TextFile(outputs["android.gdbserver-info"][0].filePath, - TextFile.WriteOnly); - infoFile.writeLine(srcPath); - infoFile.writeLine(targetPath); - infoFile.close(); - } - var strippedStlList = explicitlyDependsOn["android.stripped-stl"]; - if (strippedStlList) { - var srcPath = strippedStlList[0].filePath; - var targetPath = FileInfo.joinPaths(destDir, FileInfo.fileName(srcPath)); - var infoFile = new TextFile(outputs["android.stl-info"][0].filePath, - TextFile.WriteOnly); - infoFile.writeLine(srcPath); - infoFile.writeLine(targetPath); - infoFile.close(); - } - } - var stripArgs = ["--strip-unneeded", outputs["android.nativelibrary"][0].filePath]; - var stripCmd = new Command(product.moduleProperty("cpp", "stripPath"), stripArgs); - stripCmd.description = "Stripping unneeded symbols from " - + outputs["android.nativelibrary"][0].fileName; - return [copyCmd, stripCmd]; - } - } + _skipAllChecks: !shouldLink validate: { - if (!_skipAllChecks) + if (_skipAllChecks) return; var baseValidator = new ModUtils.PropertyValidator("qbs"); baseValidator.addCustomValidator("architecture", targetArch, function (value) { diff --git a/share/qbs/modules/cpp/freebsd-gcc.qbs b/share/qbs/modules/cpp/freebsd-gcc.qbs index 724f242ff..b5a4b89f3 100644 --- a/share/qbs/modules/cpp/freebsd-gcc.qbs +++ b/share/qbs/modules/cpp/freebsd-gcc.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import "freebsd.js" as FreeBSD UnixGCC { diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js index 452d7a4d1..7e25fa402 100644 --- a/share/qbs/modules/cpp/gcc.js +++ b/share/qbs/modules/cpp/gcc.js @@ -78,6 +78,8 @@ function collectLibraryDependencies(product, isDarwin) { var publicDeps = {}; var objects = []; var objectByFilePath = {}; + var tagForLinkingAgainstSharedLib = product.qbs.toolchain.contains("mingw") + ? "dynamiclibrary_import" : "dynamiclibrary"; function addObject(obj, addFunc) { addFunc.call(objects, obj); @@ -151,7 +153,7 @@ function collectLibraryDependencies(product, isDarwin) { var isStaticLibrary = typeof dep.artifacts["staticlibrary"] !== "undefined"; var isDynamicLibrary = !isStaticLibrary - && typeof dep.artifacts["dynamiclibrary"] !== "undefined"; + && typeof dep.artifacts[tagForLinkingAgainstSharedLib] !== "undefined"; if (!isStaticLibrary && !isDynamicLibrary) return; @@ -173,10 +175,10 @@ function collectLibraryDependencies(product, isDarwin) { } } else if (isDynamicLibrary) { if (!isBelowIndirectDynamicLib) { - addArtifactFilePaths(dep, "dynamiclibrary", addPublicFilePath); + addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPublicFilePath); publicDeps[dep.name] = true; } else { - addArtifactFilePaths(dep, "dynamiclibrary", addPrivateFilePath); + addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPrivateFilePath); } } } @@ -245,7 +247,7 @@ function escapeLinkerFlags(product, inputs, linkerFlags) { return linkerFlags; } -function linkerFlags(project, product, inputs, output, linkerPath) { +function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath) { var libraryPaths = product.cpp.libraryPaths; var distributionLibraryPaths = product.cpp.distributionLibraryPaths; var isDarwin = product.qbs.targetOS.contains("darwin"); @@ -261,7 +263,7 @@ function linkerFlags(project, product, inputs, output, linkerPath) { var escapableLinkerFlags = []; - if (output.fileTags.contains("dynamiclibrary")) { + if (primaryOutput.fileTags.contains("dynamiclibrary")) { if (isDarwin) { args.push((function () { var tags = ["c", "cpp", "objc", "objcpp", "asm_cpp"]; @@ -279,16 +281,18 @@ function linkerFlags(project, product, inputs, output, linkerPath) { var internalVersion = product.cpp.internalVersion; if (internalVersion && isNumericProductVersion(internalVersion)) args.push("-current_version", internalVersion); - escapableLinkerFlags.push("-install_name", UnixUtils.soname(product, output.fileName)); + escapableLinkerFlags.push("-install_name", UnixUtils.soname(product, + primaryOutput.fileName)); } else { - escapableLinkerFlags.push("-soname=" + UnixUtils.soname(product, output.fileName)); + escapableLinkerFlags.push("-soname=" + UnixUtils.soname(product, + primaryOutput.fileName)); } } - if (output.fileTags.contains("loadablemodule")) + if (primaryOutput.fileTags.contains("loadablemodule")) args.push(isDarwin ? "-bundle" : "-shared"); - if (output.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) { + if (primaryOutput.fileTags.containsAny(["dynamiclibrary", "loadablemodule"])) { if (isDarwin) escapableLinkerFlags.push("-headerpad_max_install_names"); else @@ -414,7 +418,7 @@ function linkerFlags(project, product, inputs, output, linkerPath) { // Note: due to the QCC response files hack in prepareLinker(), at least one object file or // library file must follow the output file path so that QCC has something to process before // sending the rest of the arguments through the response file. - args.push("-o", output.filePath); + args.push("-o", primaryOutput.filePath); if (inputs.obj) args = args.concat(inputs.obj.map(function (obj) { return obj.filePath })); @@ -501,6 +505,10 @@ function linkerFlags(project, product, inputs, output, linkerPath) { })); } + var importLibs = outputs.dynamiclibrary_import; + if (importLibs) + escapableLinkerFlags.push("--out-implib", importLibs[0].filePath); + var escapedLinkerFlags = escapeLinkerFlags(product, inputs, escapableLinkerFlags); Array.prototype.push.apply(escapedLinkerFlags, args); var driverLinkerFlags = useCompilerDriver ? product.cpp.driverLinkerFlags : undefined; @@ -976,6 +984,7 @@ function prepareAssembler(project, product, inputs, outputs, input, output) { var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; + cmd.jobPool = "assembler"; return cmd; } @@ -1035,7 +1044,25 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli var args = compilerFlags(project, product, input, output, explicitlyDependsOn); var wrapperArgsLength = 0; var wrapperArgs = product.cpp.compilerWrapper; + var extraEnv; if (wrapperArgs && wrapperArgs.length > 0) { + + // distcc cannot deal with absolute compiler paths (QBS-1336). + for (var i = 0; i < wrapperArgs.length; ++i) { + if (FileInfo.baseName(wrapperArgs[i]) !== "distcc") + continue; + if (i === wrapperArgs.length - 1) { + if (FileInfo.isAbsolutePath(compilerPath)) { + extraEnv = ["PATH=" + FileInfo.path(compilerPath)]; + compilerPath = FileInfo.fileName(compilerPath); + } + } else if (FileInfo.isAbsolutePath(wrapperArgs[i + 1])) { + extraEnv = ["PATH=" + FileInfo.path(FileInfo.path(wrapperArgs[i + 1]))]; + wrapperArgs[i + 1] = FileInfo.fileName(wrapperArgs[i + 1]); + } + break; + } + wrapperArgsLength = wrapperArgs.length; args.unshift(compilerPath); compilerPath = wrapperArgs.shift(); @@ -1047,7 +1074,10 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli if (pchOutput) cmd.description += ' (' + compilerInfo.tag + ')'; cmd.highlight = "compiler"; + cmd.jobPool = "compiler"; cmd.relevantEnvironmentVariables = compilerEnvVars(input, compilerInfo); + if (extraEnv) + cmd.environment = extraEnv; cmd.responseFileArgumentIndex = wrapperArgsLength; cmd.responseFileUsagePrefix = '@'; setResponseFileThreshold(cmd, product); @@ -1240,7 +1270,7 @@ function prepareLinker(project, product, inputs, outputs, input, output) { var linkerPath = effectiveLinkerPath(product, inputs) - var args = linkerFlags(project, product, inputs, primaryOutput, linkerPath); + var args = linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPath); var wrapperArgsLength = 0; var wrapperArgs = product.cpp.linkerWrapper; if (wrapperArgs && wrapperArgs.length > 0) { @@ -1266,6 +1296,7 @@ function prepareLinker(project, product, inputs, outputs, input, output) { cmd = new Command(linkerPath, args); cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; + cmd.jobPool = "linker"; cmd.relevantEnvironmentVariables = linkerEnvVars(product, inputs); cmd.responseFileArgumentIndex = responseFileArgumentIndex; cmd.responseFileUsagePrefix = useQnxResponseFileHack ? "-Wl,@" : "@"; diff --git a/share/qbs/modules/cpp/ios-gcc.qbs b/share/qbs/modules/cpp/ios-gcc.qbs index 408bc3aec..735766650 100644 --- a/share/qbs/modules/cpp/ios-gcc.qbs +++ b/share/qbs/modules/cpp/ios-gcc.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.DarwinTools import qbs.File import qbs.FileInfo diff --git a/share/qbs/modules/cpp/macos-gcc.qbs b/share/qbs/modules/cpp/macos-gcc.qbs index e2c930c80..612b46ae8 100644 --- a/share/qbs/modules/cpp/macos-gcc.qbs +++ b/share/qbs/modules/cpp/macos-gcc.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.ModUtils import qbs.Utilities diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js index d6df99dc2..1864c40e1 100644 --- a/share/qbs/modules/cpp/msvc.js +++ b/share/qbs/modules/cpp/msvc.js @@ -188,7 +188,8 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli if (product.cpp.debugInformation && product.cpp.separateDebugInformation) args.push("/Fd" + product.targetName + ".cl" + product.cpp.debugInfoSuffix); - var objOutput = outputs.obj ? outputs.obj[0] : undefined + var objectMap = outputs.obj || outputs.intermediate_obj + var objOutput = objectMap ? objectMap[0] : undefined args.push('/Fo' + FileInfo.toWindowsSeparators(objOutput.filePath)) args.push(FileInfo.toWindowsSeparators(input.filePath)) @@ -246,6 +247,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli if (pchOutput) cmd.description += ' (' + tag + ')'; cmd.highlight = "compiler"; + cmd.jobPool = "compiler"; cmd.workingDirectory = product.buildDirectory; cmd.responseFileUsagePrefix = '@'; // cl.exe outputs the cpp file name. We filter that out. @@ -261,8 +263,8 @@ function collectLibraryDependencies(product) { var seen = {}; var result = []; - function addFilePath(filePath, wholeArchive) { - result.push({ filePath: filePath, wholeArchive: wholeArchive }); + function addFilePath(filePath, wholeArchive, productName) { + result.push({ filePath: filePath, wholeArchive: wholeArchive, productName: productName }); } function addArtifactFilePaths(dep, artifacts) { @@ -270,8 +272,12 @@ function collectLibraryDependencies(product) { return; var artifactFilePaths = artifacts.map(function(a) { return a.filePath; }); var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive; - for (var i = 0; i < artifactFilePaths.length; ++i) - addFilePath(artifactFilePaths[i], wholeArchive); + var artifactsAreImportLibs = artifacts.length > 0 + && artifacts[0].fileTags.contains("dynamiclibrary_import"); + for (var i = 0; i < artifactFilePaths.length; ++i) { + addFilePath(artifactFilePaths[i], wholeArchive, + artifactsAreImportLibs ? dep.name : undefined); + } } function addExternalLibs(obj) { @@ -466,14 +472,31 @@ function prepareLinker(project, product, inputs, outputs, input, output) { args = wrapperArgs.concat(args); } var commands = []; + var warningCmd = new JavaScriptCommand(); + warningCmd.silent = true; + warningCmd.libDeps = libDeps; + warningCmd.sourceCode = function() { + for (var i = 0; i < libDeps.length; ++i) { + if (!libDeps[i].productName || File.exists(libDeps[i].filePath)) + continue; + console.warn("Import library '" + FileInfo.toNativeSeparators(libDeps[i].filePath) + + "' does not exist. This typically happens when a DLL does not " + + "export any symbols. Please make sure the '" + libDeps[i].productName + + "' library exports symbols, or, if you do not intend to actually " + + "link against it, specify \"cpp.link: false\" in the Depends item."); + } + }; + commands.push(warningCmd); var cmd = new Command(linkerPath, args) cmd.description = 'linking ' + primaryOutput.fileName; cmd.highlight = 'linker'; + cmd.jobPool = "linker"; cmd.relevantEnvironmentVariables = ["LINK", "_LINK_", "LIB", "TMP"]; cmd.workingDirectory = FileInfo.path(primaryOutput.filePath) cmd.responseFileUsagePrefix = '@'; cmd.stdoutFilterFunction = function(output) { - return output.replace(/^(.*performing full link.*\r\n)? +Creating library.*\r\n$/, ""); + res = output.replace(/^.*performing full link.*\s*/, ""); + return res.replace(/^ *Creating library.*\r\n$/, ""); }; commands.push(cmd); diff --git a/share/qbs/modules/cpp/qnx-qcc.qbs b/share/qbs/modules/cpp/qnx-qcc.qbs index 28c9ce266..a39a6a998 100644 --- a/share/qbs/modules/cpp/qnx-qcc.qbs +++ b/share/qbs/modules/cpp/qnx-qcc.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.FileInfo UnixGCC { diff --git a/share/qbs/modules/cpp/tvos-gcc.qbs b/share/qbs/modules/cpp/tvos-gcc.qbs index ae4dd5c5b..19bc9b787 100644 --- a/share/qbs/modules/cpp/tvos-gcc.qbs +++ b/share/qbs/modules/cpp/tvos-gcc.qbs @@ -28,8 +28,6 @@ ** ****************************************************************************/ -import qbs - DarwinGCC { priority: 1 condition: qbs.targetOS.contains('tvos') && diff --git a/share/qbs/modules/cpp/watchos-gcc.qbs b/share/qbs/modules/cpp/watchos-gcc.qbs index c8bd0a55d..46e4bf874 100644 --- a/share/qbs/modules/cpp/watchos-gcc.qbs +++ b/share/qbs/modules/cpp/watchos-gcc.qbs @@ -29,8 +29,6 @@ ** ****************************************************************************/ -import qbs - DarwinGCC { priority: 1 condition: qbs.targetOS.contains('watchos') && diff --git a/share/qbs/modules/cpp/windows-mingw.qbs b/share/qbs/modules/cpp/windows-mingw.qbs index 3e3ba409d..27382742f 100644 --- a/share/qbs/modules/cpp/windows-mingw.qbs +++ b/share/qbs/modules/cpp/windows-mingw.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.ModUtils import qbs.TextFile import qbs.Utilities diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs index 3164e08b5..8dd6dd2c0 100644 --- a/share/qbs/modules/cpp/windows-msvc.qbs +++ b/share/qbs/modules/cpp/windows-msvc.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils @@ -114,7 +113,6 @@ CppModule { dynamicLibrarySuffix: ".dll" executableSuffix: ".exe" debugInfoSuffix: ".pdb" - property string dynamicLibraryImportSuffix: ".lib" imageFormat: "pe" Properties { condition: product.multiplexByQbsProperties.contains("buildVariants") @@ -170,14 +168,20 @@ CppModule { } Rule { - id: compiler + name: "compiler" inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] explicitlyDependsOn: ["c_pch", "cpp_pch"] - Artifact { - fileTags: ['obj'] - filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".obj" + outputFileTags: ["obj", "intermediate_obj"] + outputArtifacts: { + var tags = input.fileTags.contains("cpp_intermediate_object") + ? ["intermediate_obj"] + : ["obj"]; + return [{ + fileTags: tags, + filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".obj" + }]; } prepare: { @@ -191,7 +195,7 @@ CppModule { } Rule { - id: applicationLinker + name: "applicationLinker" multiplex: true inputs: ['obj', 'native.pe.manifest'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"] @@ -221,7 +225,7 @@ CppModule { } Rule { - id: dynamicLibraryLinker + name: "dynamicLibraryLinker" multiplex: true inputs: ['obj', 'native.pe.manifest'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"] @@ -256,7 +260,7 @@ CppModule { } Rule { - id: libtool + name: "libtool" multiplex: true inputs: ["obj"] inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"] @@ -289,6 +293,7 @@ CppModule { var cmd = new Command("lib.exe", args); cmd.description = 'creating ' + lib.fileName; cmd.highlight = 'linker'; + cmd.jobPool = "linker"; cmd.workingDirectory = FileInfo.path(lib.filePath) cmd.responseFileUsagePrefix = '@'; return cmd; @@ -341,6 +346,7 @@ CppModule { var cmd = new Command('rc', args); cmd.description = 'compiling ' + input.fileName; cmd.highlight = 'compiler'; + cmd.jobPool = "compiler"; if (!hasNoLogo) { // Remove the first two lines of stdout. That's the logo. @@ -377,6 +383,7 @@ CppModule { ModUtils.moduleProperty(input, 'flags', 'asm')); var cmd = new Command(product.cpp.assemblerPath, args); cmd.description = "assembling " + input.fileName; + cmd.jobPool = "assembler"; cmd.inputFileName = input.fileName; cmd.stdoutFilterFunction = function(output) { var lines = output.split("\r\n").filter(function (s) { diff --git a/share/qbs/modules/cpufeatures/cpufeatures.qbs b/share/qbs/modules/cpufeatures/cpufeatures.qbs index a7ef95193..17e6b851e 100644 --- a/share/qbs/modules/cpufeatures/cpufeatures.qbs +++ b/share/qbs/modules/cpufeatures/cpufeatures.qbs @@ -1,5 +1,3 @@ -import qbs - Module { property bool arm_neon property bool arm_vfpv4 diff --git a/share/qbs/modules/dmg/DMGModule.qbs b/share/qbs/modules/dmg/DMGModule.qbs index 09e31f696..c5d097a0b 100644 --- a/share/qbs/modules/dmg/DMGModule.qbs +++ b/share/qbs/modules/dmg/DMGModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.DarwinTools import qbs.File import qbs.FileInfo @@ -140,7 +139,7 @@ Module { Rule { multiplex: true - inputs: ["qbs", "dmg.input", "dmg.license", "icns", "tiff"] + inputs: ["dmg.input", "dmg.license", "icns", "tiff"] Artifact { fileTags: ["dmg.dmg"] diff --git a/share/qbs/modules/ib/IBModule.qbs b/share/qbs/modules/ib/IBModule.qbs index 66d76aede..6af5e94e4 100644 --- a/share/qbs/modules/ib/IBModule.qbs +++ b/share/qbs/modules/ib/IBModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.BundleTools import qbs.DarwinTools import qbs.File @@ -175,7 +174,7 @@ Module { inputs: ["nib", "storyboard"] outputFileTags: { - var tags = []; + var tags = ["partial_infoplist"]; for (var i = 0; i < inputs.length; ++i) tags = tags.uniqueConcat(ModUtils.allFileTags(Ib.ibtoolFileTaggers(inputs[i]))); return tags; diff --git a/share/qbs/modules/ico/IcoModule.qbs b/share/qbs/modules/ico/IcoModule.qbs index 444fcd597..7157aab09 100644 --- a/share/qbs/modules/ico/IcoModule.qbs +++ b/share/qbs/modules/ico/IcoModule.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils diff --git a/share/qbs/modules/innosetup/InnoSetupModule.qbs b/share/qbs/modules/innosetup/InnoSetupModule.qbs index bc5b74460..1caf39dc8 100644 --- a/share/qbs/modules/innosetup/InnoSetupModule.qbs +++ b/share/qbs/modules/innosetup/InnoSetupModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.FileInfo import qbs.ModUtils import qbs.Probes diff --git a/share/qbs/modules/java/JavaModule.qbs b/share/qbs/modules/java/JavaModule.qbs index 928684a4f..5191d6497 100644 --- a/share/qbs/modules/java/JavaModule.qbs +++ b/share/qbs/modules/java/JavaModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.FileInfo import qbs.ModUtils import qbs.Probes @@ -65,6 +64,8 @@ Module { property string keytoolFilePath: FileInfo.joinPaths(jdkPath, "bin", keytoolName) property string keytoolName: "keytool" + property bool _tagJniHeaders: true + property string jdkPath: jdk.path version: [compilerVersionMajor, compilerVersionMinor, compilerVersionPatch].join(".") @@ -233,9 +234,17 @@ Module { inputsFromDependencies: ["java.jar"] explicitlyDependsOn: ["java.class-internal"] - outputFileTags: ["java.class", "hpp"] // Annotations can produce additional java source files. Ignored for now. + outputFileTags: ["java.class"].concat(_tagJniHeaders ? ["hpp"] : []) // Annotations can produce additional java source files. Ignored for now. outputArtifacts: { - return JavaUtils.outputArtifacts(product, inputs); + var artifacts = JavaUtils.outputArtifacts(product, inputs); + if (!product.java._tagJniHeaders) { + for (var i = 0; i < artifacts.length; ++i) { + var a = artifacts[i]; + if (Array.isArray(a.fileTags)) + a.fileTags = a.fileTags.filter(function(tag) { return tag != "hpp"; }); + } + } + return artifacts; } prepare: { var cmd = new Command(ModUtils.moduleProperty(product, "compilerFilePath"), diff --git a/share/qbs/modules/lex_yacc/lexyacc.qbs b/share/qbs/modules/lex_yacc/lexyacc.qbs index 20982f7aa..48af1d793 100644 --- a/share/qbs/modules/lex_yacc/lexyacc.qbs +++ b/share/qbs/modules/lex_yacc/lexyacc.qbs @@ -1,4 +1,3 @@ -import qbs import "lexyacc.js" as HelperFunctions Module { diff --git a/share/qbs/modules/nodejs/NodeJS.qbs b/share/qbs/modules/nodejs/NodeJS.qbs index b40ea2d9e..7fd992fdb 100644 --- a/share/qbs/modules/nodejs/NodeJS.qbs +++ b/share/qbs/modules/nodejs/NodeJS.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.Environment import qbs.File import qbs.FileInfo @@ -42,12 +41,12 @@ Module { Probes.NodeJsProbe { id: nodejs - pathPrefixes: toolchainInstallPath ? [toolchainInstallPath] : [] + searchPaths: toolchainInstallPath ? [toolchainInstallPath] : [] } Probes.NpmProbe { id: npm - pathPrefixes: toolchainInstallPath ? [toolchainInstallPath] : [] + searchPaths: toolchainInstallPath ? [toolchainInstallPath] : [] interpreterPath: FileInfo.path(nodejs.filePath) } diff --git a/share/qbs/modules/nsis/NSISModule.qbs b/share/qbs/modules/nsis/NSISModule.qbs index ef1d5b0e1..e426aee56 100644 --- a/share/qbs/modules/nsis/NSISModule.qbs +++ b/share/qbs/modules/nsis/NSISModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.File import qbs.FileInfo import qbs.ModUtils diff --git a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs new file mode 100644 index 000000000..5cb3257d4 --- /dev/null +++ b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs @@ -0,0 +1,48 @@ +import qbs +import qbs.File +import qbs.FileInfo +import qbs.Probes +import "../protobufbase.qbs" as ProtobufBase +import "../protobuf.js" as HelperFunctions + +ProtobufBase { + property string includePath: includeProbe.path + property string libraryPath: libraryProbe.path + + Depends { name: "cpp" } + + cpp.libraryPaths: [libraryPath] + cpp.dynamicLibraries: qbs.targetOS.contains("unix") ? ["protobuf", "pthread"] : ["protobuf"] + cpp.includePaths: [outputDir, includePath] + + Rule { + inputs: ["protobuf.input"] + outputFileTags: ["hpp", "cpp"] + outputArtifacts: { + return [ + HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "hpp", ".pb.h"), + HelperFunctions.cppArtifact(input.protobuf.cpp, product, input, "cpp", ".pb.cc") + ]; + } + + prepare: HelperFunctions.doPrepare(input.protobuf.cpp, product, input, outputs, "cpp") + } + + validate: { + baseValidate(); + if (!HelperFunctions.checkPath(includePath)) + throw "Can't find cpp protobuf include files. Please set the includePath property."; + if (!HelperFunctions.checkPath(libraryPath)) + throw "Can't find cpp protobuf library. Please set the libraryPath property."; + } + + Probes.IncludeProbe { + id: includeProbe + names: "google/protobuf/message.h" + } + + Probes.LibraryProbe { + id: libraryProbe + names: "protobuf" + } +} diff --git a/share/qbs/modules/protobuf/objc/protobufobjc.qbs b/share/qbs/modules/protobuf/objc/protobufobjc.qbs new file mode 100644 index 000000000..c252d9949 --- /dev/null +++ b/share/qbs/modules/protobuf/objc/protobufobjc.qbs @@ -0,0 +1,70 @@ +import qbs +import qbs.File +import qbs.FileInfo +import qbs.Probes +import "../protobufbase.qbs" as ProtobufBase +import "../protobuf.js" as HelperFunctions + +ProtobufBase { + property string includePath: includeProbe.path + property string libraryPath: libraryProbe.path + property string frameworkPath: frameworkProbe.path + + Depends { name: "cpp" } + + // library build + Properties { + condition: !frameworkPath + cpp.includePaths: [outputDir, includePath] + cpp.libraryPaths: [libraryPath] + cpp.frameworks: ["Foundation"] + cpp.dynamicLibraries: ["ProtocolBuffers"] + } + + // framework build + Properties { + condition: frameworkPath + cpp.includePaths: [outputDir] + cpp.frameworkPaths: [frameworkPath] + cpp.frameworks: ["Foundation", "Protobuf"] + cpp.defines: ["GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS"] + } + + Rule { + inputs: ["protobuf.input"] + outputFileTags: ["hpp", "objc"] + outputArtifacts: { + return [ + HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "hpp", ".pbobjc.h"), + HelperFunctions.objcArtifact(input.protobuf.objc, product, input, "objc", ".pbobjc.m") + ]; + } + + prepare: HelperFunctions.doPrepare(input.protobuf.objc, product, input, outputs, "objc") + } + + validate: { + baseValidate(); + if (!HelperFunctions.checkPath(frameworkPath)) { + if (!HelperFunctions.checkPath(includePath)) + throw "Can't find objective-c protobuf include files. Please set the includePath or frameworkPath property."; + if (!HelperFunctions.checkPath(libraryPath)) + throw "Can't find objective-c protobuf library. Please set the libraryPath or frameworkPath property."; + } + } + + Probes.IncludeProbe { + id: includeProbe + names: "GPBMessage.h" + } + + Probes.LibraryProbe { + id: libraryProbe + names: "ProtocolBuffers" + } + + Probes.FrameworkProbe { + id: frameworkProbe + names: ["Protobuf"] + } +} diff --git a/share/qbs/modules/protobuf/protobuf.js b/share/qbs/modules/protobuf/protobuf.js new file mode 100644 index 000000000..576a5ec07 --- /dev/null +++ b/share/qbs/modules/protobuf/protobuf.js @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Ivan Komissarov +** Contact: abbapoh@gmail.com +** +** This file is part of Qbs. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +var File = require("qbs.File"); +var FileInfo = require("qbs.FileInfo"); + +var checkPath = function(path) { + return path && File.exists(path) +}; + +function toCamelCase(str){ + return str.split('_').map(function(word, index) { + // If it is the first word make sure to lowercase all the chars. + if (index === 0) { + return word.toLowerCase(); + } + // If it is not the first word only upper case the first char and lowercase the rest. + return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); + }).join(''); +} + +function getOutputDir(module, product, input) { + var outputDir = module.outputDir; + var importPaths = module.importPaths; + if (importPaths.length !== 0) { + var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath)); + for (var i = 0; i < importPaths.length; ++i) { + path = File.canonicalFilePath(importPaths[i]); + + if (canonicalInput.startsWith(path)) { + return outputDir + "/" + FileInfo.relativePath(path, canonicalInput); + } + } + } + return outputDir; +} + +function cppArtifact(module, product, input, tag, suffix) { + var outputDir = getOutputDir(module, product, input); + return { + fileTags: [tag], + filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix, + cpp: { + includePaths: [].concat(input.cpp.includePaths, outputDir), + warningLevel: "none", + } + }; +} + +function objcArtifact(module, product, input, tag, suffix) { + var outputDir = getOutputDir(module, product, input); + return { + fileTags: [tag], + filePath: outputDir + "/" + toCamelCase(FileInfo.baseName(input.fileName)) + suffix, + cpp: { + includePaths: [].concat(input.cpp.includePaths, outputDir), + warningLevel: "none", + } + } +} + +function doPrepare(module, product, input, outputs, lang) +{ + var outputDir = module.outputDir; + var args = []; + + args.push("--" + lang + "_out", outputDir); + + var importPaths = module.importPaths; + if (importPaths.length === 0) + importPaths = [FileInfo.path(input.filePath)]; + importPaths.forEach(function(path) { + if (!FileInfo.isAbsolutePath(path)) + path = FileInfo.joinPaths(product.sourceDirectory, path); + args.push("--proto_path", path); + }); + + args.push(input.filePath); + + var cmd = new Command(module.protocBinary, args); + cmd.highlight = "codegen"; + cmd.description = "generating " + lang + " files for " + input.fileName; + return [cmd]; +} diff --git a/share/qbs/modules/protobuf/protobufbase.qbs b/share/qbs/modules/protobuf/protobufbase.qbs new file mode 100644 index 000000000..1c2e68800 --- /dev/null +++ b/share/qbs/modules/protobuf/protobufbase.qbs @@ -0,0 +1,30 @@ +import qbs +import qbs.File +import qbs.FileInfo +import qbs.Probes +import "protobuf.js" as HelperFunctions + +Module { + property string protocBinary: protocProbe.filePath + property pathList importPaths: [] + + property string outputDir: product.buildDirectory + "/protobuf" + readonly property string protobufRoot: FileInfo.path(FileInfo.path(protocBinary)) + + readonly property var baseValidate: { + return function() { + if (!File.exists(protocBinary)) + throw "Can't find protoc binary. Please set the protocBinary property or make sure it is found in PATH"; + } + } + + FileTagger { + patterns: ["*.proto"] + fileTags: ["protobuf.input"]; + } + + Probes.BinaryProbe { + id: protocProbe + names: ["protoc"] + } +} diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs index 86ce27c59..63bc29f8e 100644 --- a/share/qbs/modules/qbs/common.qbs +++ b/share/qbs/modules/qbs/common.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs 1.0 import qbs.Environment import qbs.FileInfo import qbs.ModUtils @@ -102,7 +101,7 @@ Module { property path installSourceBase property string installRoot: project.buildDirectory + "/install-root" property string installDir - property string installPrefix: "" + property string installPrefix: qbs.targetOS.contains("unix") ? "/usr/local" : "" property path sysroot PropertyOptions { @@ -196,28 +195,9 @@ Module { } // Properties that can be set for multiplexing products. - property stringList profiles - property stringList architectures: { - if (targetOS.contains("android")) - return ["armv7a"]; // default should be armv5te for NDK < r16, but we can't check here - if (targetOS.contains("ios-simulator")) - return ["x86", "x86_64"]; - if (targetOS.contains("ios")) - return ["armv7a", "arm64"]; - if (targetOS.contains("macos")) - return ["x86_64"]; - if (targetOS.contains("tvos-simulator")) - return ["x86_64"]; - if (targetOS.contains("tvos")) - return ["arm64"]; - if (targetOS.contains("watchos-simulator")) - return ["x86"]; - if (targetOS.contains("watchos")) - return ["armv7k"]; - return architecture ? [architecture] : undefined; - } - - property stringList buildVariants: [buildVariant] + property stringList profiles: [] + property stringList architectures: [] + property stringList buildVariants: [] // internal properties readonly property string version: [versionMajor, versionMinor, versionPatch].join(".") diff --git a/share/qbs/modules/qnx/qnx.qbs b/share/qbs/modules/qnx/qnx.qbs index 49ebc36b6..9cab5abb6 100644 --- a/share/qbs/modules/qnx/qnx.qbs +++ b/share/qbs/modules/qnx/qnx.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.Environment import qbs.File import qbs.FileInfo @@ -40,7 +39,7 @@ Module { Probes.PathProbe { id: qnxSdkProbe names: ["qnx700", "qnx660", "qnx650"] - pathPrefixes: qbs.hostOS.contains("windows") + searchPaths: qbs.hostOS.contains("windows") ? [Environment.getEnv("USERPROFILE"), Environment.getEnv("SystemDrive")] : [Environment.getEnv("HOME"), "/opt"] } diff --git a/share/qbs/modules/texttemplate/texttemplate.qbs b/share/qbs/modules/texttemplate/texttemplate.qbs new file mode 100644 index 000000000..c72929660 --- /dev/null +++ b/share/qbs/modules/texttemplate/texttemplate.qbs @@ -0,0 +1,64 @@ +import qbs.TextFile + +Module { + property var dict: ({}) + property string outputTag: "text" + property string outputFileName + FileTagger { + patterns: ["*.in"] + fileTags: ["texttemplate.input"] + } + Rule { + inputs: ["texttemplate.input"] + outputFileTags: [product.texttemplate.outputTag] + outputArtifacts: [ + { + fileTags: [product.texttemplate.outputTag], + filePath: input.texttemplate.outputFileName || input.completeBaseName + } + ] + prepare: { + var cmd = new JavaScriptCommand(); + cmd.silent = true; + cmd.sourceCode = function() { + try { + var src = new TextFile(input.filePath, TextFile.ReadOnly); + var dst = new TextFile(output.filePath, TextFile.WriteOnly); + var rex = /\${(\$|\w+)}/g; + var match; + while (!src.atEof()) { + rex.lastIndex = 0; + var line = src.readLine(); + var matches = []; + while (match = rex.exec(line)) + matches.push(match); + for (var i = matches.length; --i >= 0;) { + match = matches[i]; + var replacement; + if (match[1] === "$") { + replacement = "$"; + } else { + replacement = input.texttemplate.dict[match[1]]; + if (typeof replacement === "undefined") { + throw new Error("Placeholder '" + match[1] + + "' is not defined in textemplate.dict for '" + + input.fileName + "'."); + } + } + line = line.substr(0, match.index) + + replacement + + line.substr(match.index + match[0].length); + } + dst.writeLine(line); + } + } finally { + if (src) + src.close(); + if (dst) + dst.close(); + } + }; + return [cmd]; + } + } +} diff --git a/share/qbs/modules/typescript/TypeScriptModule.qbs b/share/qbs/modules/typescript/TypeScriptModule.qbs index 7cbd02265..d8e61b17f 100644 --- a/share/qbs/modules/typescript/TypeScriptModule.qbs +++ b/share/qbs/modules/typescript/TypeScriptModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils diff --git a/share/qbs/modules/vcs/vcs-module.qbs b/share/qbs/modules/vcs/vcs-module.qbs index ee7a34582..f3a47d2a6 100644 --- a/share/qbs/modules/vcs/vcs-module.qbs +++ b/share/qbs/modules/vcs/vcs-module.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.File import qbs.FileInfo import qbs.Process diff --git a/share/qbs/modules/wix/WiXModule.qbs b/share/qbs/modules/wix/WiXModule.qbs index 3159822de..ad8586da1 100644 --- a/share/qbs/modules/wix/WiXModule.qbs +++ b/share/qbs/modules/wix/WiXModule.qbs @@ -28,7 +28,6 @@ ** ****************************************************************************/ -import qbs import qbs.File import qbs.FileInfo import qbs.ModUtils diff --git a/share/qbs/modules/xcode/xcode.qbs b/share/qbs/modules/xcode/xcode.qbs index 0df7f5204..922580505 100644 --- a/share/qbs/modules/xcode/xcode.qbs +++ b/share/qbs/modules/xcode/xcode.qbs @@ -1,4 +1,3 @@ -import qbs import qbs.BundleTools import qbs.Environment import qbs.File |