diff options
author | Ivan Komissarov <abbapoh@gmail.com> | 2021-04-24 02:20:06 +0300 |
---|---|---|
committer | Ivan Komissarov <abbapoh@gmail.com> | 2021-04-24 02:20:06 +0300 |
commit | a8bbaf016dc3092f6f6ad0c4a333e595da665983 (patch) | |
tree | 6b1b74bbca7850ed75da01cba5a72618f3cfa94b /share | |
parent | 001bf31623c02ba8249dd066777d014d546eb7f9 (diff) | |
parent | 2f6eecdc96fcd693cecef8011d8f9500c7872fc7 (diff) |
Merge branch '1.19' into master
Change-Id: Ic6087168a1d93c2a2b46de825f5c3b9655634e8e
Diffstat (limited to 'share')
22 files changed, 575 insertions, 114 deletions
diff --git a/share/CMakeLists.txt b/share/CMakeLists.txt index f607e0a85..bde65d450 100644 --- a/share/CMakeLists.txt +++ b/share/CMakeLists.txt @@ -36,8 +36,7 @@ get_update_path_command(UPDATE_PATH_COMMAND) get_target_property(_QBS_OUTPUT_DIR qbs RUNTIME_OUTPUT_DIRECTORY) add_custom_target( BuildQbsResources ALL - COMMAND ${UPDATE_PATH_COMMAND} - COMMAND ${_QBS_OUTPUT_DIR}/qbs + COMMAND ${CMAKE_COMMAND} -E env "${UPDATE_PATH_COMMAND}" ${_QBS_OUTPUT_DIR}/qbs resolve --settings-dir ${PROJECT_BINARY_DIR}/settings -f ${PROJECT_SOURCE_DIR}/qbs.qbs @@ -47,7 +46,7 @@ add_custom_target( project.withCode:false project.withDocumentation:false profile:none - COMMAND ${_QBS_OUTPUT_DIR}/qbs + COMMAND ${CMAKE_COMMAND} -E env "${UPDATE_PATH_COMMAND}" ${_QBS_OUTPUT_DIR}/qbs build --settings-dir ${PROJECT_BINARY_DIR}/settings -f ${PROJECT_SOURCE_DIR}/qbs.qbs diff --git a/share/qbs/imports/qbs/Probes/ClangClProbe.qbs b/share/qbs/imports/qbs/Probes/ClangClProbe.qbs index 8205e92fa..658da8a9f 100644 --- a/share/qbs/imports/qbs/Probes/ClangClProbe.qbs +++ b/share/qbs/imports/qbs/Probes/ClangClProbe.qbs @@ -42,6 +42,7 @@ PathProbe { property string preferredArchitecture property string _nullDevice: qbs.nullDevice property string _pathListSeparator: qbs.pathListSeparator + property string winSdkVersion // Outputs property int versionMajor @@ -58,9 +59,21 @@ PathProbe { languages = ["c"]; var info = languages.contains("c") - ? Utilities.clangClCompilerInfo(compilerFilePath, preferredArchitecture, vcvarsallFilePath, "c") : {}; + ? Utilities.clangClCompilerInfo( + compilerFilePath, + preferredArchitecture, + vcvarsallFilePath, + "c", + winSdkVersion) + : {}; var infoCpp = languages.contains("cpp") - ? Utilities.clangClCompilerInfo(compilerFilePath, preferredArchitecture, vcvarsallFilePath, "cpp") : {}; + ? Utilities.clangClCompilerInfo( + compilerFilePath, + preferredArchitecture, + vcvarsallFilePath, + "cpp", + winSdkVersion) + : {}; found = (!languages.contains("c") || (!!info && !!info.macros && !!info.buildEnvironment)) && (!languages.contains("cpp") || diff --git a/share/qbs/imports/qbs/Probes/MsvcProbe.qbs b/share/qbs/imports/qbs/Probes/MsvcProbe.qbs index 2d5faecdd..d3624e010 100644 --- a/share/qbs/imports/qbs/Probes/MsvcProbe.qbs +++ b/share/qbs/imports/qbs/Probes/MsvcProbe.qbs @@ -38,6 +38,7 @@ PathProbe { property string compilerFilePath property stringList enableDefinesByLanguage property string preferredArchitecture + property string winSdkVersion // Outputs property string architecture @@ -54,9 +55,9 @@ PathProbe { languages = ["c"]; var info = languages.contains("c") - ? Utilities.msvcCompilerInfo(compilerFilePath, "c") : {}; + ? Utilities.msvcCompilerInfo(compilerFilePath, "c", winSdkVersion) : {}; var infoCpp = languages.contains("cpp") - ? Utilities.msvcCompilerInfo(compilerFilePath, "cpp") : {}; + ? Utilities.msvcCompilerInfo(compilerFilePath, "cpp", winSdkVersion) : {}; found = (!languages.contains("c") || (!!info && !!info.macros && !!info.buildEnvironment)) && (!languages.contains("cpp") || diff --git a/share/qbs/module-providers/Qt/templates/android_support.qbs b/share/qbs/module-providers/Qt/templates/android_support.qbs index 87c980448..68a29bb95 100644 --- a/share/qbs/module-providers/Qt/templates/android_support.qbs +++ b/share/qbs/module-providers/Qt/templates/android_support.qbs @@ -4,6 +4,7 @@ import qbs.ModUtils import qbs.TextFile import qbs.Utilities import qbs.Process +import qbs.Xml Module { version: @version@ @@ -35,6 +36,10 @@ Module { property bool _multiAbi: Utilities.versionCompare(version, "5.14") >= 0 + // QTBUG-87288: correct QtNetwork jar dependencies for 5.15.0 < Qt < 5.15.3 + property bool _correctQtNetworkDependencies: Utilities.versionCompare(version, "5.15.0") > 0 && + Utilities.versionCompare(version, "5.15.3") < 0 + Depends { name: "Android.sdk"; condition: _enableSdkSupport } Depends { name: "Android.ndk"; condition: _enableNdkSupport } Depends { name: "java"; condition: _enableSdkSupport } @@ -355,8 +360,6 @@ Module { var moveCmd = new JavaScriptCommand(); moveCmd.description = "processing androiddeployqt outout"; moveCmd.sourceCode = function() { - 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.packageContentsDir + "/lib"; var listFilePath = outputs["android.deployqt_list"][0].filePath; @@ -400,7 +403,78 @@ Module { File.remove(oldLibs[i]); } }; - return [copyCmd, androidDeployQtCmd, moveCmd]; + + var correctingCmd = new JavaScriptCommand(); + if (product.Qt.android_support._correctQtNetworkDependencies) { + correctingCmd.description = "correcting network jar dependency"; + correctingCmd.sourceCode = function() { + var findNetworkLib = function() { + var libsDir = product.Android.sdk.packageContentsDir + "/lib"; + var dirList = File.directoryEntries(libsDir, File.Dirs | + File.NoDotAndDotDot); + for (var i = 0; i < dirList.length; ++i) { + var archDir = FileInfo.joinPaths(libsDir, dirList[i]); + var fileList = File.directoryEntries(archDir, File.Files); + if (fileList) { + for (var j = 0; j < fileList.length; ++j) { + if (fileList[j].contains("libQt5Network")) { + return true; + } + } + } + } + return false; + } + + if (findNetworkLib()) { + var manifestData = new Xml.DomDocument(); + var manifestFilePath = product.Qt.android_support._deployQtOutDir + + "/AndroidManifest.xml" + manifestData.load(manifestFilePath); + + var rootElem = manifestData.documentElement(); + if (!rootElem || !rootElem.isElement() || rootElem.tagName() != "manifest") + throw "No manifest tag found in '" + manifestFilePath + "'."; + var appElem = rootElem.firstChild("application"); + if (!appElem || !appElem.isElement() || appElem.tagName() != "application") + throw "No application tag found in '" + manifestFilePath + "'."; + var activityElem = appElem.firstChild("activity"); + if (!activityElem || !activityElem.isElement() || + activityElem.tagName() != "activity") + throw "No activity tag found in '" + manifestFilePath + "'."; + var metaDataElem = activityElem.firstChild("meta-data"); + while (metaDataElem && metaDataElem.isElement()) { + if (metaDataElem.attribute("android:name") == + "android.app.load_local_jars" ) { + var value = metaDataElem.attribute("android:value"); + var fileName = "QtAndroidNetwork.jar"; + metaDataElem.setAttribute("android:value", value + ":jar/" + + fileName); + var jarFilePath = FileInfo.joinPaths( + product.Qt.android_support._qtInstallDir, "jar", + fileName); + var targetFilePath = FileInfo.joinPaths(product.java.classFilesDir, + fileName); + File.copy(jarFilePath, targetFilePath); + break; + } + metaDataElem = metaDataElem.nextSibling("meta-data"); + } + manifestData.save(outputs["android.manifest_final"][0].filePath, 4); + } else { + File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml", + outputs["android.manifest_final"][0].filePath); + } + }; + } else { + correctingCmd.description = "copying manifest"; + correctingCmd.sourceCode = function() { + File.move(product.Qt.android_support._deployQtOutDir + "/AndroidManifest.xml", + outputs["android.manifest_final"][0].filePath); + } + } + + return [copyCmd, androidDeployQtCmd, moveCmd, correctingCmd]; } } diff --git a/share/qbs/module-providers/Qt/templates/qml.js b/share/qbs/module-providers/Qt/templates/qml.js index df69034fe..e48c9230e 100644 --- a/share/qbs/module-providers/Qt/templates/qml.js +++ b/share/qbs/module-providers/Qt/templates/qml.js @@ -3,14 +3,31 @@ var FileInfo = require("qbs.FileInfo"); var Process = require("qbs.Process"); var TextFile = require("qbs.TextFile"); -function scannerData(scannerFilePath, qmlFiles, qmlPath) +function scannerData(scannerFilePath, qmlFiles, qmlPath, targetOS) { var p; try { p = new Process(); - p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]), - true); - return JSON.parse(p.readStdOut()); + if (!targetOS.contains("windows")) { + p.exec(scannerFilePath, ["-qmlFiles"].concat(qmlFiles).concat(["-importPath", qmlPath]), + true); + return JSON.parse(p.readStdOut()); + } + var data = []; + var nextFileIndex = 0; + while (nextFileIndex < qmlFiles.length) { + var currentFileList = []; + var currentFileListStringLength = 0; + while (nextFileIndex < qmlFiles.length && currentFileListStringLength < 30000) { + var currentFile = qmlFiles[nextFileIndex++]; + currentFileList.push(currentFile); + currentFileListStringLength += currentFile.length; + } + p.exec(scannerFilePath, ["-qmlFiles"].concat(currentFileList) + .concat(["-importPath", qmlPath]), true); + data = data.concat(JSON.parse(p.readStdOut())); + } + return data; } finally { if (p) p.close(); diff --git a/share/qbs/module-providers/Qt/templates/qml.qbs b/share/qbs/module-providers/Qt/templates/qml.qbs index f608ba4dd..af7b0fb5f 100644 --- a/share/qbs/module-providers/Qt/templates/qml.qbs +++ b/share/qbs/module-providers/Qt/templates/qml.qbs @@ -144,7 +144,7 @@ QtModule { qmlInputs = []; var scannerData = Qml.scannerData(product.Qt.qml.qmlImportScannerFilePath, qmlInputs.map(function(inp) { return inp.filePath; }), - product.Qt.qml.qmlPath); + product.Qt.qml.qmlPath, product.qbs.targetOS); var cppFile; var listFile; try { diff --git a/share/qbs/modules/Android/sdk/utils.js b/share/qbs/modules/Android/sdk/utils.js index 9511ae9de..264ad2da7 100644 --- a/share/qbs/modules/Android/sdk/utils.js +++ b/share/qbs/modules/Android/sdk/utils.js @@ -174,7 +174,8 @@ function prepareAapt2CompileResource(project, product, inputs, outputs, input, o throw "Cannot create directory '" + FileInfo.toNativeSeparators(compilesResourcesDir) + "'."; } - var args = ["compile", input.filePath, "-o", compilesResourcesDir]; + var args = ["compile", FileInfo.toNativeSeparators(input.filePath), + "-o", FileInfo.toNativeSeparators(compilesResourcesDir)]; var cmd = new Command(product.Android.sdk.aaptFilePath, args); var outputFileName = generateAapt2ResourceFileName(input.filePath); cmd.description = "compiling resource " + input.fileName + " into " + outputFileName; diff --git a/share/qbs/modules/codesign/CodeSignModule.qbs b/share/qbs/modules/codesign/CodeSignModule.qbs index 1951ec374..2115baebf 100644 --- a/share/qbs/modules/codesign/CodeSignModule.qbs +++ b/share/qbs/modules/codesign/CodeSignModule.qbs @@ -43,5 +43,11 @@ Module { property string codesignPath: codesignName property stringList codesignFlags + property string signingTimestamp + PropertyOptions { + name: "signingTimestamp" + description: "URL of the RFC 3161 time stamp server." + } + property bool _canSignArtifacts: false // whether can sign individual actifacts } diff --git a/share/qbs/modules/codesign/apple.qbs b/share/qbs/modules/codesign/apple.qbs index 06f07d72d..565d29080 100644 --- a/share/qbs/modules/codesign/apple.qbs +++ b/share/qbs/modules/codesign/apple.qbs @@ -96,7 +96,7 @@ CodeSignModule { } } - property string signingTimestamp: "none" + signingTimestamp: "none" property string provisioningProfile PropertyOptions { @@ -125,7 +125,7 @@ CodeSignModule { var identities = CodeSign.findSigningIdentities(signingIdentity, teamIdentifier); if (identities && Object.keys(identities).length > 1) { throw "Multiple codesigning identities (i.e. certificate and private key pairs) " + - "matching “" + signingIdentity + "” were found." + + "matching '" + signingIdentity + "' were found." + CodeSign.humanReadableIdentitySummary(identities); } @@ -240,17 +240,17 @@ CodeSignModule { } }); } else if (uuid) { - throw "Your build settings specify a provisioning profile with the UUID “" - + uuid + "”, however, no such provisioning profile was found."; + throw "Your build settings specify a provisioning profile with the UUID '" + + uuid + "', however, no such provisioning profile was found."; } else if (product._provisioningProfileRequired) { var hasProfiles = !!((inputs["codesign.provisioningprofile"] || []).length); var teamIdentifier = product.teamIdentifier; var codeSignIdentity = product.signingIdentity; if (hasProfiles) { if (codeSignIdentity) { - console.warn("No provisioning profiles matching the bundle identifier “" + console.warn("No provisioning profiles matching the bundle identifier '" + product.bundle.identifier - + "” were found."); + + "' were found."); } else { console.warn("No provisioning profiles matching an applicable signing " + "identity were found."); @@ -260,13 +260,13 @@ CodeSignModule { if (teamIdentifier) { console.warn("No provisioning profiles with a valid signing identity " + "(i.e. certificate and private key pair) matching the " - + "team ID “" + teamIdentifier + "” were found.") + + "team ID '" + teamIdentifier + "' were found.") } else { console.warn("No provisioning profiles with a valid signing identity " + "(i.e. certificate and private key pair) were found."); } } else { - console.warn("No non–expired provisioning profiles were found."); + console.warn("No non-expired provisioning profiles were found."); } } } diff --git a/share/qbs/modules/codesign/codesign.js b/share/qbs/modules/codesign/codesign.js index bf7e95224..5aa303c9c 100644 --- a/share/qbs/modules/codesign/codesign.js +++ b/share/qbs/modules/codesign/codesign.js @@ -202,6 +202,75 @@ function findBestProvisioningProfile(product, files) { } } +/** + * Finds out the search paths for the `signtool.exe` utility supplied with + * the Windows SDK's. + */ +function findBestSignToolSearchPaths(arch) { + var searchPaths = []; + var keys = [ + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows", + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft SDKs\\Windows" + ]; + for (var keyIndex = 0; keyIndex < keys.length; ++keyIndex) { + var re = /^v([0-9]+)\.([0-9]+)$/; + var groups = Utilities.nativeSettingGroups(keys[keyIndex]).filter(function(version) { + return version.match(re); + }); + + groups.sort(function(a, b) { + return Utilities.versionCompare(b.substring(1), a.substring(1)); + }); + + function addSearchPath(searchPath) { + if (File.exists(searchPath) && !searchPaths.contains(searchPath)) { + searchPaths.push(searchPath); + return true; + } + return false; + } + + for (var groupIndex = 0; groupIndex < groups.length; ++groupIndex) { + var fullKey = keys[keyIndex] + "\\" + groups[groupIndex]; + var fullVersion = Utilities.getNativeSetting(fullKey, "ProductVersion"); + if (fullVersion) { + var installRoot = FileInfo.cleanPath( + Utilities.getNativeSetting(fullKey, "InstallationFolder")); + if (installRoot) { + // Try to add the architecture-independent path at first. + var searchPath = FileInfo.joinPaths(installRoot, "App Certification Kit"); + if (!addSearchPath(searchPath)) { + // Try to add the architecture-dependent paths at second. + var binSearchPath = FileInfo.joinPaths(installRoot, "bin/" + fullVersion); + if (!File.exists(binSearchPath)) { + binSearchPath += ".0"; + if (!File.exists(binSearchPath)) + continue; + } + + function kitsArchitectureSubDirectory(arch) { + if (arch === "x86") + return "x86"; + else if (arch === "x86_64") + return "x64"; + else if (arch.startsWith("arm64")) + return "arm64"; + else if (arch.startsWith("arm")) + return "arm"; + } + + var archDir = kitsArchitectureSubDirectory(arch); + searchPath = FileInfo.joinPaths(binSearchPath, archDir); + addSearchPath(searchPath); + } + } + } + } + } + + return searchPaths; +} + function prepareSign(project, product, inputs, outputs, input, output) { var cmd, cmds = []; @@ -243,10 +312,10 @@ function prepareSign(project, product, inputs, outputs, input, output) { args.push("--force"); args.push("--sign", actualSigningIdentity.SHA1); - // If signingTimestamp is undefined, do not specify the flag at all - + // If signingTimestamp is undefined or empty, do not specify the flag at all - // this uses the system-specific default behavior var signingTimestamp = product.codesign.signingTimestamp; - if (signingTimestamp !== undefined) { + if (signingTimestamp) { // If signingTimestamp is an empty string, specify the flag but do // not specify a value - this uses a default Apple-provided server var flag = "--timestamp"; @@ -349,3 +418,49 @@ function createDebugKeyStoreCommandString(keytoolFilePath, keystoreFilePath, key "CN=Android Debug,O=Android,C=US"]; return Process.shellQuote(keytoolFilePath, args); } + +function prepareSigntool(project, product, inputs, outputs, input, output) { + var cmd, cmds = []; + + if (!product.codesign.enableCodeSigning) + return cmds; + + var args = ["sign"].concat(product.codesign.codesignFlags || []); + + var subjectName = product.codesign.subjectName; + if (subjectName) + args.push("/n", subjectName); + + var rootSubjectName = product.codesign.rootSubjectName; + if (rootSubjectName) + args.push("/r", rootSubjectName); + + var hashAlgorithm = product.codesign.hashAlgorithm; + if (hashAlgorithm) + args.push("/fd", hashAlgorithm); + + var signingTimestamp = product.codesign.signingTimestamp; + if (signingTimestamp) + args.push("/tr", signingTimestamp); + + var certificatePath = product.codesign.certificatePath; + if (certificatePath) + args.push("/f", certificatePath); + + var certificatePassword = product.codesign.certificatePassword; + if (certificatePassword) + args.push("/p", certificatePassword); + + var crossCertificatePath = product.codesign.crossCertificatePath; + if (crossCertificatePath) + args.push("/ac", crossCertificatePath); + + var outputArtifact = outputs["codesign.signed_artifact"][0]; + args.push(outputArtifact.filePath); + + cmd = new Command(product.codesign.codesignPath, args); + cmd.description = "signing " + outputArtifact.fileName; + cmd.highlight = "linker"; + cmds.push(cmd); + return cmds; +} diff --git a/share/qbs/modules/codesign/signtool.qbs b/share/qbs/modules/codesign/signtool.qbs new file mode 100644 index 000000000..13933c6f6 --- /dev/null +++ b/share/qbs/modules/codesign/signtool.qbs @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com> +** Contact: http://www.qt.io/licensing +** +** 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. +** +****************************************************************************/ + +import qbs +import qbs.File +import qbs.ModUtils +import qbs.Probes +import "codesign.js" as CODESIGN + +CodeSignModule { + condition: qbs.targetOS.contains("windows") && qbs.hostOS.contains("windows") + + _canSignArtifacts: true + + Probes.BinaryProbe { + id: signtoolProbe + names: [codesignName] + searchPaths: CODESIGN.findBestSignToolSearchPaths(qbs.hostArchitecture) + } + + codesignName: "signtool" + codesignPath: signtoolProbe.filePath + + property string subjectName + PropertyOptions { + name: "subjectName" + description: "Name of the subject of the signing certificate." + } + + property string rootSubjectName + PropertyOptions { + name: "rootSubjectName" + description: "Name of the subject of the root certificate that the signing " + + "certificate must chain to." + } + + property string hashAlgorithm + PropertyOptions { + name: "hashAlgorithm" + description: "Name of the hash algorithm used on the signing certificate." + allowedValues: ["sha1", "sha256", "sha384", "sha512"] + } + + property path certificatePath + PropertyOptions { + name: "certificatePath" + description: "Path to the signing certificate PFX file." + } + + property path certificatePassword + PropertyOptions { + name: "certificatePassword" + description: "Password to use when opening a certificate PFX file." + } + + property path crossCertificatePath + PropertyOptions { + name: "crossCertificatePath" + description: "Path to the additional certificate CER file." + } + + validate: { + if (enableCodeSigning && !File.exists(codesignPath)) { + throw ModUtils.ModuleError("Could not find 'signtool' utility"); + } + } +} diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs index 761e8be85..39077bec8 100644 --- a/share/qbs/modules/cpp/CppModule.qbs +++ b/share/qbs/modules/cpp/CppModule.qbs @@ -188,6 +188,8 @@ Module { property string dynamicLibraryImportSuffix: ".lib" property string objectSuffix: ".o" property string linkerMapSuffix: ".map" + property string compilerListingSuffix: ".lst" + property string assemblerListingSuffix: ".lst" property bool createSymlinks: true property stringList dynamicLibraries // list of names, will be linked with -lname property stringList staticLibraries // list of static library files diff --git a/share/qbs/modules/cpp/iar.js b/share/qbs/modules/cpp/iar.js index a1f1a9a88..416de7ee2 100644 --- a/share/qbs/modules/cpp/iar.js +++ b/share/qbs/modules/cpp/iar.js @@ -612,18 +612,24 @@ function collectLibraryDependencies(product) { return result; } -function compilerOutputArtifacts(input, useListing) { +function compilerOutputArtifacts(input, isCompilerArtifacts) { var artifacts = []; artifacts.push({ fileTags: ["obj"], filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + input.cpp.objectSuffix }); - if (useListing) { + if (isCompilerArtifacts && input.cpp.generateCompilerListingFiles) { artifacts.push({ fileTags: ["lst"], filePath: Utilities.getHash(input.baseDir) + "/" - + input.fileName + ".lst" + + input.fileName + input.cpp.compilerListingSuffix + }); + } else if (!isCompilerArtifacts && input.cpp.generateAssemblerListingFiles) { + artifacts.push({ + fileTags: ["lst"], + filePath: Utilities.getHash(input.baseDir) + "/" + + input.fileName + input.cpp.assemblerListingSuffix }); } return artifacts; diff --git a/share/qbs/modules/cpp/iar.qbs b/share/qbs/modules/cpp/iar.qbs index 6c00f8f36..9709695c1 100644 --- a/share/qbs/modules/cpp/iar.qbs +++ b/share/qbs/modules/cpp/iar.qbs @@ -99,8 +99,7 @@ CppModule { id: assembler inputs: ["asm"] outputFileTags: ["obj", "lst"] - outputArtifacts: IAR.compilerOutputArtifacts( - input, input.cpp.generateAssemblerListingFiles) + outputArtifacts: IAR.compilerOutputArtifacts(input, false) prepare: IAR.prepareAssembler.apply(IAR, arguments) } @@ -114,8 +113,7 @@ CppModule { inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] outputFileTags: ["obj", "lst"] - outputArtifacts: IAR.compilerOutputArtifacts( - input, input.cpp.generateCompilerListingFiles) + outputArtifacts: IAR.compilerOutputArtifacts(input, true) prepare: IAR.prepareCompiler.apply(IAR, arguments) } diff --git a/share/qbs/modules/cpp/keil.js b/share/qbs/modules/cpp/keil.js index 567b0ddd3..27e4e12d7 100644 --- a/share/qbs/modules/cpp/keil.js +++ b/share/qbs/modules/cpp/keil.js @@ -582,19 +582,24 @@ function filterC166Output(output) { return filteredLines.join('\n'); }; -function compilerOutputArtifacts(input, useListing) { +function compilerOutputArtifacts(input, isCompilerArtifacts) { var artifacts = []; artifacts.push({ fileTags: ["obj"], filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + input.cpp.objectSuffix }); - if (useListing) { + if (isCompilerArtifacts && input.cpp.generateCompilerListingFiles) { artifacts.push({ fileTags: ["lst"], filePath: Utilities.getHash(input.baseDir) + "/" - + (isArmCCCompiler(input.cpp.compilerPath) ? input.baseName : input.fileName) - + ".lst" + + input.fileName + input.cpp.compilerListingSuffix + }); + } else if (!isCompilerArtifacts && input.cpp.generateAssemblerListingFiles) { + artifacts.push({ + fileTags: ["lst"], + filePath: Utilities.getHash(input.baseDir) + "/" + + input.fileName + input.cpp.assemblerListingSuffix }); } return artifacts; @@ -970,24 +975,37 @@ function disassemblerFlags(project, product, input, outputs, explicitlyDependsOn function linkerFlags(project, product, inputs, outputs) { var args = []; + // Library paths. + var libraryPaths = product.cpp.libraryPaths; + var architecture = product.qbs.architecture; if (isMcsArchitecture(architecture) || isC166Architecture(architecture)) { - // Note: The C51/256/166 linker does not distinguish an object files and + // Note: The C51, C251, or C166 linker does not distinguish an object files and // a libraries, it interpret all this stuff as an input objects, // so, we need to pass it together in one string. - var allObjectPaths = []; - function addObjectPath(obj) { - allObjectPaths.push(obj.filePath); - } // Inputs. if (inputs.obj) - inputs.obj.map(function(obj) { addObjectPath(obj) }); + inputs.obj.map(function(obj) { allObjectPaths.push(obj.filePath) }); // Library dependencies. var libraryObjects = collectLibraryDependencies(product); - libraryObjects.forEach(function(dep) { addObjectPath(dep); }) + allObjectPaths = allObjectPaths.concat(libraryObjects.map(function(lib) { + // Semi-intelligent handling the library paths. + // We need to add the full path prefix to the library file if this + // file is not absolute or not relative. Reason is that the C51, C251, + // and C166 linkers does not support the library paths. + var filePath = lib.filePath; + if (FileInfo.isAbsolutePath(filePath)) + return filePath; + for (var i = 0; i < libraryPaths.length; ++i) { + var fullPath = FileInfo.joinPaths(libraryPaths[i], filePath); + if (File.exists(fullPath)) + return fullPath; + } + return filePath; + })); // Add all input objects as arguments (application and library object files). if (allObjectPaths.length > 0) @@ -1009,8 +1027,6 @@ function linkerFlags(project, product, inputs, outputs) { // Output. args.push("--output", outputs.application[0].filePath); - // Library paths. - var libraryPaths = product.cpp.libraryPaths; if (libraryPaths) args.push("--userlibpath=" + libraryPaths.join(",")); @@ -1084,6 +1100,38 @@ function archiverFlags(project, product, inputs, outputs) { return args; } +// The ARMCLANG compiler does not support generation +// for the listing files: +// * https://www.keil.com/support/docs/4152.htm +// So, we generate the listing files from the object files +// using the disassembler. +function generateClangCompilerListing(project, product, inputs, outputs, input, output) { + if (isArmClangCompiler(input.cpp.compilerPath) && input.cpp.generateCompilerListingFiles) { + var args = disassemblerFlags(project, product, input, outputs, explicitlyDependsOn); + var disassemblerPath = input.cpp.disassemblerPath; + var cmd = new Command(disassemblerPath, args); + cmd.silent = true; + return cmd; + } +} + +// The ARMCC compiler generates the listing files only in a short form, +// e.g. to 'module.lst' instead of 'module.{c|cpp}.lst', that complicates +// the auto-tests. Therefore we need to rename generated listing files +// with correct unified names. +function generateArmccCompilerListing(project, product, inputs, outputs, input, output) { + if (isArmCCCompiler(input.cpp.compilerPath) && input.cpp.generateCompilerListingFiles) { + var listingPath = FileInfo.path(outputs.lst[0].filePath); + var cmd = new JavaScriptCommand(); + cmd.oldListing = FileInfo.joinPaths(listingPath, input.baseName + ".lst"); + cmd.newListing = FileInfo.joinPaths( + listingPath, input.fileName + input.cpp.compilerListingSuffix); + cmd.silent = true; + cmd.sourceCode = function() { File.move(oldListing, newListing); }; + return cmd; + } +} + function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); @@ -1101,18 +1149,14 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli } cmds.push(cmd); - // The ARMCLANG compiler does not support generation - // for the listing files: - // * https://www.keil.com/support/docs/4152.htm - // So, we generate the listing files from the object files - // using the disassembler. - if (isArmClangCompiler(compilerPath) && input.cpp.generateCompilerListingFiles) { - args = disassemblerFlags(project, product, input, outputs, explicitlyDependsOn); - var disassemblerPath = input.cpp.disassemblerPath; - cmd = new Command(disassemblerPath, args); - cmd.silent = true; + cmd = generateClangCompilerListing(project, product, inputs, outputs, input, output); + if (cmd) cmds.push(cmd); - } + + cmd = generateArmccCompilerListing(project, product, inputs, outputs, input, output); + if (cmd) + cmds.push(cmd); + return cmds; } diff --git a/share/qbs/modules/cpp/keil.qbs b/share/qbs/modules/cpp/keil.qbs index f1f3b50e8..ea99b589c 100644 --- a/share/qbs/modules/cpp/keil.qbs +++ b/share/qbs/modules/cpp/keil.qbs @@ -103,8 +103,7 @@ CppModule { id: assembler inputs: ["asm"] outputFileTags: ["obj", "lst"] - outputArtifacts: KEIL.compilerOutputArtifacts( - input, input.cpp.generateAssemblerListingFiles) + outputArtifacts: KEIL.compilerOutputArtifacts(input, false) prepare: KEIL.prepareAssembler.apply(KEIL, arguments) } @@ -118,8 +117,7 @@ CppModule { inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] outputFileTags: ["obj", "lst"] - outputArtifacts: KEIL.compilerOutputArtifacts( - input, input.cpp.generateCompilerListingFiles) + outputArtifacts: KEIL.compilerOutputArtifacts(input, true) prepare: KEIL.prepareCompiler.apply(KEIL, arguments) } diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js index 566059610..9f3d20282 100644 --- a/share/qbs/modules/cpp/msvc.js +++ b/share/qbs/modules/cpp/msvc.js @@ -28,6 +28,7 @@ ** ****************************************************************************/ +var Codesign = require("../codesign/codesign.js"); var Cpp = require("cpp.js"); var File = require("qbs.File"); var FileInfo = require("qbs.FileInfo"); @@ -655,6 +656,12 @@ function prepareLinker(project, product, inputs, outputs, input, output) { commands.push(cmd); } + if (product.cpp.shouldSignArtifacts) { + Array.prototype.push.apply( + commands, Codesign.prepareSigntool( + project, product, inputs, outputs, input, output)); + } + return commands; } diff --git a/share/qbs/modules/cpp/sdcc.js b/share/qbs/modules/cpp/sdcc.js index a47063401..1904f59fc 100644 --- a/share/qbs/modules/cpp/sdcc.js +++ b/share/qbs/modules/cpp/sdcc.js @@ -239,7 +239,7 @@ function collectLibraryDependencies(product) { return result; } -function compilerOutputArtifacts(input, useListing) { +function compilerOutputArtifacts(input, isCompilerArtifacts) { var obj = { fileTags: ["obj"], filePath: Utilities.getHash(input.baseDir) + "/" @@ -270,11 +270,17 @@ function compilerOutputArtifacts(input, useListing) { + input.fileName + ".rst" }; var artifacts = [obj, asm_adb, asm_src, asm_sym, rst_data]; - if (useListing) { + if (isCompilerArtifacts && input.cpp.generateCompilerListingFiles) { artifacts.push({ fileTags: ["lst"], filePath: Utilities.getHash(input.baseDir) + "/" - + input.fileName + ".lst" + + input.fileName + input.cpp.compilerListingSuffix + }); + } else if (!isCompilerArtifacts && input.cpp.generateAssemblerListingFiles) { + artifacts.push({ + fileTags: ["lst"], + filePath: Utilities.getHash(input.baseDir) + "/" + + input.fileName + input.cpp.assemblerListingSuffix }); } return artifacts; @@ -547,14 +553,19 @@ function archiverFlags(project, product, inputs, outputs) { return args; } +function buildLinkerMapFilePath(target, suffix) { + return FileInfo.joinPaths(FileInfo.path(target.filePath), + FileInfo.completeBaseName(target.fileName) + suffix); +} + // This is the workaround for the SDCC bug on a Windows host: // * https://sourceforge.net/p/sdcc/bugs/2970/ // We need to replace the '\r\n\' line endings with the'\n' line // endings for each generated object file. -function patchObjectFiles(project, product, inputs, outputs, input, output) { +function patchObjectFile(project, product, inputs, outputs, input, output) { var isWindows = input.qbs.hostOS.contains("windows"); if (isWindows && input.cpp.debugInformation) { - cmd = new JavaScriptCommand(); + var cmd = new JavaScriptCommand(); cmd.objectPath = outputs.obj[0].filePath; cmd.silent = true; cmd.sourceCode = function() { @@ -576,6 +587,85 @@ function patchObjectFiles(project, product, inputs, outputs, input, output) { } } +// It is a workaround which removes the generated linker map file +// if it is disabled by cpp.generateLinkerMapFile property. +// Reason is that the SDCC compiler always generates this file, +// and does not have an option to disable generation for a linker +// map file. So, we can to remove a listing files only after the +// linking completes. +function removeLinkerMapFile(project, product, inputs, outputs, input, output) { + if (!product.cpp.generateLinkerMapFile) { + var target = outputs.application[0]; + var cmd = new JavaScriptCommand(); + cmd.mapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix) + cmd.silent = true; + cmd.sourceCode = function() { File.remove(mapFilePath); }; + return cmd; + } +} + +// It is a workaround to rename the extension of the output linker +// map file to the specified one, since the linker generates only +// files with the '.map' extension. +function renameLinkerMapFile(project, product, inputs, outputs, input, output) { + if (product.cpp.generateLinkerMapFile && (product.cpp.linkerMapSuffix !== ".map")) { + var target = outputs.application[0]; + var cmd = new JavaScriptCommand(); + cmd.newMapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix); + cmd.oldMapFilePath = buildLinkerMapFilePath(target, ".map"); + cmd.silent = true; + cmd.sourceCode = function() { File.move(oldMapFilePath, newMapFilePath); }; + return cmd; + } +} + +// It is a workaround which removes the generated listing files +// if it is disabled by cpp.generateCompilerListingFiles property +// or when the cpp.compilerListingSuffix differs with '.lst'. +// Reason is that the SDCC compiler does not have an option to +// disable generation for a listing files. Besides, the SDCC +// compiler use this files and for the linking. So, we can to +// remove a listing files only after the linking completes. +function removeCompilerListingFiles(project, product, inputs, outputs, input, output) { + var cmd = new JavaScriptCommand(); + cmd.objects = inputs.obj.map(function(a) { return a; }); + cmd.silent = true; + cmd.sourceCode = function() { + objects.forEach(function(object) { + if (!object.filePath.endsWith(".c" + object.cpp.objectSuffix)) + return; // Skip the assembler generated objects. + if (!object.cpp.generateCompilerListingFiles + || (object.cpp.compilerListingSuffix !== ".lst")) { + var listingPath = FileInfo.joinPaths(FileInfo.path(object.filePath), + object.completeBaseName + ".lst"); + File.remove(listingPath); + } + }) + }; + return cmd; +} + +// It is a workaround that duplicates the generated listing files +// but with desired names. The problem is that the SDCC compiler does +// not support an options to specify names for the generated listing +// files. At the same time, the compiler always generates the listing +// files in the form of 'module.c.lst', which makes it impossible to +// change the file suffix to a user-specified one. In addition, these +// files are also somehow used for linking. Thus, we can not rename them +// on the compiling stage. +function duplicateCompilerListingFile(project, product, inputs, outputs, input, output) { + if (input.cpp.generateCompilerListingFiles + && (input.cpp.compilerListingSuffix !== ".lst")) { + var cmd = new JavaScriptCommand(); + cmd.newListing = outputs.lst[0].filePath; + cmd.oldListing = FileInfo.joinPaths(FileInfo.path(outputs.lst[0].filePath), + outputs.lst[0].completeBaseName + ".lst"); + cmd.silent = true; + cmd.sourceCode = function() { File.copy(oldListing, newListing); }; + return cmd; + } +} + function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var cmds = []; var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn); @@ -585,7 +675,11 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli cmd.highlight = "compiler"; cmds.push(cmd); - cmd = patchObjectFiles(project, product, inputs, outputs, input, output); + cmd = patchObjectFile(project, product, inputs, outputs, input, output); + if (cmd) + cmds.push(cmd); + + cmd = duplicateCompilerListingFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); @@ -601,7 +695,7 @@ function prepareAssembler(project, product, inputs, outputs, input, output, expl cmd.highlight = "compiler"; cmds.push(cmd); - cmd = patchObjectFiles(project, product, inputs, outputs, input, output); + cmd = patchObjectFile(project, product, inputs, outputs, input, output); if (cmd) cmds.push(cmd); @@ -610,52 +704,24 @@ function prepareAssembler(project, product, inputs, outputs, input, output, expl function prepareLinker(project, product, inputs, outputs, input, output) { var cmds = []; - var target = outputs.application[0]; var args = linkerFlags(project, product, inputs, outputs); var linkerPath = effectiveLinkerPath(product); var cmd = new Command(linkerPath, args); - cmd.description = "linking " + target.fileName; + cmd.description = "linking " + outputs.application[0].fileName; cmd.highlight = "linker"; cmds.push(cmd); - // It is a workaround which removes the generated listing files - // if it is disabled by cpp.generateCompilerListingFiles property. - // Reason is that the SDCC compiler does not have an option to - // disable generation for a listing files. Besides, the SDCC - // compiler use this files and for the linking. So, we can to - // remove a listing files only after the linking completes. - if (!product.cpp.generateCompilerListingFiles) { - cmd = new JavaScriptCommand(); - cmd.objectPaths = inputs.obj.map(function(a) { return a.filePath; }); - cmd.objectSuffix = product.cpp.objectSuffix; - cmd.silent = true; - cmd.sourceCode = function() { - objectPaths.forEach(function(objectPath) { - if (!objectPath.endsWith(".c" + objectSuffix)) - return; // Skip the assembler objects. - var listingPath = FileInfo.joinPaths( - FileInfo.path(objectPath), - FileInfo.completeBaseName(objectPath) + ".lst"); - File.remove(listingPath); - }); - }; + cmd = removeCompilerListingFiles(project, product, inputs, outputs, input, output); + if (cmd) cmds.push(cmd); - } - // It is a workaround which removes the generated linker map file - // if it is disabled by cpp.generateLinkerMapFile property. - // Reason is that the SDCC compiler always generates this file, - // and does not have an option to disable generation for a linker - // map file. So, we can to remove a listing files only after the - // linking completes. - if (!product.cpp.generateLinkerMapFile) { - cmd = new JavaScriptCommand(); - cmd.mapFilePath = FileInfo.joinPaths( - FileInfo.path(target.filePath), - FileInfo.completeBaseName(target.fileName) + product.cpp.linkerMapSuffix); - cmd.silent = true; - cmd.sourceCode = function() { File.remove(mapFilePath); }; + + cmd = renameLinkerMapFile(project, product, inputs, outputs, input, output); + if (cmd) + cmds.push(cmd); + + cmd = removeLinkerMapFile(project, product, inputs, outputs, input, output); + if (cmd) cmds.push(cmd); - } return cmds; } diff --git a/share/qbs/modules/cpp/sdcc.qbs b/share/qbs/modules/cpp/sdcc.qbs index 8b631d4e5..c5a0893d4 100644 --- a/share/qbs/modules/cpp/sdcc.qbs +++ b/share/qbs/modules/cpp/sdcc.qbs @@ -100,7 +100,7 @@ CppModule { id: assembler inputs: ["asm"] outputFileTags: ["obj", "asm_adb", "lst", "asm_src", "asm_sym", "rst_data"] - outputArtifacts: SDCC.compilerOutputArtifacts(input, true) + outputArtifacts: SDCC.compilerOutputArtifacts(input, false) prepare: SDCC.prepareAssembler.apply(SDCC, arguments) } @@ -114,8 +114,7 @@ CppModule { inputs: ["cpp", "c"] auxiliaryInputs: ["hpp"] outputFileTags: ["obj", "asm_adb", "lst", "asm_src", "asm_sym", "rst_data"] - outputArtifacts: SDCC.compilerOutputArtifacts( - input, input.cpp.generateCompilerListingFiles) + outputArtifacts: SDCC.compilerOutputArtifacts(input, true) prepare: SDCC.prepareCompiler.apply(SDCC, arguments) } diff --git a/share/qbs/modules/cpp/windows-clang-cl.qbs b/share/qbs/modules/cpp/windows-clang-cl.qbs index a34a67ad2..556efb042 100644 --- a/share/qbs/modules/cpp/windows-clang-cl.qbs +++ b/share/qbs/modules/cpp/windows-clang-cl.qbs @@ -53,6 +53,7 @@ MsvcBaseModule { vcvarsallFilePath: vcvarsallPath enableDefinesByLanguage: enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture + winSdkVersion: windowsSdkVersion } qbs.architecture: clangClProbe.found ? clangClProbe.architecture : original diff --git a/share/qbs/modules/cpp/windows-msvc-base.qbs b/share/qbs/modules/cpp/windows-msvc-base.qbs index b25fdf159..c45ec5ec3 100644 --- a/share/qbs/modules/cpp/windows-msvc-base.qbs +++ b/share/qbs/modules/cpp/windows-msvc-base.qbs @@ -40,6 +40,8 @@ import 'msvc.js' as MSVC CppModule { condition: false + Depends { name: "codesign" } + windowsApiCharacterSet: "unicode" platformDefines: { var defines = base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) @@ -100,6 +102,8 @@ CppModule { property var buildEnv + readonly property bool shouldSignArtifacts: codesign.enableCodeSigning + setupBuildEnvironment: { for (var key in product.cpp.buildEnv) { var v = new ModUtils.EnvironmentVariable(key, ';'); @@ -108,6 +112,8 @@ CppModule { } } + property string windowsSdkVersion + Rule { condition: useCPrecompiledHeader inputs: ["c_pch_src"] @@ -162,7 +168,8 @@ CppModule { if (input.cpp.generateCompilerListingFiles) { artifacts.push({ fileTags: ["lst"], - filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".lst" + filePath: Utilities.getHash(input.baseDir) + + "/" + input.fileName + input.cpp.compilerListingSuffix }); } return artifacts; @@ -189,10 +196,16 @@ CppModule { inputs: ['obj', 'native.pe.manifest', 'def'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"] - outputFileTags: ["application", "debuginfo_app", "mem_map"] + outputFileTags: { + var tags = ["application", "debuginfo_app", "mem_map"]; + if (shouldSignArtifacts) + tags.push("codesign.signed_artifact"); + return tags; + } outputArtifacts: { var app = { - fileTags: ["application"], + fileTags: ["application"].concat( + product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), filePath: FileInfo.joinPaths( product.destinationDirectory, PathTools.applicationFilePath(product)) @@ -227,11 +240,17 @@ CppModule { inputs: ['obj', 'native.pe.manifest', 'def'] inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"] - outputFileTags: ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"] + outputFileTags: { + var tags = ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"]; + if (shouldSignArtifacts) + tags.push("codesign.signed_artifact"); + return tags; + } outputArtifacts: { var artifacts = [ { - fileTags: ["dynamiclibrary"], + fileTags: ["dynamiclibrary"].concat( + product.cpp.shouldSignArtifacts ? ["codesign.signed_artifact"] : []), filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product) }, { diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs index d5b5baf92..33c5e74c8 100644 --- a/share/qbs/modules/cpp/windows-msvc.qbs +++ b/share/qbs/modules/cpp/windows-msvc.qbs @@ -51,6 +51,7 @@ MsvcBaseModule { compilerFilePath: compilerPath enableDefinesByLanguage: enableCompilerDefinesByLanguage preferredArchitecture: qbs.architecture + winSdkVersion: windowsSdkVersion } qbs.architecture: msvcProbe.found ? msvcProbe.architecture : original |