diff options
author | Ivan Komissarov <ABBAPOH@gmail.com> | 2019-03-19 22:24:33 +0100 |
---|---|---|
committer | Ivan Komissarov <ABBAPOH@gmail.com> | 2019-04-10 07:27:02 +0000 |
commit | 62e07306481373d9d9b6b656d855b204aa6964f3 (patch) | |
tree | dac1f681be32eaba98b117a481a9011500af9b91 /share/qbs/modules | |
parent | 14324ad4aa9582e07dc687dc63b1b886f2d272e5 (diff) |
Add support for the clang-cl compiler
Task-number: QBS-1316
Change-Id: Ibf9da364610c260ead088a8990a70c7739d53c39
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
Diffstat (limited to 'share/qbs/modules')
-rw-r--r-- | share/qbs/modules/cpp/CppModule.qbs | 72 | ||||
-rw-r--r-- | share/qbs/modules/cpp/msvc.js | 28 | ||||
-rw-r--r-- | share/qbs/modules/cpp/windows-clang-cl.qbs | 84 | ||||
-rw-r--r-- | share/qbs/modules/cpp/windows-msvc-base.qbs | 372 | ||||
-rw-r--r-- | share/qbs/modules/cpp/windows-msvc.qbs | 344 |
5 files changed, 523 insertions, 377 deletions
diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs index 01b0f8af9..35a5de4f0 100644 --- a/share/qbs/modules/cpp/CppModule.qbs +++ b/share/qbs/modules/cpp/CppModule.qbs @@ -454,42 +454,48 @@ Module { fileTags: ["hpp"] } - validate: { - var validator = new ModUtils.PropertyValidator("cpp"); - validator.setRequiredProperty("architecture", architecture, - "you might want to re-run 'qbs-setup-toolchains'"); - validator.addCustomValidator("architecture", architecture, function (value) { - return !architecture || architecture === Utilities.canonicalArchitecture(architecture); - }, "'" + architecture + "' is invalid. You must use the canonical name '" + - Utilities.canonicalArchitecture(architecture) + "'"); - validator.setRequiredProperty("endianness", endianness); - validator.setRequiredProperty("compilerDefinesByLanguage", compilerDefinesByLanguage); - validator.setRequiredProperty("compilerVersion", compilerVersion); - validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); - validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); - validator.setRequiredProperty("compilerVersionPatch", compilerVersionPatch); - validator.addVersionValidator("compilerVersion", compilerVersion, 3, 3); - validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); - validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); - validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); - if (minimumWindowsVersion) { - validator.addVersionValidator("minimumWindowsVersion", minimumWindowsVersion, 2, 2); - validator.addCustomValidator("minimumWindowsVersion", minimumWindowsVersion, function (v) { - return !v || v === WindowsUtils.canonicalizeVersion(v); - }, "'" + minimumWindowsVersion + "' is invalid. Did you mean '" + - WindowsUtils.canonicalizeVersion(minimumWindowsVersion) + "'?"); - } - validator.validate(); - - if (minimumWindowsVersion && !WindowsUtils.isValidWindowsVersion(minimumWindowsVersion)) { - console.warn("Unknown Windows version '" + minimumWindowsVersion - + "'; expected one of: " - + WindowsUtils.knownWindowsVersions().map(function (a) { - return '"' + a + '"'; }).join(", ") - + ". See https://docs.microsoft.com/en-us/windows/desktop/SysInfo/operating-system-version"); + property var validateFunc: { + return function() { + var validator = new ModUtils.PropertyValidator("cpp"); + validator.setRequiredProperty("architecture", architecture, + "you might want to re-run 'qbs-setup-toolchains'"); + validator.addCustomValidator("architecture", architecture, function (value) { + return !architecture || architecture === Utilities.canonicalArchitecture(architecture); + }, "'" + architecture + "' is invalid. You must use the canonical name '" + + Utilities.canonicalArchitecture(architecture) + "'"); + validator.setRequiredProperty("endianness", endianness); + validator.setRequiredProperty("compilerDefinesByLanguage", compilerDefinesByLanguage); + validator.setRequiredProperty("compilerVersion", compilerVersion); + validator.setRequiredProperty("compilerVersionMajor", compilerVersionMajor); + validator.setRequiredProperty("compilerVersionMinor", compilerVersionMinor); + validator.setRequiredProperty("compilerVersionPatch", compilerVersionPatch); + validator.addVersionValidator("compilerVersion", compilerVersion, 3, 3); + validator.addRangeValidator("compilerVersionMajor", compilerVersionMajor, 1); + validator.addRangeValidator("compilerVersionMinor", compilerVersionMinor, 0); + validator.addRangeValidator("compilerVersionPatch", compilerVersionPatch, 0); + if (minimumWindowsVersion) { + validator.addVersionValidator("minimumWindowsVersion", minimumWindowsVersion, 2, 2); + validator.addCustomValidator("minimumWindowsVersion", minimumWindowsVersion, function (v) { + return !v || v === WindowsUtils.canonicalizeVersion(v); + }, "'" + minimumWindowsVersion + "' is invalid. Did you mean '" + + WindowsUtils.canonicalizeVersion(minimumWindowsVersion) + "'?"); + } + validator.validate(); + + if (minimumWindowsVersion && !WindowsUtils.isValidWindowsVersion(minimumWindowsVersion)) { + console.warn("Unknown Windows version '" + minimumWindowsVersion + + "'; expected one of: " + + WindowsUtils.knownWindowsVersions().map(function (a) { + return '"' + a + '"'; }).join(", ") + + ". See https://docs.microsoft.com/en-us/windows/desktop/SysInfo/operating-system-version"); + } } } + validate: { + return validateFunc(); + } + setupRunEnvironment: { SetupRunEnv.setupRunEnvironment(product, config); } diff --git a/share/qbs/modules/cpp/msvc.js b/share/qbs/modules/cpp/msvc.js index 1864c40e1..5da2ad0cf 100644 --- a/share/qbs/modules/cpp/msvc.js +++ b/share/qbs/modules/cpp/msvc.js @@ -62,7 +62,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; + return Utilities.versionCompare(input.cpp.compilerVersion, "19.12.25831") >= 0 + || (input.qbs.toolchain.contains("clang-cl") && input.cpp.compilerVersionMajor >= 7); } function addLanguageVersionFlag(input, args) { @@ -72,7 +73,9 @@ function addLanguageVersionFlag(input, args) { return; // Visual C++ 2013, Update 3 - var hasStdOption = Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0; + var hasStdOption = Utilities.versionCompare(input.cpp.compilerVersion, "18.00.30723") >= 0 + // or clang-cl + || input.qbs.toolchain.contains("clang-cl"); if (!hasStdOption) return; @@ -210,10 +213,20 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli var pchInputs = explicitlyDependsOn[tag + "_pch"]; if (pchOutput) { // create PCH - args.push("/Yc"); - args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); - args.push("/Fo" + FileInfo.toWindowsSeparators(objOutput.filePath)); - args.push(FileInfo.toWindowsSeparators(input.filePath)); + if (input.qbs.toolchain.contains("clang-cl")) { + // clang-cl does not support /Yc flag without filename + args.push("/Yc" + FileInfo.toWindowsSeparators(input.filePath)); + // clang-cl complains when pch file is not included + args.push("/FI" + FileInfo.toWindowsSeparators(input.filePath)); + args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); + args.push("/Fo" + FileInfo.toWindowsSeparators(objOutput.filePath)); + } else { // real msvc + args.push("/Yc"); + args.push("/Fp" + FileInfo.toWindowsSeparators(pchOutput.filePath)); + args.push("/Fo" + FileInfo.toWindowsSeparators(objOutput.filePath)); + args.push(FileInfo.toWindowsSeparators(input.filePath)); + } + } else if (pchInputs && pchInputs.length === 1 && ModUtils.moduleProperty(input, "usePrecompiledHeader", tag)) { // use PCH @@ -399,7 +412,8 @@ function prepareLinker(project, product, inputs, outputs, input, output) { 'subsystem'); if (subsystemVersion) { subsystemSwitch += ',' + subsystemVersion; - args.push('/OSVERSION:' + subsystemVersion); + if (product.cpp.linkerName !== "lld-link.exe") // llvm linker does not support /OSVERSION + args.push('/OSVERSION:' + subsystemVersion); } } diff --git a/share/qbs/modules/cpp/windows-clang-cl.qbs b/share/qbs/modules/cpp/windows-clang-cl.qbs new file mode 100644 index 000000000..1b2833060 --- /dev/null +++ b/share/qbs/modules/cpp/windows-clang-cl.qbs @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2019 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.ModUtils +import qbs.Probes +import qbs.FileInfo +import 'windows-msvc-base.qbs' as MsvcBaseModule + +MsvcBaseModule { + condition: qbs.hostOS.contains('windows') && + qbs.targetOS.contains('windows') && + qbs.toolchain && qbs.toolchain.contains('clang-cl') + priority: 100 + + Probes.BinaryProbe { + id: clangPathProbe + condition: !toolchainInstallPath && !_skipAllChecks + names: ["clang-cl"] + } + + Probes.ClangClProbe { + id: clangClProbe + condition: !_skipAllChecks + compilerFilePath: compilerPath + vcvarsallFilePath: vcvarsallPath + enableDefinesByLanguage: enableCompilerDefinesByLanguage + architecture: qbs.architecture + } + + compilerVersionMajor: clangClProbe.versionMajor + compilerVersionMinor: clangClProbe.versionMinor + compilerVersionPatch: clangClProbe.versionPatch + compilerIncludePaths: clangClProbe.includePaths + compilerDefinesByLanguage: clangClProbe.compilerDefinesByLanguage + + toolchainInstallPath: clangPathProbe.found ? clangPathProbe.path + : undefined + buildEnv: clangClProbe.buildEnv + + property string vcvarsallPath + + compilerName: "clang-cl.exe" + linkerName: "lld-link.exe" + linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) + + validateFunc: { + return function() { + if (_skipAllChecks) + return; + var validator = new ModUtils.PropertyValidator("cpp"); + validator.setRequiredProperty("vcvarsallPath", vcvarsallPath); + validator.validate(); + base(); + } + } +} diff --git a/share/qbs/modules/cpp/windows-msvc-base.qbs b/share/qbs/modules/cpp/windows-msvc-base.qbs new file mode 100644 index 000000000..d36daa99f --- /dev/null +++ b/share/qbs/modules/cpp/windows-msvc-base.qbs @@ -0,0 +1,372 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** 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.File +import qbs.FileInfo +import qbs.ModUtils +import qbs.PathTools +import qbs.Probes +import qbs.Utilities +import qbs.WindowsUtils +import 'msvc.js' as MSVC + +CppModule { + condition: false + + windowsApiCharacterSet: "unicode" + platformDefines: { + var defines = base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) + .concat("WIN32"); + var def = WindowsUtils.winapiFamilyDefine(windowsApiFamily); + if (def) + defines.push("WINAPI_FAMILY=WINAPI_FAMILY_" + def); + (windowsApiAdditionalPartitions || []).map(function (name) { + defines.push("WINAPI_PARTITION_" + WindowsUtils.winapiPartitionDefine(name) + "=1"); + }); + return defines; + } + platformCommonCompilerFlags: { + var flags = base; + if (compilerVersionMajor >= 18) // 2013 + flags.push("/FS"); + return flags; + } + warningLevel: "default" + compilerName: "cl.exe" + compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) + assemblerName: { + switch (qbs.architecture) { + case "armv7": + return "armasm.exe"; + case "arm64": + return "armasm64.exe"; + case "ia64": + return "ias.exe"; + case "x86": + return "ml.exe"; + case "x86_64": + return "ml64.exe"; + } + } + + linkerName: "link.exe" + runtimeLibrary: "dynamic" + separateDebugInformation: true + + property bool generateManifestFile: true + property string toolchainInstallPath + + architecture: qbs.architecture + endianness: "little" + staticLibrarySuffix: ".lib" + dynamicLibrarySuffix: ".dll" + executableSuffix: ".exe" + debugInfoSuffix: ".pdb" + imageFormat: "pe" + Properties { + condition: product.multiplexByQbsProperties.contains("buildVariants") + && qbs.buildVariants && qbs.buildVariants.length > 1 + && qbs.buildVariant !== "release" + && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) + variantSuffix: "d" + } + + property var buildEnv + + setupBuildEnvironment: { + for (var key in product.cpp.buildEnv) { + var v = new ModUtils.EnvironmentVariable(key, ';'); + v.prepend(product.cpp.buildEnv[key]); + v.set(); + } + } + + Rule { + condition: useCPrecompiledHeader + inputs: ["c_pch_src"] + auxiliaryInputs: ["hpp"] + Artifact { + fileTags: ['obj'] + filePath: Utilities.getHash(input.completeBaseName) + '_c.obj' + } + Artifact { + fileTags: ['c_pch'] + filePath: product.name + '_c.pch' + } + prepare: { + return MSVC.prepareCompiler.apply(MSVC, arguments); + } + } + + Rule { + condition: useCxxPrecompiledHeader + inputs: ["cpp_pch_src"] + explicitlyDependsOn: ["c_pch"] // to prevent vc--0.pdb conflict + auxiliaryInputs: ["hpp"] + Artifact { + fileTags: ['obj'] + filePath: Utilities.getHash(input.completeBaseName) + '_cpp.obj' + } + Artifact { + fileTags: ['cpp_pch'] + filePath: product.name + '_cpp.pch' + } + prepare: { + return MSVC.prepareCompiler.apply(MSVC, arguments); + } + } + + Rule { + name: "compiler" + inputs: ["cpp", "c"] + auxiliaryInputs: ["hpp"] + explicitlyDependsOn: ["c_pch", "cpp_pch"] + + outputFileTags: ["obj", "intermediate_obj"] + outputArtifacts: { + var tags = input.fileTags.contains("cpp_intermediate_object") + ? ["intermediate_obj"] + : ["obj"]; + return [{ + fileTags: tags, + filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".obj" + }]; + } + + prepare: { + return MSVC.prepareCompiler.apply(MSVC, arguments); + } + } + + FileTagger { + patterns: ["*.manifest"] + fileTags: ["native.pe.manifest"] + } + + Rule { + name: "applicationLinker" + multiplex: true + inputs: ['obj', 'native.pe.manifest'] + inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"] + + outputFileTags: ["application", "debuginfo_app"] + outputArtifacts: { + var app = { + fileTags: ["application"], + filePath: FileInfo.joinPaths( + product.destinationDirectory, + PathTools.applicationFilePath(product)) + }; + var artifacts = [app]; + if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { + artifacts.push({ + fileTags: ["debuginfo_app"], + filePath: app.filePath.substr(0, app.filePath.length - 4) + + product.cpp.debugInfoSuffix + }); + } + return artifacts; + } + + prepare: { + return MSVC.prepareLinker.apply(MSVC, arguments); + } + } + + Rule { + name: "dynamicLibraryLinker" + multiplex: true + inputs: ['obj', 'native.pe.manifest'] + inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"] + + outputFileTags: ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"] + outputArtifacts: { + var artifacts = [ + { + fileTags: ["dynamiclibrary"], + filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product) + }, + { + fileTags: ["dynamiclibrary_import"], + filePath: product.destinationDirectory + "/" + PathTools.importLibraryFilePath(product), + alwaysUpdated: false + } + ]; + if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { + var lib = artifacts[0]; + artifacts.push({ + fileTags: ["debuginfo_dll"], + filePath: lib.filePath.substr(0, lib.filePath.length - 4) + + product.cpp.debugInfoSuffix + }); + } + return artifacts; + } + + prepare: { + return MSVC.prepareLinker.apply(MSVC, arguments); + } + } + + Rule { + name: "libtool" + multiplex: true + inputs: ["obj"] + inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"] + outputFileTags: ["staticlibrary", "debuginfo_cl"] + outputArtifacts: { + var artifacts = [ + { + fileTags: ["staticlibrary"], + filePath: FileInfo.joinPaths(product.destinationDirectory, + PathTools.staticLibraryFilePath(product)) + } + ]; + if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { + artifacts.push({ + fileTags: ["debuginfo_cl"], + filePath: product.targetName + ".cl" + product.cpp.debugInfoSuffix + }); + } + return artifacts; + } + prepare: { + var args = ['/nologo'] + var lib = outputs["staticlibrary"][0]; + var nativeOutputFileName = FileInfo.toWindowsSeparators(lib.filePath) + args.push('/OUT:' + nativeOutputFileName) + for (var i in inputs.obj) { + var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].filePath) + args.push(fileName) + } + var cmd = new Command("lib.exe", args); + cmd.description = 'creating ' + lib.fileName; + cmd.highlight = 'linker'; + cmd.jobPool = "linker"; + cmd.workingDirectory = FileInfo.path(lib.filePath) + cmd.responseFileUsagePrefix = '@'; + return cmd; + } + } + + FileTagger { + patterns: ["*.rc"] + fileTags: ["rc"] + } + + Rule { + inputs: ["rc"] + auxiliaryInputs: ["hpp"] + + Artifact { + filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".res" + fileTags: ["obj"] + } + + prepare: { + var platformDefines = input.cpp.platformDefines; + var defines = input.cpp.defines; + var includePaths = input.cpp.includePaths; + var systemIncludePaths = input.cpp.systemIncludePaths; + var args = []; + var i; + var hasNoLogo = product.cpp.compilerVersionMajor >= 16; // 2010 + if (hasNoLogo) + args.push("/nologo"); + + for (i in platformDefines) { + args.push('/d'); + args.push(platformDefines[i]); + } + for (i in defines) { + args.push('/d'); + args.push(defines[i]); + } + for (i in includePaths) { + args.push('/i'); + args.push(includePaths[i]); + } + for (i in systemIncludePaths) { + args.push('/i'); + args.push(systemIncludePaths[i]); + } + + args = args.concat(['/fo', output.filePath, input.filePath]); + var cmd = new Command('rc', args); + cmd.description = 'compiling ' + input.fileName; + cmd.highlight = 'compiler'; + cmd.jobPool = "compiler"; + + if (!hasNoLogo) { + // Remove the first two lines of stdout. That's the logo. + cmd.stdoutFilterFunction = function(output) { + var idx = 0; + for (var i = 0; i < 3; ++i) + idx = output.indexOf('\n', idx + 1); + return output.substr(idx + 1); + } + } + + return cmd; + } + } + + FileTagger { + patterns: "*.asm" + fileTags: ["asm"] + } + + Rule { + inputs: ["asm"] + Artifact { + filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".obj" + fileTags: ["obj"] + } + prepare: { + var args = ["/nologo", "/c", + "/Fo" + FileInfo.toWindowsSeparators(output.filePath), + FileInfo.toWindowsSeparators(input.filePath)]; + if (product.cpp.debugInformation) + args.push("/Zi"); + args = args.concat(ModUtils.moduleProperty(input, 'platformFlags', 'asm'), + ModUtils.moduleProperty(input, 'flags', 'asm')); + var cmd = new Command(product.cpp.assemblerPath, args); + cmd.description = "assembling " + input.fileName; + cmd.jobPool = "assembler"; + cmd.inputFileName = input.fileName; + cmd.stdoutFilterFunction = function(output) { + var lines = output.split("\r\n").filter(function (s) { + return !s.endsWith(inputFileName); }); + return lines.join("\r\n"); + }; + return cmd; + } + } +} diff --git a/share/qbs/modules/cpp/windows-msvc.qbs b/share/qbs/modules/cpp/windows-msvc.qbs index 8dd6dd2c0..59032d28a 100644 --- a/share/qbs/modules/cpp/windows-msvc.qbs +++ b/share/qbs/modules/cpp/windows-msvc.qbs @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2019 Ivan Komissarov (abbapoh@gmail.com) ** Contact: http://www.qt.io/licensing ** ** This file is part of Qbs. @@ -28,19 +29,14 @@ ** ****************************************************************************/ -import qbs.File -import qbs.FileInfo -import qbs.ModUtils -import qbs.PathTools import qbs.Probes -import qbs.Utilities -import qbs.WindowsUtils -import 'msvc.js' as MSVC +import "windows-msvc-base.qbs" as MsvcBaseModule -CppModule { +MsvcBaseModule { condition: qbs.hostOS.contains('windows') && qbs.targetOS.contains('windows') && qbs.toolchain && qbs.toolchain.contains('msvc') + priority: 50 Probes.BinaryProbe { id: compilerPathProbe @@ -62,335 +58,9 @@ CppModule { compilerVersionMinor: msvcProbe.versionMinor compilerVersionPatch: msvcProbe.versionPatch compilerIncludePaths: msvcProbe.includePaths - - windowsApiCharacterSet: "unicode" - platformDefines: { - var defines = base.concat(WindowsUtils.characterSetDefines(windowsApiCharacterSet)) - .concat("WIN32"); - var def = WindowsUtils.winapiFamilyDefine(windowsApiFamily); - if (def) - defines.push("WINAPI_FAMILY=WINAPI_FAMILY_" + def); - (windowsApiAdditionalPartitions || []).map(function (name) { - defines.push("WINAPI_PARTITION_" + WindowsUtils.winapiPartitionDefine(name) + "=1"); - }); - return defines; - } - platformCommonCompilerFlags: { - var flags = base; - if (compilerVersionMajor >= 18) // 2013 - flags.push("/FS"); - return flags; - } compilerDefinesByLanguage: msvcProbe.compilerDefinesByLanguage - warningLevel: "default" - compilerName: "cl.exe" - compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) - assemblerName: { - switch (qbs.architecture) { - case "armv7": - return "armasm.exe"; - case "arm64": - return "armasm64.exe"; - case "ia64": - return "ias.exe"; - case "x86": - return "ml.exe"; - case "x86_64": - return "ml64.exe"; - } - } - - linkerName: "link.exe" - runtimeLibrary: "dynamic" - separateDebugInformation: true - - property bool generateManifestFile: true - property string toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path - : undefined - architecture: qbs.architecture - endianness: "little" - staticLibrarySuffix: ".lib" - dynamicLibrarySuffix: ".dll" - executableSuffix: ".exe" - debugInfoSuffix: ".pdb" - imageFormat: "pe" - Properties { - condition: product.multiplexByQbsProperties.contains("buildVariants") - && qbs.buildVariants && qbs.buildVariants.length > 1 - && qbs.buildVariant !== "release" - && product.type.containsAny(["staticlibrary", "dynamiclibrary"]) - variantSuffix: "d" - } - - property var buildEnv: msvcProbe.buildEnv - - setupBuildEnvironment: { - for (var key in product.cpp.buildEnv) { - var v = new ModUtils.EnvironmentVariable(key, ';'); - v.prepend(product.cpp.buildEnv[key]); - v.set(); - } - } - - Rule { - condition: useCPrecompiledHeader - inputs: ["c_pch_src"] - auxiliaryInputs: ["hpp"] - Artifact { - fileTags: ['obj'] - filePath: Utilities.getHash(input.completeBaseName) + '_c.obj' - } - Artifact { - fileTags: ['c_pch'] - filePath: product.name + '_c.pch' - } - prepare: { - return MSVC.prepareCompiler.apply(MSVC, arguments); - } - } - - Rule { - condition: useCxxPrecompiledHeader - inputs: ["cpp_pch_src"] - explicitlyDependsOn: ["c_pch"] // to prevent vc--0.pdb conflict - auxiliaryInputs: ["hpp"] - Artifact { - fileTags: ['obj'] - filePath: Utilities.getHash(input.completeBaseName) + '_cpp.obj' - } - Artifact { - fileTags: ['cpp_pch'] - filePath: product.name + '_cpp.pch' - } - prepare: { - return MSVC.prepareCompiler.apply(MSVC, arguments); - } - } - - Rule { - name: "compiler" - inputs: ["cpp", "c"] - auxiliaryInputs: ["hpp"] - explicitlyDependsOn: ["c_pch", "cpp_pch"] - - outputFileTags: ["obj", "intermediate_obj"] - outputArtifacts: { - var tags = input.fileTags.contains("cpp_intermediate_object") - ? ["intermediate_obj"] - : ["obj"]; - return [{ - fileTags: tags, - filePath: Utilities.getHash(input.baseDir) + "/" + input.fileName + ".obj" - }]; - } - - prepare: { - return MSVC.prepareCompiler.apply(MSVC, arguments); - } - } - - FileTagger { - patterns: ["*.manifest"] - fileTags: ["native.pe.manifest"] - } - - Rule { - name: "applicationLinker" - multiplex: true - inputs: ['obj', 'native.pe.manifest'] - inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_app"] - - outputFileTags: ["application", "debuginfo_app"] - outputArtifacts: { - var app = { - fileTags: ["application"], - filePath: FileInfo.joinPaths( - product.destinationDirectory, - PathTools.applicationFilePath(product)) - }; - var artifacts = [app]; - if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { - artifacts.push({ - fileTags: ["debuginfo_app"], - filePath: app.filePath.substr(0, app.filePath.length - 4) - + product.cpp.debugInfoSuffix - }); - } - return artifacts; - } - prepare: { - return MSVC.prepareLinker.apply(MSVC, arguments); - } - } - - Rule { - name: "dynamicLibraryLinker" - multiplex: true - inputs: ['obj', 'native.pe.manifest'] - inputsFromDependencies: ['staticlibrary', 'dynamiclibrary_import', "debuginfo_dll"] - - outputFileTags: ["dynamiclibrary", "dynamiclibrary_import", "debuginfo_dll"] - outputArtifacts: { - var artifacts = [ - { - fileTags: ["dynamiclibrary"], - filePath: product.destinationDirectory + "/" + PathTools.dynamicLibraryFilePath(product) - }, - { - fileTags: ["dynamiclibrary_import"], - filePath: product.destinationDirectory + "/" + PathTools.importLibraryFilePath(product), - alwaysUpdated: false - } - ]; - if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { - var lib = artifacts[0]; - artifacts.push({ - fileTags: ["debuginfo_dll"], - filePath: lib.filePath.substr(0, lib.filePath.length - 4) - + product.cpp.debugInfoSuffix - }); - } - return artifacts; - } - - prepare: { - return MSVC.prepareLinker.apply(MSVC, arguments); - } - } - - Rule { - name: "libtool" - multiplex: true - inputs: ["obj"] - inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"] - outputFileTags: ["staticlibrary", "debuginfo_cl"] - outputArtifacts: { - var artifacts = [ - { - fileTags: ["staticlibrary"], - filePath: FileInfo.joinPaths(product.destinationDirectory, - PathTools.staticLibraryFilePath(product)) - } - ]; - if (product.cpp.debugInformation && product.cpp.separateDebugInformation) { - artifacts.push({ - fileTags: ["debuginfo_cl"], - filePath: product.targetName + ".cl" + product.cpp.debugInfoSuffix - }); - } - return artifacts; - } - prepare: { - var args = ['/nologo'] - var lib = outputs["staticlibrary"][0]; - var nativeOutputFileName = FileInfo.toWindowsSeparators(lib.filePath) - args.push('/OUT:' + nativeOutputFileName) - for (var i in inputs.obj) { - var fileName = FileInfo.toWindowsSeparators(inputs.obj[i].filePath) - args.push(fileName) - } - var cmd = new Command("lib.exe", args); - cmd.description = 'creating ' + lib.fileName; - cmd.highlight = 'linker'; - cmd.jobPool = "linker"; - cmd.workingDirectory = FileInfo.path(lib.filePath) - cmd.responseFileUsagePrefix = '@'; - return cmd; - } - } - - FileTagger { - patterns: ["*.rc"] - fileTags: ["rc"] - } - - Rule { - inputs: ["rc"] - auxiliaryInputs: ["hpp"] - - Artifact { - filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".res" - fileTags: ["obj"] - } - - prepare: { - var platformDefines = input.cpp.platformDefines; - var defines = input.cpp.defines; - var includePaths = input.cpp.includePaths; - var systemIncludePaths = input.cpp.systemIncludePaths; - var args = []; - var i; - var hasNoLogo = product.cpp.compilerVersionMajor >= 16; // 2010 - if (hasNoLogo) - args.push("/nologo"); - - for (i in platformDefines) { - args.push('/d'); - args.push(platformDefines[i]); - } - for (i in defines) { - args.push('/d'); - args.push(defines[i]); - } - for (i in includePaths) { - args.push('/i'); - args.push(includePaths[i]); - } - for (i in systemIncludePaths) { - args.push('/i'); - args.push(systemIncludePaths[i]); - } - - args = args.concat(['/fo', output.filePath, input.filePath]); - var cmd = new Command('rc', args); - cmd.description = 'compiling ' + input.fileName; - cmd.highlight = 'compiler'; - cmd.jobPool = "compiler"; - - if (!hasNoLogo) { - // Remove the first two lines of stdout. That's the logo. - cmd.stdoutFilterFunction = function(output) { - var idx = 0; - for (var i = 0; i < 3; ++i) - idx = output.indexOf('\n', idx + 1); - return output.substr(idx + 1); - } - } - - return cmd; - } - } - - FileTagger { - patterns: "*.asm" - fileTags: ["asm"] - } - - Rule { - inputs: ["asm"] - Artifact { - filePath: Utilities.getHash(input.baseDir) + "/" + input.completeBaseName + ".obj" - fileTags: ["obj"] - } - prepare: { - var args = ["/nologo", "/c", - "/Fo" + FileInfo.toWindowsSeparators(output.filePath), - FileInfo.toWindowsSeparators(input.filePath)]; - if (product.cpp.debugInformation) - args.push("/Zi"); - args = args.concat(ModUtils.moduleProperty(input, 'platformFlags', 'asm'), - ModUtils.moduleProperty(input, 'flags', 'asm')); - var cmd = new Command(product.cpp.assemblerPath, args); - cmd.description = "assembling " + input.fileName; - cmd.jobPool = "assembler"; - cmd.inputFileName = input.fileName; - cmd.stdoutFilterFunction = function(output) { - var lines = output.split("\r\n").filter(function (s) { - return !s.endsWith(inputFileName); }); - return lines.join("\r\n"); - }; - return cmd; - } - } + toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path + : undefined + buildEnv: msvcProbe.buildEnv } |