diff options
Diffstat (limited to 'share/qbs/modules')
31 files changed, 993 insertions, 295 deletions
diff --git a/share/qbs/modules/Android/sdk/sdk.qbs b/share/qbs/modules/Android/sdk/sdk.qbs index d663a01e4..440448dcf 100644 --- a/share/qbs/modules/Android/sdk/sdk.qbs +++ b/share/qbs/modules/Android/sdk/sdk.qbs @@ -52,7 +52,7 @@ Module { Probes.PathProbe { id: bundletoolProbe - platformSearchPaths: [Android.sdk.sdkDir] + platformSearchPaths: [sdkDir] names: ["bundletool-all"] nameSuffixes: ["-0.11.0.jar", "-0.12.0.jar", "-0.13.0.jar", "-0.13.3.jar", "-0.13.4.jar", "-0.14.0.jar", "-0.15.0.jar", "-1.0.0.jar", "-1.1.0.jar", "-1.2.0.jar", "-1.3.0.jar", @@ -102,36 +102,36 @@ Module { Group { name: "java sources" - condition: Android.sdk.automaticSources - prefix: FileInfo.resolvePath(product.sourceDirectory, Android.sdk.sourcesDir + '/') + condition: product.Android.sdk.automaticSources + prefix: FileInfo.resolvePath(product.sourceDirectory, product.Android.sdk.sourcesDir + '/') files: "**/*.java" } Group { name: "android resources" - condition: Android.sdk.automaticSources + condition: product.Android.sdk.automaticSources fileTags: ["android.resources"] - prefix: FileInfo.resolvePath(product.sourceDirectory, Android.sdk.resourcesDir + '/') + prefix: FileInfo.resolvePath(product.sourceDirectory, product.Android.sdk.resourcesDir + '/') files: "**/*" } Group { name: "android assets" - condition: Android.sdk.automaticSources + condition: product.Android.sdk.automaticSources fileTags: ["android.assets"] - prefix: FileInfo.resolvePath(product.sourceDirectory, Android.sdk.assetsDir + '/') + prefix: FileInfo.resolvePath(product.sourceDirectory, product.Android.sdk.assetsDir + '/') files: "**/*" } Group { name: "manifest" - condition: Android.sdk.automaticSources + condition: product.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] : []) + files: product.Android.sdk.manifestFile + && product.Android.sdk.manifestFile !== product.Android.sdk.defaultManifestFile + ? [product.Android.sdk.manifestFile] + : (File.exists(product.Android.sdk.defaultManifestFile) + ? [product.Android.sdk.defaultManifestFile] : []) } @@ -196,8 +196,8 @@ Module { java.languageVersion: platformJavaVersion java.runtimeVersion: platformJavaVersion java.bootClassPaths: androidJarFilePath - codesign.apksignerFilePath: Android.sdk.apksignerFilePath - codesign._packageName: Android.sdk.apkBaseName + (_generateAab ? ".aab" : ".apk") + codesign.apksignerFilePath: apksignerFilePath + codesign._packageName: apkBaseName + (_generateAab ? ".aab" : ".apk") codesign.useApksigner: !_generateAab } @@ -263,7 +263,7 @@ Module { property bool customManifestProcessing: false Group { - condition: !Android.sdk.customManifestProcessing + condition: !product.Android.sdk.customManifestProcessing fileTagsFilter: "android.manifest_processed" fileTags: "android.manifest_final" } diff --git a/share/qbs/modules/Exporter/cmake/cmakeexporter.js b/share/qbs/modules/Exporter/cmake/cmakeexporter.js new file mode 100644 index 000000000..093032f2e --- /dev/null +++ b/share/qbs/modules/Exporter/cmake/cmakeexporter.js @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Raphaël Cotty <raphael.cotty@gmail.com> +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: http://www.qt.io/licensing +** +** This file is part of the 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 FileInfo = require("qbs.FileInfo"); +var ModUtils = require("qbs.ModUtils"); +var ExporterHelpers = require("../exporter.js"); + +function tagListToString(tagList) +{ + return JSON.stringify(tagList); +} + +function collectAutodetectedData(project, topLevelProduct, outputs) +{ + var packageName = topLevelProduct.Exporter.cmake.packageName; + + var data = {}; + data.packageName = packageName; + data.installPrefixDir = "_" + packageName.toUpperCase() + "_INSTALL_PREFIX"; + data.packages = []; + + function quote(value) + { + return "\"" + value + "\""; + } + + function quoteAndPrefixify(propName) + { + function quoteAndPrefixifyHelper(value) { + var prefixToStrip = + ExporterHelpers.getPrefixToStrip(project, topLevelProduct, propName, value); + if (typeof value !== "string" + || !prefixToStrip + || (value.length > prefixToStrip.length + && value[prefixToStrip.length] !== '/')) { + return quote(value); + } + return quote("${" + data.installPrefixDir + "}" + value.slice(prefixToStrip.length)); + } + return quoteAndPrefixifyHelper; + } + + var installedOutputFilePath = ModUtils.artifactInstalledFilePath( + outputs["Exporter.cmake.configFile"][0]); + var installedOutputPathName = FileInfo.path(installedOutputFilePath); + + var installRootPath = FileInfo.joinPaths(topLevelProduct.qbs.installRoot, topLevelProduct.qbs.installPrefix); + data.installPrefix = FileInfo.relativePath(installedOutputPathName, installRootPath); + + var libArtifacts; + var libImportArtifacts; + var isProduct = !topLevelProduct.present; + var considerFramework = !isProduct || (topLevelProduct.type + && topLevelProduct.type.includes("bundle.content")) + && topLevelProduct.bundle + && topLevelProduct.bundle.isBundle + && topLevelProduct.qbs.targetOS.includes("darwin"); + var considerDynamicLibs = !isProduct || (topLevelProduct.type + && topLevelProduct.type.includes("dynamiclibrary")); + var considerStaticLibs = !isProduct || (topLevelProduct.type + && topLevelProduct.type.includes("staticlibrary")); + if (considerFramework) { + libArtifacts = topLevelProduct.artifacts["bundle.symlink.executable"]; + if (considerDynamicLibs) + data.type = "SHARED"; + else if (considerStaticLibs) + data.type = "STATIC"; + else + data.type = "INTERFACE"; + } else if (considerDynamicLibs) { + libArtifacts = topLevelProduct.artifacts.dynamiclibrary; + libImportArtifacts = topLevelProduct.artifacts.dynamiclibrary_import; + data.type = "SHARED"; + } else if (considerStaticLibs) { + libArtifacts = topLevelProduct.artifacts.staticlibrary; + data.type = "STATIC"; + } else { + data.type = "INTERFACE"; + } + + for (var i = 0; i < (libArtifacts || []).length; ++i) { + var libArtifact = libArtifacts[i]; + var libImportArtifact = (libImportArtifacts || [])[i]; + if (libArtifact.qbs.install) { + var installPath = ModUtils.artifactInstalledFilePath(libArtifact); + data.importedLocation = quoteAndPrefixify("installRoot")(installPath); + data.soName = topLevelProduct.targetName; + if (libImportArtifact && libImportArtifact.qbs.install) { + installPath = ModUtils.artifactInstalledFilePath(libImportArtifact); + data.importedImplibLocation = quoteAndPrefixify("installRoot")(installPath); + } + break; + } + } + var cpp = topLevelProduct.exports.cpp; + if (cpp) { + data.libraryPaths = (cpp.libraryPaths || []).map(quoteAndPrefixify("cpp.libraryPaths")); + + data.linkLibraries = []; + data.linkLibraries = data.linkLibraries.concat(cpp.dynamicLibraries || []); + data.linkLibraries = data.linkLibraries.concat(cpp.staticLibraries || []); + data.linkLibraries = data.linkLibraries.map(quoteAndPrefixify("cpp.dynamicLibraries")); + + data.linkOptions = []; + data.linkOptions = data.linkOptions.concat(cpp.driverLinkerFlags || []); + if ((cpp.linkerFlags || []).length > 0) { + data.linkOptions = + data.linkOptions.concat("LINKER:" + (cpp.linkerFlags || []).join(",")); + } + data.linkOptions = data.linkOptions.map(quote); + + data.includeDirectories = + (cpp.includePaths || []).map(quoteAndPrefixify("cpp.includePaths")); + data.compileDefinitions = (cpp.defines || []).map(quote); + + data.compileOptions = []; + data.compileOptions = data.compileOptions.concat(cpp.commonCompilerFlags || []); + data.compileOptions = data.compileOptions.concat(cpp.driverFlags || []); + data.compileOptions = data.compileOptions.concat(cpp.cxxFlags || []); + data.compileOptions = data.compileOptions.concat(cpp.cFlags || []); + data.compileOptions = data.compileOptions.map(quote); + } + + function gatherDeps(dep) { + if (dep.name === "Exporter.cmake") + return; + var depHasExporter = dep.Exporter && dep.Exporter.cmake; + if (!depHasExporter) + return; + data.packages.push(dep.Exporter.cmake.packageName); + } + + var exportedDeps = topLevelProduct.exports ? topLevelProduct.exports.dependencies : []; + exportedDeps.forEach(gatherDeps); + + return data; +} + +function writeConfigFile(project, product, outputs) +{ + var autoDetectedData = collectAutodetectedData(project, product, outputs); + var packageName = autoDetectedData.packageName; + + function writeCommand(command, lines) + { + if ((lines || []).length === 0) + return; + cmakeConfigFile.writeLine(command + "(" + packageName + " INTERFACE"); + for (i = 0; i < lines.length; i++) { + cmakeConfigFile.writeLine(" " + lines[i]); + } + cmakeConfigFile.writeLine(")"); + } + + var cmakeConfigFile = new TextFile(outputs["Exporter.cmake.configFile"][0].filePath, + TextFile.WriteOnly); + cmakeConfigFile.writeLine("# Generated by Qbs"); + + cmakeConfigFile.writeLine("cmake_minimum_required(VERSION 3.5)"); + + cmakeConfigFile.writeLine("if(TARGET " + packageName + ")"); + cmakeConfigFile.writeLine(" return()"); + cmakeConfigFile.writeLine("endif()"); + + cmakeConfigFile.writeLine("set(" + autoDetectedData.installPrefixDir + + " \"${CMAKE_CURRENT_LIST_DIR}/" + + autoDetectedData.installPrefix + "\")"); + + autoDetectedData.packages.forEach(function(packageName) { + cmakeConfigFile.writeLine("find_package(" + packageName + " REQUIRED SILENT)"); + }); + cmakeConfigFile.writeLine( + "add_library(" + packageName + " " + autoDetectedData.type + " IMPORTED)"); + var configuration = (product.qbs.buildVariant) ? + product.qbs.buildVariant.toUpperCase() : "NONE"; + cmakeConfigFile.writeLine("set_property(TARGET " + packageName + + " APPEND PROPERTY IMPORTED_CONFIGURATIONS " + + configuration + ")"); + + cmakeConfigFile.writeLine("set_target_properties(" + packageName + " PROPERTIES"); + cmakeConfigFile.writeLine(" IMPORTED_LINK_INTERFACE_LANGUAGES_" + configuration + + " CXX"); + if (autoDetectedData.type !== "INTERFACE") { + cmakeConfigFile.writeLine(" IMPORTED_LOCATION_" + configuration + " " + + autoDetectedData.importedLocation); + } + if (autoDetectedData.importedImplibLocation) { + cmakeConfigFile.writeLine(" IMPORTED_IMPLIB_" + configuration + " " + + autoDetectedData.importedImplibLocation); + } + cmakeConfigFile.writeLine(")"); + + writeCommand("target_link_directories", autoDetectedData.libraryPaths); + writeCommand("target_link_libraries", + autoDetectedData.linkLibraries.concat(autoDetectedData.packages)); + writeCommand("target_link_options", autoDetectedData.linkOptions); + writeCommand("target_include_directories", autoDetectedData.includeDirectories); + writeCommand("target_compile_definitions", autoDetectedData.compileDefinitions); + writeCommand("target_compile_options", autoDetectedData.compileOptions); + + cmakeConfigFile.close(); +} + +function writeVersionFile(product, outputs) +{ + var cmakeVersionFile = new TextFile( + outputs["Exporter.cmake.versionFile"][0].filePath, TextFile.WriteOnly); + cmakeVersionFile.writeLine("# Generated by Qbs"); + cmakeVersionFile.writeLine("set(PACKAGE_VERSION \"" + product.version + "\")"); + cmakeVersionFile.close(); +} diff --git a/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs b/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs new file mode 100644 index 000000000..a578e938b --- /dev/null +++ b/share/qbs/modules/Exporter/cmake/cmakeexporter.qbs @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Raphaël Cotty <raphael.cotty@gmail.com> +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qbs. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import qbs.File +import qbs.FileInfo +import qbs.ModUtils +import qbs.TextFile + +import "cmakeexporter.js" as HelperFunctions + +Module { + property string configFileName: packageName + "Config.cmake" + property string versionFileName: packageName + "ConfigVersion.cmake" + property string packageName: product.targetName + + additionalProductTypes: ["Exporter.cmake.package"] + + Rule { + multiplex: true + requiresInputs: false + + auxiliaryInputs: { + if (product.type.includes("staticlibrary")) + return ["staticlibrary"]; + if (product.type.includes("dynamiclibrary")) + return ["dynamiclibrary"]; + } + + Artifact { + filePath: product.Exporter.cmake.configFileName + fileTags: ["Exporter.cmake.package", "Exporter.cmake.configFile"] + } + Artifact { + filePath: product.Exporter.cmake.versionFileName + fileTags: ["Exporter.cmake.package", "Exporter.cmake.versionFile"] + } + prepare: { + var cmd = new JavaScriptCommand(); + cmd.description = "generate cmake package files"; + cmd.sourceCode = function() { + HelperFunctions.writeConfigFile(project, product, outputs); + HelperFunctions.writeVersionFile(product, outputs); + } + return [cmd]; + } + } +} diff --git a/share/qbs/modules/Exporter/exporter.js b/share/qbs/modules/Exporter/exporter.js new file mode 100644 index 000000000..65a632ac8 --- /dev/null +++ b/share/qbs/modules/Exporter/exporter.js @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2024 Ivan Komissarov (abbapoh@gmail.com) +** Contact: http://www.qt.io/licensing +** +** This file is part of the 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. +** +****************************************************************************/ + +function getPrefixToStrip(project, product, propName, value) +{ + function checkValuePrefix(forbiddenPrefix, prefixDescription) + { + if (value.startsWith(forbiddenPrefix)) { + throw "Value '" + value + "' for exported property '" + propName + "' in product '" + + product.name + "' points into " + prefixDescription + ".\n" + + "Did you forget to set the prefixMapping property in an Export item?"; + } + } + + // Catch user oversights: Paths that point into the project source or build directories + // make no sense in the module. + if (!value.startsWith(product.qbs.installRoot)) { + checkValuePrefix(project.buildDirectory, "project build directory"); + checkValuePrefix(project.sourceDirectory, "project source directory"); + } + + // Adapt file paths pointing into the install dir, that is, make them relative to the + // module file for relocatability. We accept them with or without the install root. + // The latter form will typically be a result of applying the prefixMapping property, + // while the first one could be an untransformed path, for instance if the project + // file is written in such a way that include paths are picked up from the installed + // location rather than the source directory. + var result; + var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix); + if (fullInstallPrefix.length > 1 && value.startsWith(fullInstallPrefix)) { + result = fullInstallPrefix; + } else { + var installPrefix = FileInfo.joinPaths("/", product.qbs.installPrefix); + if (installPrefix.length > 1 && value.startsWith(installPrefix)) + result = installPrefix; + } + return result; +} diff --git a/share/qbs/modules/Exporter/qbs/qbsexporter.js b/share/qbs/modules/Exporter/qbs/qbsexporter.js index f09dd2d0c..145474a4b 100644 --- a/share/qbs/modules/Exporter/qbs/qbsexporter.js +++ b/share/qbs/modules/Exporter/qbs/qbsexporter.js @@ -30,6 +30,7 @@ var FileInfo = require("qbs.FileInfo"); var ModUtils = require("qbs.ModUtils"); +var ExporterHelpers = require("../exporter.js"); function tagListToString(tagList) { @@ -102,15 +103,6 @@ function writeTargetArtifactGroups(product, output, moduleFile) } } -function checkValuePrefix(name, value, forbiddenPrefix, prefixDescription) -{ - if (value.startsWith(forbiddenPrefix)) { - throw "Value '" + value + "' for exported property '" + name + "' in product '" - + product.name + "' points into " + prefixDescription + ".\n" - + "Did you forget to set the prefixMapping property in an Export item?"; - } -} - function stringifyValue(project, product, moduleInstallDir, prop, value) { if (value instanceof Array) { @@ -128,29 +120,9 @@ function stringifyValue(project, product, moduleInstallDir, prop, value) return value; } - // Catch user oversights: Paths that point into the project source or build directories - // make no sense in the module. - if (!value.startsWith(product.qbs.installRoot)) { - checkValuePrefix(prop.name, value, project.buildDirectory, "project build directory"); - checkValuePrefix(prop.name, value, project.sourceDirectory, "project source directory"); - } - - // Adapt file paths pointing into the install dir, that is, make them relative to the - // module file for relocatability. We accept them with or without the install root. - // The latter form will typically be a result of applying the prefixMapping property, - // while the first one could be an untransformed path, for instance if the project - // file is written in such a way that include paths are picked up from the installed - // location rather than the source directory. - var valuePrefixToStrip; - var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix); - if (fullInstallPrefix.length > 1 && value.startsWith(fullInstallPrefix)) { - valuePrefixToStrip = fullInstallPrefix; - } else { - var installPrefix = FileInfo.joinPaths("/", product.qbs.installPrefix); - if (installPrefix.length > 1 && value.startsWith(installPrefix)) - valuePrefixToStrip = installPrefix; - } + var valuePrefixToStrip = ExporterHelpers.getPrefixToStrip(project, product, prop.name, value); if (valuePrefixToStrip) { + var fullInstallPrefix = FileInfo.joinPaths(product.qbs.installRoot, product.qbs.installPrefix); var deployedModuleInstallDir = moduleInstallDir.slice(fullInstallPrefix.length); return "FileInfo.cleanPath(FileInfo.joinPaths(path, FileInfo.relativePath(" + JSON.stringify(deployedModuleInstallDir) + ", " diff --git a/share/qbs/modules/Sanitizers/address/asan.qbs b/share/qbs/modules/Sanitizers/address/asan.qbs index 9ae6f285e..9d8f5b97e 100644 --- a/share/qbs/modules/Sanitizers/address/asan.qbs +++ b/share/qbs/modules/Sanitizers/address/asan.qbs @@ -64,7 +64,8 @@ Module { flags.push("-fsanitize-address-use-after-scope"); if (detectUseAfterReturn) { if (qbs.toolchain.includes("llvm")) { - if (Utilities.versionCompare(cpp.compilerVersion, "13") >= 0) + var minVersion = qbs.toolchain.contains("xcode") ? "14" : "13"; + if (Utilities.versionCompare(cpp.compilerVersion, minVersion) >= 0) flags.push("-fsanitize-address-use-after-return=" + detectUseAfterReturn); } else if (detectUseAfterReturn === "never") { flags.push("--param", "asan-use-after-return=0"); diff --git a/share/qbs/modules/bundle/BundleModule.qbs b/share/qbs/modules/bundle/BundleModule.qbs index 0d8452a7e..f640fd55f 100644 --- a/share/qbs/modules/bundle/BundleModule.qbs +++ b/share/qbs/modules/bundle/BundleModule.qbs @@ -193,6 +193,11 @@ Module { property string _productTypeIdentifier: Bundle.productTypeIdentifier(product.type) property stringList _productTypeIdentifierChain: bundleSettingsProbe.productTypeIdentifierChain + readonly property path _developerPath: xcode.developerPath + readonly property path _platformInfoPlist: xcode.platformInfoPlist + readonly property path _sdkSettingsPlist: xcode.sdkSettingsPlist + readonly property path _toolchainInfoPlist: xcode.toolchainInfoPlist + property bool _useXcodeBuildSpecs: true // TODO: remove in 1.25 property var extraEnv: ({ @@ -281,8 +286,8 @@ Module { outputFileTags: ["bundle.input", "aggregate_infoplist"] outputArtifacts: { var artifacts = []; - var embed = ModUtils.moduleProperty(product, "embedInfoPlist"); - if (ModUtils.moduleProperty(product, "isBundle") || embed) { + var embed = product.bundle.embedInfoPlist; + if (product.bundle.isBundle || embed) { artifacts.push({ filePath: FileInfo.joinPaths( product.destinationDirectory, product.name + "-Info.plist"), @@ -290,7 +295,7 @@ Module { bundle: { _bundleFilePath: FileInfo.joinPaths( product.destinationDirectory, - ModUtils.moduleProperty(product, "infoPlistPath")), + product.bundle.infoPlistPath), } }); } @@ -301,20 +306,21 @@ Module { var cmd = new JavaScriptCommand(); cmd.description = "generating Info.plist for " + product.name; cmd.highlight = "codegen"; - cmd.infoPlist = ModUtils.moduleProperty(product, "infoPlist") || {}; - cmd.processInfoPlist = ModUtils.moduleProperty(product, "processInfoPlist"); - cmd.infoPlistFormat = ModUtils.moduleProperty(product, "infoPlistFormat"); - cmd.extraEnv = ModUtils.moduleProperty(product, "extraEnv"); - cmd.qmakeEnv = ModUtils.moduleProperty(product, "qmakeEnv"); + cmd.infoPlist = product.bundle.infoPlist || {}; + cmd.processInfoPlist = product.bundle.processInfoPlist; + cmd.infoPlistFormat = product.bundle.infoPlistFormat; + cmd.extraEnv = product.bundle.extraEnv; + cmd.qmakeEnv = product.bundle.qmakeEnv; + // TODO: bundle module should know nothing about cpp module cmd.buildEnv = product.moduleProperty("cpp", "buildEnv"); - cmd.developerPath = product.moduleProperty("xcode", "developerPath"); - cmd.platformInfoPlist = product.moduleProperty("xcode", "platformInfoPlist"); - cmd.sdkSettingsPlist = product.moduleProperty("xcode", "sdkSettingsPlist"); - cmd.toolchainInfoPlist = product.moduleProperty("xcode", "toolchainInfoPlist"); + cmd.developerPath = product.bundle._developerPath; + cmd.platformInfoPlist = product.bundle._platformInfoPlist; + cmd.sdkSettingsPlist = product.bundle._sdkSettingsPlist; + cmd.toolchainInfoPlist = product.bundle._toolchainInfoPlist; - cmd.osBuildVersion = product.moduleProperty("qbs", "hostOSBuildVersion"); + cmd.osBuildVersion = product.qbs.hostOSBuildVersion; cmd.sourceCode = function() { var plist, process, key, i; @@ -343,7 +349,7 @@ Module { if (processInfoPlist) { // Add default values to the aggregate plist if the corresponding keys // for those values are not already present - var defaultValues = ModUtils.moduleProperty(product, "defaultInfoPlist"); + var defaultValues = product.bundle.defaultInfoPlist; for (key in defaultValues) { if (defaultValues.hasOwnProperty(key) && !(key in aggregatePlist)) aggregatePlist[key] = defaultValues[key]; @@ -480,11 +486,11 @@ Module { outputFileTags: ["bundle.input", "pkginfo"] outputArtifacts: { var artifacts = []; - if (ModUtils.moduleProperty(product, "isBundle") && ModUtils.moduleProperty(product, "generatePackageInfo")) { + if (product.bundle.isBundle && product.bundle.generatePackageInfo) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, "PkgInfo"), fileTags: ["bundle.input", "pkginfo"], - bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "pkgInfoPath")) } + bundle: { _bundleFilePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.pkgInfoPath) } }); } return artifacts; @@ -535,9 +541,9 @@ Module { "bundle.code-signature"] outputArtifacts: { var i, artifacts = []; - if (ModUtils.moduleProperty(product, "isBundle")) { + if (product.bundle.isBundle) { for (i in inputs["bundle.input"]) { - var fp = inputs["bundle.input"][i].moduleProperty("bundle", "_bundleFilePath"); + var fp = inputs["bundle.input"][i].bundle._bundleFilePath; if (!fp) throw("Artifact " + inputs["bundle.input"][i].filePath + " has no associated bundle file path"); var extraTags = inputs["bundle.input"][i].fileTags.includes("application") @@ -552,20 +558,19 @@ Module { for (i in provprofiles) { artifacts.push({ filePath: FileInfo.joinPaths(product.destinationDirectory, - ModUtils.moduleProperty(product, - "contentsFolderPath"), + product.bundle.contentsFolderPath, provprofiles[i].fileName), fileTags: ["bundle.provisioningprofile", "bundle.content"] }); } - var packageType = ModUtils.moduleProperty(product, "packageType"); - var isShallow = ModUtils.moduleProperty(product, "isShallow"); + var packageType = product.bundle.packageType; + var isShallow = product.bundle.isShallow; if (packageType === "FMWK" && !isShallow) { - var publicHeaders = ModUtils.moduleProperty(product, "publicHeaders"); + var publicHeaders = product.bundle.publicHeaders; if (publicHeaders && publicHeaders.length) { artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Headers"), + filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "Headers"), fileTags: ["bundle.symlink.headers", "bundle.content"] }); } @@ -573,23 +578,23 @@ Module { var privateHeaders = ModUtils.moduleProperty(product, "privateHeaders"); if (privateHeaders && privateHeaders.length) { artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "PrivateHeaders"), + filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "PrivateHeaders"), fileTags: ["bundle.symlink.private-headers", "bundle.content"] }); } artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), "Resources"), + filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, "Resources"), fileTags: ["bundle.symlink.resources", "bundle.content"] }); artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "bundleName"), product.targetName), + filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName, product.targetName), fileTags: ["bundle.symlink.executable", "bundle.content"] }); artifacts.push({ - filePath: FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "versionsFolderPath"), "Current"), + filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.versionsFolderPath, "Current"), fileTags: ["bundle.symlink.version", "bundle.content"] }); } @@ -606,7 +611,7 @@ Module { } } - sources = ModUtils.moduleProperty(product, "resources"); + sources = product.bundle.resources; for (i in sources) { destination = BundleTools.destinationDirectoryForResource(product, {baseDir: FileInfo.path(sources[i]), fileName: FileInfo.fileName(sources[i])}); artifacts.push({ @@ -617,7 +622,7 @@ Module { var wrapperPath = FileInfo.joinPaths( product.destinationDirectory, - ModUtils.moduleProperty(product, "bundleName")); + product.bundle.bundleName); for (var i = 0; i < artifacts.length; ++i) artifacts[i].bundle = { wrapperPath: wrapperPath }; @@ -634,7 +639,7 @@ Module { prepare: { var i, cmd, commands = []; - var packageType = ModUtils.moduleProperty(product, "packageType"); + var packageType = product.bundle.packageType; var bundleType = "bundle"; if (packageType === "APPL") @@ -652,7 +657,7 @@ Module { var symlinks = outputs["bundle.symlink.version"]; for (i in symlinks) { - cmd = new Command("ln", ["-sfn", ModUtils.moduleProperty(product, "frameworkVersion"), + cmd = new Command("ln", ["-sfn", product.bundle.frameworkVersion, symlinks[i].filePath]); cmd.silent = true; commands.push(cmd); @@ -699,8 +704,8 @@ Module { } var bundleInputs = sortedArtifactList(inputs["bundle.input"], function (a, b) { - return a.moduleProperty("bundle", "_bundleFilePath").localeCompare( - b.moduleProperty("bundle", "_bundleFilePath")); + return a.bundle._bundleFilePath.localeCompare( + b.bundle._bundleFilePath); }); var bundleContents = sortedArtifactList(outputs["bundle.content.copied"]); for (i in bundleContents) { @@ -733,8 +738,8 @@ Module { cmd = new JavaScriptCommand(); cmd.description = "copying public headers"; cmd.highlight = "filegen"; - cmd.sources = ModUtils.moduleProperty(product, "publicHeaders"); - cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "publicHeadersFolderPath")); + cmd.sources = product.bundle.publicHeaders; + cmd.destination = FileInfo.joinPaths(product.destinationDirectory, product.bundle.publicHeadersFolderPath); cmd.sourceCode = function() { var i; for (var i in sources) { @@ -747,8 +752,8 @@ Module { cmd = new JavaScriptCommand(); cmd.description = "copying private headers"; cmd.highlight = "filegen"; - cmd.sources = ModUtils.moduleProperty(product, "privateHeaders"); - cmd.destination = FileInfo.joinPaths(product.destinationDirectory, ModUtils.moduleProperty(product, "privateHeadersFolderPath")); + cmd.sources = product.bundle.privateHeaders; + cmd.destination = FileInfo.joinPaths(product.destinationDirectory, product.bundle.privateHeadersFolderPath); cmd.sourceCode = function() { var i; for (var i in sources) { @@ -761,7 +766,7 @@ Module { cmd = new JavaScriptCommand(); cmd.description = "copying resources"; cmd.highlight = "filegen"; - cmd.sources = ModUtils.moduleProperty(product, "resources"); + cmd.sources = product.bundle.resources; cmd.sourceCode = function() { var i; for (var i in sources) { @@ -772,17 +777,17 @@ Module { if (cmd.sources && cmd.sources.length) commands.push(cmd); - if (product.moduleProperty("qbs", "hostOS").includes("darwin")) { + if (product.qbs.hostOS.includes("darwin")) { Array.prototype.push.apply(commands, Codesign.prepareSign( project, product, inputs, outputs, input, output)); if (bundleType === "application" - && product.moduleProperty("qbs", "targetOS").includes("macos")) { + && product.qbs.targetOS.includes("macos")) { var bundlePath = FileInfo.joinPaths( product.destinationDirectory, product.bundle.bundleName); - cmd = new Command(ModUtils.moduleProperty(product, "lsregisterPath"), + cmd = new Command(product.bundle.lsregisterPath, ["-f", bundlePath]); - cmd.description = "registering " + ModUtils.moduleProperty(product, "bundleName"); + cmd.description = "registering " + product.bundle.bundleName; commands.push(cmd); } } diff --git a/share/qbs/modules/bundle/bundle.js b/share/qbs/modules/bundle/bundle.js index ec0e30054..cf765f7be 100644 --- a/share/qbs/modules/bundle/bundle.js +++ b/share/qbs/modules/bundle/bundle.js @@ -152,13 +152,21 @@ function _assign(target, source) { function macOSSpecsPaths(version, developerPath) { var result = []; - if (Utilities.versionCompare(version, "12.5") >= 0) { + if (Utilities.versionCompare(version, "15.3") >= 0) { + result.push(FileInfo.joinPaths( + developerPath, "..", "SharedFrameworks", "XCBuild.framework", "PlugIns", + "XCBBuildService.bundle", "Contents", "PlugIns", "XCBSpecifications.ideplugin", + "Contents", "Resources")); + } + if (Utilities.versionCompare(version, "14.3") >= 0) { + result.push(FileInfo.joinPaths( + developerPath, "Library", "Xcode", "Plug-ins", "XCBSpecifications.ideplugin", + "Contents", "Resources")); + } else if (Utilities.versionCompare(version, "12.5") >= 0) { result.push(FileInfo.joinPaths( developerPath, "..", "PlugIns", "XCBSpecifications.ideplugin", "Contents", "Resources")); - } - - if (Utilities.versionCompare(version, "12") >= 0) { + } else if (Utilities.versionCompare(version, "12") >= 0) { result.push(FileInfo.joinPaths( developerPath, "Platforms", "MacOSX.platform", "Developer", "Library", "Xcode", "PrivatePlugIns", "IDEOSXSupportCore.ideplugin", "Contents", "Resources")); @@ -311,7 +319,8 @@ var XcodeBuildSpecsReader = (function () { }; XcodeBuildSpecsReader.prototype.expandedSetting = function (typeIdentifier, baseSettings, settingName) { - var obj = baseSettings || {}; + var obj = {}; + _assign(obj, baseSettings); // todo: copy recursively obj = _assign(obj, this.settings(typeIdentifier, true)); if (obj) { for (var x in this._additionalSettings) { diff --git a/share/qbs/modules/capnproto/capnprotobase.qbs b/share/qbs/modules/capnproto/capnprotobase.qbs index e84d39433..916e53a51 100644 --- a/share/qbs/modules/capnproto/capnprotobase.qbs +++ b/share/qbs/modules/capnproto/capnprotobase.qbs @@ -28,6 +28,7 @@ ** ****************************************************************************/ +import qbs.FileInfo import qbs.Probes import "capnproto.js" as HelperFunctions @@ -40,16 +41,20 @@ Module { property pathList importPaths: [] - readonly property string outputDir: product.buildDirectory + "/capnp" + property string outputDir: product.buildDirectory + "/capnp" + + property var _searchPaths Probes.BinaryProbe { id: compilerProbe names: compilerName ? [compilerName] : [] + searchPaths: _searchPaths } Probes.BinaryProbe { id: pluginProbe names: pluginName ? [pluginName] : [] + searchPaths: _searchPaths } FileTagger { diff --git a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs index f33bc9a48..83192b7de 100644 --- a/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs +++ b/share/qbs/modules/capnproto/cpp/capnprotocpp.qbs @@ -39,6 +39,8 @@ CapnProtoBase { Depends { name: "capnp-rpc"; condition: useRpc } pluginName: "capnpc-c++" + version: capnp.version + _searchPaths: capnp.hostBinDirs cpp.systemIncludePaths: outputDir cpp.cxxLanguageVersion: "c++14" diff --git a/share/qbs/modules/codesign/apple.qbs b/share/qbs/modules/codesign/apple.qbs index 72384a06a..0d1335d92 100644 --- a/share/qbs/modules/codesign/apple.qbs +++ b/share/qbs/modules/codesign/apple.qbs @@ -181,7 +181,7 @@ CodeSignModule { } readonly property string _embeddedProfileName: - (xcode._platformProps || {})["EMBEDDED_PROFILE_NAME"] + (xcode._platformProps || {})["EMBEDDED_PROFILE_NAME"] || "embedded.mobileprovision" setupBuildEnvironment: { var prefixes = product.xcode ? [ diff --git a/share/qbs/modules/codesign/codesign.js b/share/qbs/modules/codesign/codesign.js index 903d16f80..482225ea2 100644 --- a/share/qbs/modules/codesign/codesign.js +++ b/share/qbs/modules/codesign/codesign.js @@ -280,20 +280,21 @@ function prepareSign(project, product, inputs, outputs, input, output) { return cmds; var isBundle = "bundle.content" in outputs; - var outputFilePath = isBundle - ? FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName) - : outputs["codesign.signed_artifact"][0].filePath; - var outputFileName = isBundle - ? product.bundle.bundleName - : outputs["codesign.signed_artifact"][0].fileName; - var isProductBundle = product.bundle && product.bundle.isBundle; - // If the product is a bundle, just sign the bundle - // instead of signing the bundle and executable separately + var artifacts = []; + if (isBundle) { + artifacts = [{ + filePath: FileInfo.joinPaths(product.destinationDirectory, product.bundle.bundleName), + fileName: product.bundle.bundleName + }]; + } else { + artifacts = outputs["codesign.signed_artifact"]; + } + var isProductBundle = product.bundle && product.bundle.isBundle; var shouldSignArtifact = !isProductBundle || isBundle; var enableCodeSigning = product.codesign.enableCodeSigning; - if (enableCodeSigning && shouldSignArtifact) { + if (enableCodeSigning) { var actualSigningIdentity = product.codesign._actualSigningIdentity; if (!actualSigningIdentity) { throw "No codesigning identities (i.e. certificate and private key pairs) matching “" @@ -310,36 +311,53 @@ function prepareSign(project, product, inputs, outputs, input, output) { } } - var args = ["--force", "--sign", actualSigningIdentity.SHA1]; - - // 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) { - // 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"; - if (signingTimestamp) - flag += "=" + signingTimestamp; - args.push(flag); + // The codesign tool behaves weirdly. It can sign a bundle with a single artifact, but if + // say debug build variant is present, it starts complaining that it is not signed. + // We could always sign everything, but again, in case of a framework (but not in case of + // app or loadable bundle), codesign produces a warning that artifact is already signed. + // So, we skip signing the release artifact and only sign if other build variants present. + if (!shouldSignArtifact && artifacts.length == 1) { + artifacts = []; } + for (var i = 0; i < artifacts.length; ++i) { + if (!shouldSignArtifact + && artifacts[i].qbs && artifacts[i].qbs.buildVariant === "release") { + continue; + } + var outputFilePath = artifacts[i].filePath; + var outputFileName = artifacts[i].fileName; + + var args = ["--force", "--sign", actualSigningIdentity.SHA1]; + + // 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) { + // 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"; + if (signingTimestamp) + flag += "=" + signingTimestamp; + args.push(flag); + } - for (var j in inputs["codesign.xcent"]) { - args.push("--entitlements", inputs["codesign.xcent"][j].filePath); - break; // there should only be one - } + for (var j in inputs["codesign.xcent"]) { + args.push("--entitlements", inputs["codesign.xcent"][j].filePath); + break; // there should only be one + } - args = args.concat(product.codesign.codesignFlags || []); + args = args.concat(product.codesign.codesignFlags || []); - args.push(outputFilePath + subpath); - cmd = new Command(product.codesign.codesignPath, args); - cmd.description = "codesign " + outputFileName - + " (" + actualSigningIdentity.subjectInfo.CN + ")"; - cmd.outputFilePath = outputFilePath; - cmd.stderrFilterFunction = function(stderr) { - return stderr.replace(outputFilePath + ": replacing existing signature\n", ""); - }; - cmds.push(cmd); + args.push(outputFilePath + subpath); + cmd = new Command(product.codesign.codesignPath, args); + cmd.description = "codesign " + outputFileName + + " (" + actualSigningIdentity.subjectInfo.CN + ")"; + cmd.outputFilePath = outputFilePath; + cmd.stderrFilterFunction = function(stderr) { + return stderr.replace(outputFilePath + ": replacing existing signature\n", ""); + }; + cmds.push(cmd); + } } if (isBundle) { diff --git a/share/qbs/modules/cpp/GenericGCC.qbs b/share/qbs/modules/cpp/GenericGCC.qbs index 22a98ad57..f84028940 100644 --- a/share/qbs/modules/cpp/GenericGCC.qbs +++ b/share/qbs/modules/cpp/GenericGCC.qbs @@ -170,7 +170,7 @@ CppModule { property string linkerVariant PropertyOptions { name: "linkerVariant" - allowedValues: ["bfd", "gold", "lld"] + allowedValues: ["bfd", "gold", "lld", "mold"] description: "Allows to specify the linker variant. Maps to gcc's and clang's -fuse-ld " + "option." } @@ -216,7 +216,7 @@ CppModule { linkerScriptFlag: "-T" readonly property bool shouldCreateSymlinks: { - return createSymlinks && internalVersion && ["macho", "elf"].includes(cpp.imageFormat); + return createSymlinks && internalVersion && ["macho", "elf"].includes(imageFormat); } readonly property bool shouldSignArtifacts: codesign._canSignArtifacts @@ -252,7 +252,7 @@ CppModule { property var buildEnv: { var env = {}; if (qbs.toolchain.includes("mingw")) - env.PATH = [toolchainInstallPath]; // For libwinpthread etc + env.PATH = toolchainInstallPath; // For libwinpthread etc return env; } diff --git a/share/qbs/modules/cpp/cpp.js b/share/qbs/modules/cpp/cpp.js index a13504013..9f907580a 100644 --- a/share/qbs/modules/cpp/cpp.js +++ b/share/qbs/modules/cpp/cpp.js @@ -327,7 +327,10 @@ function collectIncludePaths(input) { var includePaths = input.cpp.includePaths; if (includePaths) allIncludePaths = allIncludePaths.uniqueConcat(includePaths); - return allIncludePaths; + var builtIns = input.cpp.compilerIncludePaths; + return allIncludePaths.filter(function(p) { + return !builtIns.includes(p); + }); } function collectSystemIncludePaths(input) { @@ -338,7 +341,10 @@ function collectSystemIncludePaths(input) { var distributionIncludePaths = input.cpp.distributionIncludePaths; if (distributionIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(distributionIncludePaths); - return allIncludePaths; + var builtIns = input.cpp.compilerIncludePaths; + return allIncludePaths.filter(function(p) { + return !builtIns.includes(p); + }); } function collectPreincludePaths(input) { diff --git a/share/qbs/modules/cpp/gcc.js b/share/qbs/modules/cpp/gcc.js index 747c6c9ee..90f8fc933 100644 --- a/share/qbs/modules/cpp/gcc.js +++ b/share/qbs/modules/cpp/gcc.js @@ -78,6 +78,7 @@ function useCompilerDriverLinker(product, inputs) { function collectLibraryDependencies(product, isDarwin) { var publicDeps = {}; + var privateDeps = {}; var objects = []; var objectByFilePath = {}; var tagForLinkingAgainstSharedLib = product.cpp.imageFormat === "pe" @@ -170,6 +171,8 @@ function collectLibraryDependencies(product, isDarwin) { && typeof dep.artifacts[tagForLinkingAgainstSharedLib] !== "undefined"; if (!isStaticLibrary && !isDynamicLibrary) return; + if (isBelowIndirectDynamicLib && privateDeps[dep.name]) + return; var nextIsBelowIndirectDynamicLib = isBelowIndirectDynamicLib || isDynamicLibrary; dep.dependencies.forEach(function(depdep) { @@ -193,6 +196,7 @@ function collectLibraryDependencies(product, isDarwin) { publicDeps[dep.name] = true; } else { addArtifactFilePaths(dep, tagForLinkingAgainstSharedLib, addPrivateFilePath); + privateDeps[dep.name] = true; } } } @@ -204,7 +208,6 @@ function collectLibraryDependencies(product, isDarwin) { product.dependencies.forEach(traverseDirectDependency); addExternalLibs(product); - var seenRPathLinkDirs = {}; var result = { libraries: [], rpath_link: [] }; objects.forEach( function (obj) { @@ -215,10 +218,7 @@ function collectLibraryDependencies(product, isDarwin) { framework: obj.framework }); } else { var dirPath = FileInfo.path(obj.filePath); - if (!seenRPathLinkDirs.hasOwnProperty(dirPath)) { - seenRPathLinkDirs[dirPath] = true; - result.rpath_link.push(dirPath); - } + result.rpath_link.push(dirPath); } }); return result; @@ -377,6 +377,9 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat var minimumWindowsVersion = product.cpp.minimumWindowsVersion; if (minimumWindowsVersion) { + // workaround for QBS-1724, mingw seems to be broken + if (Utilities.versionCompare(minimumWindowsVersion, "6.2") > 0) + minimumWindowsVersion = "6.2"; var subsystemVersion = WindowsUtils.getWindowsVersionInFormat(minimumWindowsVersion, 'subsystem'); if (subsystemVersion) { var major = subsystemVersion.split('.')[0]; @@ -403,8 +406,8 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat // Flags for library search paths var allLibraryPaths = Cpp.collectLibraryPaths(product); - if (systemRunPaths.length > 0) - allLibraryPaths = allLibraryPaths.filter(isNotSystemRunPath); + var builtIns = product.cpp.compilerLibraryPaths + allLibraryPaths = allLibraryPaths.filter(function(p) { return !builtIns.includes(p); }); args = args.concat(allLibraryPaths.map(function(path) { return product.cpp.libraryPathFlag + path })); escapableLinkerFlags = escapableLinkerFlags.concat(Cpp.collectLinkerScriptPathsArguments(product, inputs)); @@ -474,7 +477,10 @@ function linkerFlags(project, product, inputs, outputs, primaryOutput, linkerPat if (isDarwin && symbolLinkMode) { if (!["lazy", "reexport", "upward", "weak"].includes(symbolLinkMode)) throw new Error("unknown value '" + symbolLinkMode + "' for cpp.symbolLinkMode"); + } + var supportsLazyMode = Utilities.versionCompare(product.cpp.compilerVersion, "15.0.0") < 0; + if (isDarwin && symbolLinkMode && (symbolLinkMode !== "lazy" || supportsLazyMode)) { if (FileInfo.isAbsolutePath(lib) || lib.startsWith('@')) escapableLinkerFlags.push("-" + symbolLinkMode + "_library", lib); else if (dep.framework) diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js index 8be4bff24..1700c21b3 100644 --- a/share/qbs/modules/cpp/msvc.js +++ b/share/qbs/modules/cpp/msvc.js @@ -79,8 +79,8 @@ function hasCxx17Option(input) { // Probably this is not the earliest version to support the flag, but we have tested this one // and it's a pain to find out the exact minimum. - return Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0 - || (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 7); + return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 7) + || Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0; } function hasZCplusPlusOption(input) @@ -92,20 +92,20 @@ function hasZCplusPlusOption(input) // clang-cl supports this option starting around-ish versions 8/9, but it // ignores this option, so this doesn't really matter // https://reviews.llvm.org/D45877 - return Utilities.versionCompare(input.cpp.compilerVersion, "19.14.26433") >= 0 - || (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 9); + return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 9) + || Utilities.versionCompare(input.cpp.compilerVersion, "19.14.26433") >= 0; } function hasCxx20Option(input) { - return Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30133.0") >= 0 - || (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13); + return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13) + || Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30133.0") >= 0; } function hasCVerOption(input) { - return Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30138.0") >= 0 - || (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13); + return (input.qbs.toolchain.includes("clang-cl") && input.cpp.compilerVersionMajor >= 13) + || Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30138.0") >= 0; } function supportsExternalIncludesOption(input) { @@ -124,10 +124,9 @@ function addCxxLanguageVersionFlag(input, args) { if (!cxxVersion) return; - // Visual C++ 2013, Update 3 - var hasStdOption = Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0 - // or clang-cl - || input.qbs.toolchain.includes("clang-cl"); + // Visual C++ 2013, Update 3 or clang-cl + var hasStdOption = input.qbs.toolchain.includes("clang-cl") + || Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0; if (!hasStdOption) return; @@ -250,14 +249,17 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path); })); - var includeFlag = input.cpp.includeFlag; - if (supportsExternalIncludesOption(input)) { - args.push("/experimental:external"); - var enforcesSlashW = - Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30037") >= 0 - if (enforcesSlashW) - args.push("/external:W0") - includeFlag = input.cpp.systemIncludeFlag; + var includeFlag = input.qbs.toolchain.includes("clang-cl") + ? input.cpp.systemIncludeFlag : input.cpp.includeFlag; + if (!input.qbs.toolchain.includes("clang-cl")) { + if (supportsExternalIncludesOption(input)) { + args.push("/experimental:external"); + var enforcesSlashW = + Utilities.versionCompare(input.cpp.compilerVersion, "19.29.30037") >= 0 + if (enforcesSlashW) + args.push("/external:W0") + includeFlag = input.cpp.systemIncludeFlag; + } } var systemIncludePaths = Cpp.collectSystemIncludePaths(input); args = args.concat([].uniqueConcat(systemIncludePaths).map(function(path) { @@ -371,7 +373,8 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli function linkerSupportsWholeArchive(product) { - return Utilities.versionCompare(product.cpp.compilerVersion, "19.0.24215.1") >= 0 + return product.qbs.toolchainType.includes("clang-cl") || + Utilities.versionCompare(product.cpp.compilerVersion, "19.0.24215.1") >= 0 } function handleDiscardProperty(product, flags) { diff --git a/share/qbs/modules/cpp/windows-clang-cl.qbs b/share/qbs/modules/cpp/windows-clang-cl.qbs index 32abb572a..9aa9d7395 100644 --- a/share/qbs/modules/cpp/windows-clang-cl.qbs +++ b/share/qbs/modules/cpp/windows-clang-cl.qbs @@ -85,6 +85,8 @@ MsvcBaseModule { linkerName: "lld-link.exe" linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) + systemIncludeFlag: "/imsvc" + validateFunc: { var baseFunc = base; return function() { diff --git a/share/qbs/modules/cpp/windows-msvc-base.qbs b/share/qbs/modules/cpp/windows-msvc-base.qbs index 1a2c338db..9613800e5 100644 --- a/share/qbs/modules/cpp/windows-msvc-base.qbs +++ b/share/qbs/modules/cpp/windows-msvc-base.qbs @@ -320,12 +320,11 @@ CppModule { outputFileTags: Cpp.assemblerOutputTags(false) outputArtifacts: Cpp.assemblerOutputArtifacts(input) prepare: { - var args = ["/nologo", "/c", - "/Fo" + FileInfo.toWindowsSeparators(output.filePath), - FileInfo.toWindowsSeparators(input.filePath)]; + var args = ["/nologo", "/c", "/Fo" + FileInfo.toWindowsSeparators(output.filePath)]; if (product.cpp.debugInformation) args.push("/Zi"); args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm")); + args.push(FileInfo.toWindowsSeparators(input.filePath)); var cmd = new Command(product.cpp.assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.jobPool = "assembler"; diff --git a/share/qbs/modules/dmg/DMGModule.qbs b/share/qbs/modules/dmg/DMGModule.qbs index 59161b1db..27a945033 100644 --- a/share/qbs/modules/dmg/DMGModule.qbs +++ b/share/qbs/modules/dmg/DMGModule.qbs @@ -34,6 +34,7 @@ import qbs.FileInfo import qbs.Host import qbs.ModUtils import qbs.Process +import qbs.Probes import qbs.TextFile import "dmg.js" as Dmg @@ -73,6 +74,12 @@ Module { property string sourceBase + Probes.BinaryProbe { + id: pythonProbe + names: ["python3"] + } + property string pythonExePath: pythonProbe.found ? pythonProbe.filePath : "python3" + readonly property string pythonPath: File.canonicalFilePath(FileInfo.joinPaths(path, "..", "..", "python")) diff --git a/share/qbs/modules/dmg/dmg.js b/share/qbs/modules/dmg/dmg.js index 7d50d95f3..06fe7b906 100644 --- a/share/qbs/modules/dmg/dmg.js +++ b/share/qbs/modules/dmg/dmg.js @@ -135,7 +135,7 @@ function dmgbuildSettings(product, inputs) { } }); - return { + var result = { "title": product.dmg.volumeName, "icon": !product.dmg.badgeVolumeIcon ? volumeIcon : undefined, "badge-icon": product.dmg.badgeVolumeIcon ? volumeIcon : undefined, @@ -154,13 +154,16 @@ function dmgbuildSettings(product, inputs) { }, "format": product.dmg.format, "compression-level": product.dmg.compressionLevel, - "license": { + "contents": contentsArray + }; + if (licenseFileObjects.length >= 0) { + result["license"] = { "default-language": product.dmg.defaultLicenseLocale, "licenses": reduceLicensesForKey(licenseFileObjects, "licenses"), "buttons": reduceLicensesForKey(licenseFileObjects, "buttons") - }, - "contents": contentsArray - }; + }; + } + return result; } function prepareLicense(project, product, inputs, outputs, input, output) { @@ -199,8 +202,10 @@ function prepareDmg(project, product, inputs, outputs, input, output) { cmds.push(cmd); // Create the actual DMG via dmgbuild - cmd = new Command(FileInfo.joinPaths(product.qbs.libexecPath, "dmgbuild"), - [product.dmg.volumeName, + cmd = new Command(product.dmg.pythonExePath, + ["-m", + "dmgbuild", + product.dmg.volumeName, output.filePath, "--no-hidpi", // qbs handles this by itself "--settings", settingsJsonFilePath]); diff --git a/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs b/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs new file mode 100644 index 000000000..9f5b2b70c --- /dev/null +++ b/share/qbs/modules/flatbuf/c/flatbuffers-c.qbs @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@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.FileInfo + +import "../flatbuffers.js" as Flatbuf +import "../flatbuffersbase.qbs" as FlatbufBase + +FlatbufBase { + Depends { name: "cpp" } + Depends { name: "flatcc" } + + compilerName: "flatcc" + + _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "c") + _searchPaths: flatbuffers.hostBinDirs + + cpp.systemIncludePaths: base.concat([_outputDir]) + + Rule { + inputs: ["flatbuf.input"] + outputFileTags: ["hpp"] + outputArtifacts: [Flatbuf.artifactC(input.flatbuf.c, input, "hpp", "_generated.h")] + + prepare: { + return Flatbuf.doPrepareC(input.flatbuf.c, input); + } + } + + validate: { + Flatbuf.validateCompiler(compilerName, compilerPath); + } +} diff --git a/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs b/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs new file mode 100644 index 000000000..4614d4949 --- /dev/null +++ b/share/qbs/modules/flatbuf/cpp/flatbuffers-cpp.qbs @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@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.FileInfo + +import "../flatbuffers.js" as Flatbuf +import "../flatbuffersbase.qbs" as FlatbufBase + +FlatbufBase { + Depends { name: "cpp" } + Depends { name: "flatbuffers" } + + property string filenameExtension: "h" + property string filenameSuffix: "_generated" + property string includePrefix // TODO: test + property bool keepPrefix: false + + _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf", "cpp") + _searchPaths: flatbuffers.hostBinDirs + + cpp.cxxLanguageVersion: "c++11" + cpp.systemIncludePaths: base.concat([_outputDir]) + + Rule { + inputs: ["flatbuf.input"] + outputFileTags: ["hpp"] + outputArtifacts: { + var module = input.flatbuf.cpp; + var fullSuffix = module.filenameSuffix + "." + module.filenameExtension; + return [ Flatbuf.artifact(module, input, "hpp", fullSuffix) ]; + } + + prepare: { + return Flatbuf.doPrepareCpp(input.flatbuf.cpp, input, output); + } + } + + validate: { + Flatbuf.validateCompiler(compilerName, compilerPath); + } +} diff --git a/share/qbs/modules/flatbuf/flatbuffers.js b/share/qbs/modules/flatbuf/flatbuffers.js new file mode 100644 index 000000000..24fd91168 --- /dev/null +++ b/share/qbs/modules/flatbuf/flatbuffers.js @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@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. +** +****************************************************************************/ + +var File = require("qbs.File"); + +function validateCompiler(compilerName, compilerPath) { + if (!File.exists(compilerPath)) { + throw "Can't find '" + compilerName + "' binary. Please set the compilerPath property or " + + "make sure the compiler is found in PATH"; + } +} + +function getOutputDir(module, input) { + var outputDir = module._outputDir; + if (!module.keepPrefix) + return outputDir; + var importPaths = module.importPaths; + if (importPaths !== undefined && importPaths.length !== 0) { + var canonicalInput = File.canonicalFilePath(FileInfo.path(input.filePath)); + for (var i = 0; i < importPaths.length; ++i) { + var path = File.canonicalFilePath(importPaths[i]); + + if (canonicalInput.startsWith(path)) { + return outputDir + "/" + FileInfo.relativePath(path, canonicalInput); + } + } + } + return outputDir; +} + +function artifactC(module, input, tag, suffix) { + var outputDir = module._outputDir; + return { + fileTags: [tag], + filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix, + cpp: { warningLevel: "none"} + }; +} + +function doPrepareC(module, input) +{ + var args = []; + args.push("-a") // write all + args.push("-o", input.flatbuf.c._outputDir) // output dir + + var importPaths = module.importPaths; + importPaths.forEach(function(path) { + args.push("-I", path); + }); + + args.push(input.filePath); + + var cmd = new Command(module.compilerPath, args); + cmd.workingDirectory = FileInfo.path(module._outputDir) + cmd.highlight = "codegen"; + cmd.description = "generating C files for " + input.fileName; + return [cmd]; +} + +function artifact(module, input, tag, suffix) { + var outputDir = getOutputDir(module, input); + return { + fileTags: [tag], + filePath: outputDir + "/" + FileInfo.baseName(input.fileName) + suffix, + cpp: { warningLevel: "none" } + }; +} + +function doPrepareCpp(module, input, output) +{ + var outputDir = FileInfo.path(output.filePath); + var result = []; + + var args = []; + args.push("--cpp") + + var importPaths = module.importPaths; + importPaths.forEach(function(path) { + args.push("-I", path); + }); + + args.push("--filename-ext", module.filenameExtension); + args.push("--filename-suffix", module.filenameSuffix); + + if (module.includePrefix) + args.push("--include-prefix", module.includePrefix); + + if (module.keepPrefix) + args.push("--keep-prefix"); + + args.push(input.filePath); + var cmd = new Command(input.flatbuf.cpp.compilerPath, args); + cmd.workingDirectory = outputDir; + cmd.highlight = "codegen"; + cmd.description = "generating C++ files for " + input.fileName; + result.push(cmd); + + return result; +} diff --git a/share/qbs/modules/flatbuf/flatbuffersbase.qbs b/share/qbs/modules/flatbuf/flatbuffersbase.qbs new file mode 100644 index 000000000..98eb2f344 --- /dev/null +++ b/share/qbs/modules/flatbuf/flatbuffersbase.qbs @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2024 Ivan Komissarov (abbapoh@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.FileInfo +import qbs.Probes + +import "flatbuffers.js" as HelperFunctions + +Module { + property string compilerName: "flatc" + property string compilerPath: compilerProbe.filePath + + property pathList importPaths: [] + + property string _outputDir: FileInfo.joinPaths(product.buildDirectory, "flatbuf") + + property stringList _searchPaths + + FileTagger { + patterns: ["*.fbs"] + fileTags: ["flatbuf.input"]; + } + + Probes.BinaryProbe { + id: compilerProbe + names: [compilerName] + searchPaths: _searchPaths + } +} diff --git a/share/qbs/modules/java/utils.js b/share/qbs/modules/java/utils.js index 9ee5932dc..a59b8d41d 100644 --- a/share/qbs/modules/java/utils.js +++ b/share/qbs/modules/java/utils.js @@ -99,16 +99,44 @@ function findJdkPath(hostOS, arch, environmentPaths, searchPaths) { try { // We filter by architecture here so that we'll get a compatible JVM for JNI use. var args = []; + var canonicalArch; if (arch) { // Hardcoding apple/macosx/macho here is fine because we know we're on macOS - args.push("--arch", - Utilities.canonicalTargetArchitecture(arch, undefined, - "apple", "macosx", "macho")); + canonicalArch = Utilities.canonicalTargetArchitecture(arch, undefined, "apple", + "macosx", "macho"); + args.push("--arch", canonicalArch); } // --failfast doesn't print the default JVM if nothing matches the filter(s). var status = p.exec("/usr/libexec/java_home", args.concat(["--failfast"])); - return status === 0 ? p.readStdOut().trim() : undefined; + if (status === 0) + return p.readStdOut().trim(); + + // It has been obvserved that java_home fails for any architecture that is passed, + // so try without the filter and look up the JDK architecture manually. + if (!canonicalArch) + return undefined; + + if (p.exec("/usr/libexec/java_home", ["--failfast"]) !== 0) + return undefined; + var jdkPath = p.readStdOut().trim(); + var releaseFile = new TextFile(jdkPath + "/release", TextFile.ReadOnly); + var line; + while ((line = releaseFile.readLine())) { + if (!line.startsWith("OS_ARCH=")) + continue; + var firstQuote = line.indexOf('"'); + if (firstQuote === -1) + break; + var secondQuote = line.indexOf('"', firstQuote + 1); + if (secondQuote === -1) + break; + var archFromFile = line.substring(firstQuote + 1, secondQuote); + if (archFromFile !== canonicalArch) + break; + return jdkPath; + } + return undefined; } finally { p.close(); } diff --git a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs index ae218a0c2..bd4a08557 100644 --- a/share/qbs/modules/protobuf/cpp/protobufcpp.qbs +++ b/share/qbs/modules/protobuf/cpp/protobufcpp.qbs @@ -6,40 +6,29 @@ import "../protobufbase.qbs" as ProtobufBase import "../protobuf.js" as HelperFunctions ProtobufBase { - property string includePath: includeProbe.found ? includeProbe.path : undefined - property string libraryPath: libraryProbe.found ? libraryProbe.path : undefined - property bool useGrpc: false property bool _linkLibraries: true - property stringList _extraGrpcLibs: [] readonly property bool _hasModules: protobuflib.present && (!useGrpc || grpcpp.present) - property string grpcIncludePath: grpcIncludeProbe.found ? grpcIncludeProbe.path : undefined - property string grpcLibraryPath: grpcLibraryProbe.found ? grpcLibraryProbe.path : undefined + property string _cxxLanguageVersion: "c++17" - readonly property string _libraryName: { - var libraryName; - if (libraryProbe.found) { - libraryName = FileInfo.baseName(libraryProbe.fileName); - if (libraryName.startsWith("lib")) - libraryName = libraryName.substring(3); - } - return libraryName; - } + _searchPaths: protobuflib.present ? protobuflib.hostBinDirs : undefined + property stringList _grpcSearchPaths: grpcpp.present ? grpcpp.hostBinDirs : undefined + + cpp.includePaths: outputDir Depends { name: "cpp" } Depends { name: "protobuflib"; condition: _linkLibraries; - required: false; - enableFallback: false + required: false } Depends { - name: "grpcpp"; + name: "grpc++"; + id: grpcpp condition: _linkLibraries && useGrpc; - required: false; - enableFallback: false + required: false } property path grpcPluginPath: grpcPluginProbe.filePath @@ -48,45 +37,10 @@ ProtobufBase { condition: useGrpc id: grpcPluginProbe names: "grpc_cpp_plugin" + searchPaths: _grpcSearchPaths } - cpp.libraryPaths: { - if (!_linkLibraries || _hasModules) - return []; - - var result = []; - if (libraryProbe.found) - result.push(libraryProbe.path); - if (useGrpc && grpcLibraryProbe.found) - result.push(grpcLibraryPath); - return result; - } - cpp.dynamicLibraries: { - if (!_linkLibraries || _hasModules) - return []; - - var result = []; - if (_libraryName) - result.push(_libraryName) - if (qbs.targetOS.includes("unix")) - result.push("pthread"); - if (useGrpc) { - result = result.concat(_extraGrpcLibs); - result.push("grpc++"); - } - return result; - } - cpp.includePaths: { - if (!_linkLibraries || _hasModules) - return [outputDir]; - - var result = [outputDir]; - if (includeProbe.found) - result.push(includePath); - if (useGrpc && grpcIncludeProbe.found) - result.push(grpcIncludePath); - return result; - } + cpp.cxxLanguageVersion: _cxxLanguageVersion Rule { inputs: ["protobuf.input", "protobuf.grpc"] @@ -120,56 +74,16 @@ ProtobufBase { } } - Probes.IncludeProbe { - id: includeProbe - names: "google/protobuf/message.h" - platformSearchPaths: includePath ? [] : base - searchPaths: includePath ? [includePath] : [] - } - - Probes.LibraryProbe { - id: libraryProbe - names: [ - "protobuf", - "protobufd", - ] - platformSearchPaths: libraryPath ? [] : base - searchPaths: libraryPath ? [libraryPath] : [] - } - - Probes.IncludeProbe { - id: grpcIncludeProbe - pathSuffixes: "grpc++" - names: "grpc++.h" - platformSearchPaths: grpcIncludePath ? [] : base - searchPaths: grpcIncludePath ? [grpcIncludePath] : [] - } - - Probes.LibraryProbe { - id: grpcLibraryProbe - names: "grpc++" - platformSearchPaths: grpcLibraryPath ? [] : base - searchPaths: grpcLibraryPath ? [grpcLibraryPath] : [] - } - validate: { HelperFunctions.validateCompiler(compilerName, compilerPath); - if (_hasModules) - return; - - if (_linkLibraries && !includeProbe.found) - throw "Can't find cpp protobuf include files. Please set the includePath property."; - if (_linkLibraries && !libraryProbe.found) - throw "Can't find cpp protobuf library. Please set the libraryPath property."; + if (_linkLibraries && ! _hasModules) { + throw "Can't find cpp protobuf runtime. Make sure .pc files are present"; + } if (useGrpc) { if (!File.exists(grpcPluginPath)) throw "Can't find grpc_cpp_plugin plugin. Please set the grpcPluginPath property."; - if (_linkLibraries && !grpcIncludeProbe.found) - throw "Can't find grpc++ include files. Please set the grpcIncludePath property."; - if (_linkLibraries && !grpcLibraryProbe.found) - throw "Can't find grpc++ library. Please set the grpcLibraryPath property."; } } } diff --git a/share/qbs/modules/protobuf/nanopb/nanopb.qbs b/share/qbs/modules/protobuf/nanopb/nanopb.qbs index 898e230b6..ada7c20bb 100644 --- a/share/qbs/modules/protobuf/nanopb/nanopb.qbs +++ b/share/qbs/modules/protobuf/nanopb/nanopb.qbs @@ -41,6 +41,7 @@ ProtobufBase { result.push(includePath); return result; } + cpp.cxxLanguageVersion: qbs.targetOS.contains("darwin") ? ["c++17"] : ["c++11"] Rule { inputs: ["protobuf.input"] diff --git a/share/qbs/modules/protobuf/protobufbase.qbs b/share/qbs/modules/protobuf/protobufbase.qbs index e302d3758..e32ee30b9 100644 --- a/share/qbs/modules/protobuf/protobufbase.qbs +++ b/share/qbs/modules/protobuf/protobufbase.qbs @@ -6,6 +6,7 @@ import "protobuf.js" as HelperFunctions Module { property string compilerName: "protoc" property string compilerPath: compilerProbe.filePath + property var _searchPaths property pathList importPaths: [] @@ -19,5 +20,6 @@ Module { Probes.BinaryProbe { id: compilerProbe names: [compilerName] + searchPaths: _searchPaths } } diff --git a/share/qbs/modules/qbs/common.qbs b/share/qbs/modules/qbs/common.qbs index 7723c6050..8b31092a9 100644 --- a/share/qbs/modules/qbs/common.qbs +++ b/share/qbs/modules/qbs/common.qbs @@ -102,7 +102,7 @@ Module { property path installSourceBase property string installRoot: project.buildDirectory + "/install-root" property string installDir - property string installPrefix: qbs.targetOS.includes("unix") ? "/usr/local" : "" + property string installPrefix: targetOS.includes("unix") ? "/usr/local" : "" property path sysroot PropertyOptions { diff --git a/share/qbs/modules/xcode/xcode.js b/share/qbs/modules/xcode/xcode.js index 15afddb95..726974579 100644 --- a/share/qbs/modules/xcode/xcode.js +++ b/share/qbs/modules/xcode/xcode.js @@ -112,7 +112,7 @@ function sdkInfoList(sdksPath) { if (!sdks[i].match(/[0-9]+/)) continue; - if (sdks[i].startsWith("DriverKit")) + if (sdks[i].startsWith("DriverKit") || sdks[i].startsWith("AssetRuntime")) continue; var settingsPlist = FileInfo.joinPaths(sdksPath, sdks[i], "SDKSettings.plist"); @@ -205,8 +205,19 @@ function boolFromSdkOrPlatform(varName, sdkProps, platformProps, defaultValue) { function archsSpecsPath(version, targetOS, platformType, platformPath, devicePlatformPath, developerPath) { if (Utilities.versionCompare(version, "13.3") >= 0) { - var baseDir = FileInfo.joinPaths(developerPath, "..", - "PlugIns/XCBSpecifications.ideplugin/Contents/Resources"); + var pluginsDir; + if (Utilities.versionCompare(version, "15.3") >= 0) { + pluginsDir = FileInfo.joinPaths(developerPath, "..", + "SharedFrameworks", "XCBuild.framework", "PlugIns", "XCBBuildService.bundle", + "Contents", "PlugIns"); + } else if (Utilities.versionCompare(version, "14.3") >= 0) { + pluginsDir = FileInfo.joinPaths(developerPath, "Library", "Xcode", "Plug-ins"); + } else { + pluginsDir = FileInfo.joinPaths(developerPath, "..", "PlugIns"); + } + var baseDir = FileInfo.joinPaths(pluginsDir, + "XCBSpecifications.ideplugin", "Contents", "Resources"); + var baseName = targetOS.includes("macos") ? "MacOSX Architectures" : targetOS.includes("ios-simulator") ? "iOS Simulator" : targetOS.includes("ios") ? "iOS Device" diff --git a/share/qbs/modules/xcode/xcode.qbs b/share/qbs/modules/xcode/xcode.qbs index 941b8d395..2c0cd001a 100644 --- a/share/qbs/modules/xcode/xcode.qbs +++ b/share/qbs/modules/xcode/xcode.qbs @@ -9,21 +9,19 @@ import qbs.PropertyList import qbs.Utilities Module { - id: xcodeModule - Probes.XcodeLocationProbe { id: xcodeLocationProbe - condition: !xcodeModule.developerPath + condition: !developerPath } Probes.XcodeProbe { id: xcodeProbe - developerPath: xcodeModule.developerPath - platformType: xcodeModule.platformType - platformPath: xcodeModule.platformPath - devicePlatformPath: xcodeModule.devicePlatformPath - xcodebuildPath: xcodeModule.xcodebuildPath - sdksPath: xcodeModule.sdksPath + developerPath: parent.developerPath + platformType: parent.platformType + platformPath: parent.platformPath + devicePlatformPath: parent.devicePlatformPath + xcodebuildPath: parent.xcodebuildPath + sdksPath: parent.sdksPath } condition: qbs.targetOS.includes("darwin") && @@ -134,6 +132,7 @@ Module { readonly property var _sdkSettings: { if (_availableSdks) { + // see 'sdk' property doc to understand why this loop is needed for (var i in _availableSdks) { if (_availableSdks[i]["Version"] === sdk) return _availableSdks[i]; @@ -141,7 +140,7 @@ Module { return _availableSdks[i]; } - // Latest SDK available for the platform + // Latest SDK available for the platform (default case) if (DarwinTools.applePlatformName(qbs.targetOS, platformType) === sdk) return _latestSdk; } |