summaryrefslogtreecommitdiff
path: root/share/qbs/modules/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'share/qbs/modules/cpp')
-rw-r--r--share/qbs/modules/cpp/CppModule.qbs1
-rw-r--r--share/qbs/modules/cpp/cpp.js105
-rw-r--r--share/qbs/modules/cpp/dmc.js462
-rw-r--r--share/qbs/modules/cpp/dmc.qbs177
4 files changed, 725 insertions, 20 deletions
diff --git a/share/qbs/modules/cpp/CppModule.qbs b/share/qbs/modules/cpp/CppModule.qbs
index 17c8c6bfc..0a959ea8e 100644
--- a/share/qbs/modules/cpp/CppModule.qbs
+++ b/share/qbs/modules/cpp/CppModule.qbs
@@ -190,6 +190,7 @@ Module {
property string linkerMapSuffix: ".map"
property string compilerListingSuffix: ".lst"
property string assemblerListingSuffix: ".lst"
+ property string resourceSuffix: ".res"
property bool createSymlinks: true
property stringList dynamicLibraries // list of names, will be linked with -lname
property stringList staticLibraries // list of static library files
diff --git a/share/qbs/modules/cpp/cpp.js b/share/qbs/modules/cpp/cpp.js
index 1e153e8ba..9563a5c84 100644
--- a/share/qbs/modules/cpp/cpp.js
+++ b/share/qbs/modules/cpp/cpp.js
@@ -28,6 +28,7 @@
**
****************************************************************************/
+var File = require("qbs.File");
var FileInfo = require("qbs.FileInfo");
var ModUtils = require("qbs.ModUtils");
var PathTools = require("qbs.PathTools");
@@ -63,6 +64,12 @@ function extractMacros(output) {
return m;
}
+function relativePath(baseDirectory, filePath) {
+ if (FileInfo.isAbsolutePath(filePath))
+ return FileInfo.relativePath(baseDirectory, filePath);
+ return filePath;
+}
+
function assemblerOutputTags(needsListingFiles) {
var tags = ["obj"];
if (needsListingFiles)
@@ -84,10 +91,18 @@ function applicationLinkerOutputTags(needsLinkerMapFile) {
return tags;
}
+function dynamicLibraryLinkerOutputTags() {
+ return ["dynamiclibrary", "dynamiclibrary_import"];
+}
+
function staticLibraryLinkerOutputTags() {
return ["staticlibrary"];
}
+function resourceCompilerOutputTags() {
+ return ["res"];
+}
+
function assemblerOutputArtifacts(input) {
var artifacts = [];
artifacts.push({
@@ -140,32 +155,57 @@ function applicationLinkerOutputArtifacts(product) {
return artifacts;
}
+function dynamicLibraryLinkerOutputArtifacts(product) {
+ return [{
+ fileTags: ["dynamiclibrary"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.dynamicLibraryFilePath(product))
+ }, {
+ fileTags: ["dynamiclibrary_import"],
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.importLibraryFilePath(product)),
+ alwaysUpdated: false
+ }];
+}
+
function staticLibraryLinkerOutputArtifacts(product) {
- var staticLib = {
+ return [{
fileTags: ["staticlibrary"],
- filePath: FileInfo.joinPaths(
- product.destinationDirectory,
- PathTools.staticLibraryFilePath(product))
- };
- return [staticLib]
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ PathTools.staticLibraryFilePath(product))
+ }];
+}
+
+function resourceCompilerOutputArtifacts(input) {
+ return [{
+ fileTags: ["res"],
+ filePath: FileInfo.joinPaths(Utilities.getHash(input.baseDir),
+ input.completeBaseName + input.cpp.resourceSuffix)
+ }];
}
function collectLibraryDependencies(product) {
var seen = {};
var result = [];
- function addFilePath(filePath) {
- result.push({ filePath: filePath });
+ function addFilePath(filePath, wholeArchive, productName) {
+ result.push({ filePath: filePath, wholeArchive: wholeArchive, productName: productName });
}
function addArtifactFilePaths(dep, artifacts) {
if (!artifacts)
return;
var artifactFilePaths = artifacts.map(function(a) { return a.filePath; });
- artifactFilePaths.forEach(addFilePath);
+ var wholeArchive = dep.parameters.cpp && dep.parameters.cpp.linkWholeArchive;
+ var artifactsAreImportLibs = artifacts.length > 0
+ && artifacts[0].fileTags.contains("dynamiclibrary_import");
+ for (var i = 0; i < artifactFilePaths.length; ++i) {
+ addFilePath(artifactFilePaths[i], wholeArchive,
+ artifactsAreImportLibs ? dep.name : undefined);
+ }
}
- function addExternalStaticLibs(obj) {
+ function addExternalLibs(obj) {
if (!obj.cpp)
return;
function ensureArray(a) {
@@ -175,36 +215,57 @@ function collectLibraryDependencies(product) {
return ensureArray(ModUtils.sanitizedModuleProperty(obj, moduleName, propertyName));
}
var externalLibs = [].concat(
- sanitizedModuleListProperty(obj, "cpp", "staticLibraries"));
- var staticLibrarySuffix = obj.moduleProperty("cpp", "staticLibrarySuffix");
- externalLibs.forEach(function(staticLibraryName) {
- if (!staticLibraryName.endsWith(staticLibrarySuffix))
- staticLibraryName += staticLibrarySuffix;
- addFilePath(staticLibraryName);
+ sanitizedModuleListProperty(obj, "cpp", "staticLibraries"),
+ sanitizedModuleListProperty(obj, "cpp", "dynamicLibraries"));
+ var libSuffix = obj.moduleProperty("cpp", "staticLibrarySuffix");
+ externalLibs.forEach(function(libName) {
+ if (!libName.endsWith(libSuffix) && !libName.startsWith('@'))
+ libName += libSuffix;
+ addFilePath(libName);
});
}
function traverse(dep) {
if (seen.hasOwnProperty(dep.name))
return;
- seen[dep.name] = true;
-
if (dep.parameters.cpp && dep.parameters.cpp.link === false)
return;
var staticLibraryArtifacts = dep.artifacts["staticlibrary"];
+ var dynamicLibraryArtifacts = staticLibraryArtifacts
+ ? null : dep.artifacts["dynamiclibrary_import"];
if (staticLibraryArtifacts) {
+ seen[dep.name] = true;
dep.dependencies.forEach(traverse);
addArtifactFilePaths(dep, staticLibraryArtifacts);
- addExternalStaticLibs(dep);
+ addExternalLibs(dep);
+ } else if (dynamicLibraryArtifacts) {
+ seen[dep.name] = true;
+ addArtifactFilePaths(dep, dynamicLibraryArtifacts);
}
}
product.dependencies.forEach(traverse);
- addExternalStaticLibs(product);
+ addExternalLibs(product);
return result;
}
+function collectAbsoluteLibraryDependencyPaths(product) {
+ var paths = collectLibraryPaths(product);
+ var deps = collectLibraryDependencies(product);
+ return deps.map(function(dep) {
+ var filePath = dep.filePath;
+ if (FileInfo.isAbsolutePath(filePath))
+ return filePath;
+ for (var i = 0; i < paths.length; ++i) {
+ var fullPath = FileInfo.joinPaths(paths[i], filePath);
+ if (File.exists(fullPath))
+ return fullPath;
+ }
+ return filePath;
+ });
+}
+
function collectDefines(input) {
var allDefines = [];
var platformDefines = input.cpp.platformDefines;
@@ -260,6 +321,10 @@ function collectLinkerObjectPaths(inputs) {
return inputs.obj ? inputs.obj.map(function(obj) { return obj.filePath; }) : [];
}
+function collectResourceObjectPaths(inputs) {
+ return inputs.res ? inputs.res.map(function(res) { return res.filePath; }) : [];
+}
+
function collectLibraryDependenciesArguments(product) {
var deps = collectLibraryDependencies(product);
return deps.map(function(dep) { return product.cpp.libraryDependencyFlag + dep.filePath })
diff --git a/share/qbs/modules/cpp/dmc.js b/share/qbs/modules/cpp/dmc.js
new file mode 100644
index 000000000..7303c67fc
--- /dev/null
+++ b/share/qbs/modules/cpp/dmc.js
@@ -0,0 +1,462 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+var Cpp = require("cpp.js");
+var Environment = require("qbs.Environment");
+var File = require("qbs.File");
+var FileInfo = require("qbs.FileInfo");
+var ModUtils = require("qbs.ModUtils");
+var Process = require("qbs.Process");
+var TemporaryDir = require("qbs.TemporaryDir");
+var TextFile = require("qbs.TextFile");
+var Utilities = require("qbs.Utilities");
+
+function dumpMacros(compilerFilePath, tag) {
+ // Note: The DMC compiler does not support the predefined/ macros dumping. So, we do it
+ // with the following trick, where we try to create and compile a special temporary file
+ // and to parse the console output with the own magic pattern: #define <key> <value>.
+
+ var outputDirectory = new TemporaryDir();
+ var outputFilePath = FileInfo.joinPaths(outputDirectory.path(), "dump-macros.c");
+ var outputFile = new TextFile(outputFilePath, TextFile.WriteOnly);
+ outputFile.writeLine("#define VALUE_TO_STRING(x) #x");
+ outputFile.writeLine("#define VALUE(x) VALUE_TO_STRING(x)");
+ outputFile.writeLine("#define VAR_NAME_VALUE(var) \"#define \" #var\" \"VALUE(var)");
+ // Declare all available pre-defined macros of DMC compiler.
+ var keys = [
+ // Prepare the DOS target macros.
+ "_MSDOS", "MSDOS",
+ // Prepare the OS/2 target macros.
+ "__OS2__",
+ "WIN32", "_WIN32",
+ // Prepare extended the 32 and 16 bit DOS target macros.
+ "DOS386", "DOS16RM",
+ // Prepare the memory model macros.
+ "M_I86", "_M_I86",
+ "_M_I86TM", "M_I86TM",
+ "_M_I86SM", "M_I86SM",
+ "_M_I86MM", "M_I86MM",
+ "_M_I86CM", "M_I86CM",
+ "_M_I86LM", "M_I86LM",
+ "_M_I86VM", "M_I86VM",
+ // Prepare 8086 macros.
+ "_M_I8086", "M_I8086",
+ // Prepare 286 macros.
+ "_M_I286", "M_I286",
+ // Prepare 32 bit macros.
+ "_M_IX86",
+ // Prepare compiler identification macros.
+ "__DMC__", "__DMC_VERSION_STRING__",
+ // Prepare common compiler macros.
+ "_CHAR_UNSIGNED", "_CHAR_EQ_UCHAR", "_DEBUG_TRACE", "_DLL",
+ "_ENABLE_ARRAYNEW", "_BOOL_DEFINED", "_WCHAR_T_DEFINED",
+ "_CPPRTTI", "_CPPUNWIND", "_MD", "_PUSHPOP_SUPPORTED",
+ "_STDCALL_SUPPORTED", "__INTSIZE", "__DEFALIGN", "_INTEGRAL_MAX_BITS",
+ "_WINDOWS", "_WINDLL", "__INLINE_8087", "__I86__", "__SMALL__",
+ "__MEDIUM__", "__COMPACT__", "__LARGE__", "__VCM__", "__FPCE__",
+ "__FPCE__IEEE__", "DEBUG",
+ // Prepare C99 and C++98 macros.
+ "__STDC__", "__STDC_HOSTED__", "__STDC_VERSION__", "__STDC_IEC_559__",
+ "__STDC_IEC_559_COMPLEX__", "__STDC_ISO_10646__", "__cplusplus"
+ ];
+ for (var i = 0; i < keys.length; ++i) {
+ var key = keys[i];
+ outputFile.writeLine("#if defined (" + key + ")");
+ outputFile.writeLine("#pragma message (VAR_NAME_VALUE(" + key + "))");
+ outputFile.writeLine("#endif");
+ }
+ outputFile.close();
+
+ var process = new Process();
+ process.setWorkingDirectory(outputDirectory.path());
+ var args = ["-c"].concat((tag === "cpp") ? ["-cpp"] : [],
+ FileInfo.toWindowsSeparators(outputFilePath));
+ process.exec(compilerFilePath, args, false);
+ File.remove(outputFilePath);
+ var out = process.readStdOut();
+ return Cpp.extractMacros(out);
+}
+
+function dumpDefaultPaths(compilerFilePath, tag) {
+ var binPath = FileInfo.path(compilerFilePath);
+ var rootPath = FileInfo.path(binPath);
+ var includePaths = [];
+ var cppIncludePath = FileInfo.joinPaths(rootPath, "stlport/stlport");
+ if (File.exists(cppIncludePath))
+ includePaths.push(cppIncludePath);
+ var cIncludePath = FileInfo.joinPaths(rootPath, "include");
+ if (File.exists(cIncludePath))
+ includePaths.push(cIncludePath);
+
+ var libraryPaths = [];
+ var libraryPath = FileInfo.joinPaths(rootPath, "lib");
+ if (File.exists(libraryPath))
+ libraryPaths.push(libraryPath);
+
+ return {
+ "includePaths": includePaths,
+ "libraryPaths": libraryPaths,
+ }
+}
+
+function guessVersion(macros) {
+ var version = macros["__DMC__"];
+ return { major: parseInt(version / 100),
+ minor: parseInt(version % 100),
+ patch: 0 };
+}
+
+function effectiveLinkerPath(product) {
+ if (product.cpp.linkerMode === "automatic") {
+ var compilerPath = product.cpp.compilerPath;
+ if (compilerPath)
+ return compilerPath;
+ console.log("Found no C-language objects, choosing system linker for " + product.name);
+ }
+ return product.cpp.linkerPath;
+}
+
+function useCompilerDriverLinker(product) {
+ var linker = effectiveLinkerPath(product);
+ var compilers = product.cpp.compilerPathByLanguage;
+ if (compilers)
+ return linker === compilers["cpp"] || linker === compilers["c"];
+ return linker === product.cpp.compilerPath;
+}
+
+function depsOutputTags() {
+ return ["dep"];
+}
+
+function depsOutputArtifacts(input, product) {
+ return [{
+ fileTags: depsOutputTags(),
+ filePath: FileInfo.joinPaths(product.destinationDirectory,
+ input.baseName + ".dep")
+ }];
+}
+
+function compilerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = ["-c"];
+
+ // Input.
+ args.push(FileInfo.toWindowsSeparators(input.filePath));
+ // Output.
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath));
+ // Preinclude headers.
+ args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) {
+ return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Defines.
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(outputs.obj[0].fileTags));
+ if (tag === "cpp") {
+ // We need to add the paths to the STL includes, because the DMC compiler does
+ // not handle it by default (because the STL libraries is a separate port).
+ var compilerIncludePaths = input.cpp.compilerIncludePaths || [];
+ args = args.concat(compilerIncludePaths.map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ }
+
+ // Other includes.
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Debug information flags.
+ if (input.cpp.debugInformation)
+ args.push("-d");
+
+ // Optimization flags.
+ switch (input.cpp.optimization) {
+ case "small":
+ args.push("-o+space");
+ break;
+ case "fast":
+ args.push("-o+speed");
+ break;
+ case "none":
+ args.push("-o+none");
+ break;
+ }
+
+ // Warning level flags.
+ switch (input.cpp.warningLevel) {
+ case "none":
+ args.push("-w");
+ break;
+ case "all":
+ args.push("-w-");
+ break;
+ }
+ if (input.cpp.treatWarningsAsErrors)
+ args.push("-wx");
+
+ if (tag === "cpp") {
+ args.push("-cpp");
+
+ // Exceptions flag.
+ if (input.cpp.enableExceptions)
+ args.push("-Ae");
+
+ // RTTI flag.
+ var enableRtti = input.cpp.enableRtti;
+ if (input.cpp.enableRtti)
+ args.push("-Ar");
+ }
+
+ // Listing files generation flag.
+ if (input.cpp.generateCompilerListingFiles) {
+ // We need to use the relative path here, because the DMC compiler does not handle
+ // a long file path for this option.
+ var listingPath = Cpp.relativePath(product.buildDirectory, outputs.lst[0].filePath);
+ args.push("-l" + FileInfo.toWindowsSeparators(listingPath));
+ }
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscCompilerArguments(input, tag),
+ Cpp.collectMiscDriverArguments(product));
+ return args;
+}
+
+function assemblerFlags(project, product, input, outputs, explicitlyDependsOn) {
+ var args = ["-c"];
+
+ // Input.
+ args.push(FileInfo.toWindowsSeparators(input.filePath));
+ // Output.
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.obj[0].filePath));
+ // Preinclude headers.
+ args = args.concat(Cpp.collectPreincludePaths(input).map(function(path) {
+ return input.cpp.preincludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Defines.
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ // Other includes.
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscAssemblerArguments(input, "asm"));
+ return args;
+}
+
+function linkerFlags(project, product, inputs, outputs) {
+ var args = [];
+
+ var useCompilerDriver = useCompilerDriverLinker(product);
+ if (useCompilerDriver) {
+ // Input objects.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Input resources.
+ args = args.concat(Cpp.collectResourceObjectPaths(inputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Input libraries.
+ args = args.concat(Cpp.collectAbsoluteLibraryDependencyPaths(product).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+
+ // Output.
+ if (product.type.contains("application")) {
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.application[0].filePath));
+ args.push("-WA");
+ args.push("/SUBSYSTEM:" + (product.consoleApplication ? "CONSOLE" : "WINDOWS"));
+ } else if (product.type.contains("dynamiclibrary")) {
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.dynamiclibrary[0].filePath));
+ args.push("-WD");
+ }
+
+ if (product.cpp.debugInformation)
+ args.push("/DEBUG");
+
+ args.push("/NOLOGO", "/SILENT");
+ }
+
+ // Misc flags.
+ args = args.concat(Cpp.collectMiscEscapableLinkerArguments(product),
+ Cpp.collectMiscLinkerArguments(product),
+ Cpp.collectMiscDriverArguments(product));
+ return args;
+}
+
+function archiverFlags(project, product, inputs, outputs) {
+ var args = ["-c"];
+ // Output.
+ args.push(FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath));
+ // Input objects.
+ args = args.concat(Cpp.collectLinkerObjectPaths(inputs).map(function(path) {
+ return FileInfo.toWindowsSeparators(path);
+ }));
+ return args;
+}
+
+function rccCompilerFlags(project, product, input, outputs) {
+ // Input.
+ var args = [FileInfo.toWindowsSeparators(input.filePath)];
+ // Output.
+ args.push("-o" + FileInfo.toWindowsSeparators(outputs.res[0].filePath));
+ // Bitness.
+ args.push("-32");
+
+ // Defines
+ args = args.concat(Cpp.collectDefinesArguments(input));
+
+ // Other includes.
+ args = args.concat(Cpp.collectIncludePaths(input).map(function(path) {
+ return input.cpp.includeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ args = args.concat(Cpp.collectSystemIncludePaths(input).map(function(path) {
+ return input.cpp.systemIncludeFlag + FileInfo.toWindowsSeparators(path);
+ }));
+ return args;
+}
+
+function buildLinkerMapFilePath(target, suffix) {
+ return FileInfo.joinPaths(FileInfo.path(target.filePath),
+ FileInfo.completeBaseName(target.fileName) + suffix);
+}
+
+// It is a workaround which removes the generated linker map file if it is disabled
+// by cpp.generateLinkerMapFile property. Reason is that the DMC compiler always
+// generates this file, and does not have an option to disable generation for a linker
+// map file. So, we can to remove a listing files only after the linking completes.
+function removeLinkerMapFile(project, product, inputs, outputs, input, output) {
+ var target = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var cmd = new JavaScriptCommand();
+ cmd.mapFilePath = buildLinkerMapFilePath(target, ".map")
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.remove(mapFilePath); };
+ return cmd;
+}
+
+// It is a workaround to rename the extension of the output linker map file to the
+// specified one, since the linker generates only files with the '.map' extension.
+function renameLinkerMapFile(project, product, inputs, outputs, input, output) {
+ var target = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var cmd = new JavaScriptCommand();
+ cmd.newMapFilePath = buildLinkerMapFilePath(target, product.cpp.linkerMapSuffix);
+ cmd.oldMapFilePath = buildLinkerMapFilePath(target, ".map");
+ cmd.silent = true;
+ cmd.sourceCode = function() { File.move(oldMapFilePath, newMapFilePath); };
+ return cmd;
+}
+
+// It is a workaround to generate the import library file from the dynamic library.
+// Because the DMC compiler use the separate `implib.exe` tool for that.
+function createImportLib(project, product, inputs, outputs, input, output) {
+ var args = [
+ FileInfo.toWindowsSeparators(outputs.dynamiclibrary_import[0].filePath),
+ FileInfo.toWindowsSeparators(outputs.dynamiclibrary[0].filePath)
+ ];
+ var cmd = new Command(input.cpp.implibPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.silent = true;
+ return cmd;
+}
+
+function prepareCompiler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var args = compilerFlags(project, product, input, outputs, explicitlyDependsOn);
+ var cmd = new Command(input.cpp.compilerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ return [cmd];
+}
+
+function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) {
+ var args = assemblerFlags(project, product, input, outputs, explicitlyDependsOn);
+ var cmd = new Command(input.cpp.assemblerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ return [cmd];
+}
+
+function prepareLinker(project, product, inputs, outputs, input, output) {
+ var cmds = [];
+ var primaryOutput = outputs.dynamiclibrary ? outputs.dynamiclibrary[0]
+ : outputs.application[0];
+ var args = linkerFlags(project, product, inputs, outputs);
+ var linkerPath = effectiveLinkerPath(product);
+ var cmd = new Command(linkerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "linking " + primaryOutput.fileName;
+ cmd.highlight = "linker";
+ cmds.push(cmd);
+
+ if (outputs.dynamiclibrary
+ || (outputs.application && !product.cpp.generateLinkerMapFile)) {
+ if (outputs.dynamiclibrary)
+ cmds.push(createImportLib(project, product, inputs, outputs, input, output));
+ cmds.push(removeLinkerMapFile(project, product, inputs, outputs, input, output));
+ } else if (outputs.application
+ && product.cpp.generateLinkerMapFile
+ && (product.cpp.linkerMapSuffix !== ".map")) {
+ cmds.push(renameLinkerMapFile(project, product, inputs, outputs, input, output));
+ }
+ return cmds;
+}
+
+function prepareArchiver(project, product, inputs, outputs, input, output) {
+ var args = archiverFlags(project, product, inputs, outputs);
+ var cmd = new Command(product.cpp.archiverPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "linking " + output.fileName;
+ cmd.highlight = "linker";
+ return [cmd];
+}
+
+function prepareRccCompiler(project, product, inputs, outputs, input, output) {
+ var args = rccCompilerFlags(project, product, input, outputs);
+ var cmd = new Command(input.cpp.rccCompilerPath, args);
+ cmd.workingDirectory = product.buildDirectory;
+ cmd.description = "compiling " + input.fileName;
+ cmd.highlight = "compiler";
+ return [cmd];
+}
diff --git a/share/qbs/modules/cpp/dmc.qbs b/share/qbs/modules/cpp/dmc.qbs
new file mode 100644
index 000000000..5369e84a7
--- /dev/null
+++ b/share/qbs/modules/cpp/dmc.qbs
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt.io/licensing
+**
+** This file is part of Qbs.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+import qbs.File
+import qbs.FileInfo
+import qbs.PathTools
+import qbs.Probes
+import qbs.Utilities
+import "dmc.js" as DMC
+import "cpp.js" as Cpp
+
+CppModule {
+ condition: qbs.hostOS.contains("windows") && qbs.toolchain && qbs.toolchain.contains("dmc")
+
+ Probes.BinaryProbe {
+ id: compilerPathProbe
+ condition: !toolchainInstallPath && !_skipAllChecks
+ names: ["cxcorm"]
+ }
+
+ Probes.DmcProbe {
+ id: dmcProbe
+ condition: !_skipAllChecks
+ compilerFilePath: compilerPath
+ enableDefinesByLanguage: enableCompilerDefinesByLanguage
+ }
+
+ qbs.architecture: dmcProbe.found ? dmcProbe.architecture : original
+ qbs.targetPlatform: dmcProbe.targetPlatform
+
+ compilerVersionMajor: dmcProbe.versionMajor
+ compilerVersionMinor: dmcProbe.versionMinor
+ compilerVersionPatch: dmcProbe.versionPatch
+ endianness: "little"
+
+ compilerDefinesByLanguage: dmcProbe.compilerDefinesByLanguage
+ compilerIncludePaths: dmcProbe.includePaths
+
+ toolchainInstallPath: compilerPathProbe.found ? compilerPathProbe.path : undefined
+
+ /* Work-around for QtCreator which expects these properties to exist. */
+ property string cCompilerName: compilerName
+ property string cxxCompilerName: compilerName
+
+ compilerName: "dmc.exe"
+ compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName)
+
+ assemblerName: "dmc.exe"
+ assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName)
+
+ linkerName: "link.exe"
+ linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName)
+
+ property string archiverName: "lib.exe"
+ property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName)
+ property string implibName: "implib.exe"
+ property string implibPath: FileInfo.joinPaths(toolchainInstallPath, implibName)
+ property string rccCompilerName: "rcc.exe"
+ property string rccCompilerPath: FileInfo.joinPaths(toolchainInstallPath, rccCompilerName)
+
+ runtimeLibrary: "dynamic"
+
+ staticLibrarySuffix: ".lib"
+ dynamicLibraryImportSuffix: ".lib"
+ dynamicLibrarySuffix: ".dll"
+ executableSuffix: ".exe"
+ objectSuffix: ".obj"
+ resourceSuffix: ".res"
+
+ imageFormat: "pe"
+
+ defineFlag: "-D"
+ includeFlag: "-I"
+ systemIncludeFlag: "-I"
+ preincludeFlag: "-HI"
+ libraryPathFlag: "-L/packcode"
+
+ knownArchitectures: ["x86"]
+
+ Rule {
+ id: assembler
+ inputs: ["asm"]
+ outputFileTags: DMC.depsOutputTags().concat(
+ Cpp.assemblerOutputTags(generateAssemblerListingFiles))
+ outputArtifacts: DMC.depsOutputArtifacts(input, product).concat(
+ Cpp.assemblerOutputArtifacts(input))
+ prepare: DMC.prepareAssembler.apply(DMC, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.s", "*.asm"]
+ fileTags: ["asm"]
+ }
+
+ Rule {
+ id: compiler
+ inputs: ["cpp", "c"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: DMC.depsOutputTags().concat(
+ Cpp.compilerOutputTags(generateCompilerListingFiles))
+ outputArtifacts: DMC.depsOutputArtifacts(input, product).concat(
+ Cpp.compilerOutputArtifacts(input))
+ prepare: DMC.prepareCompiler.apply(DMC, arguments)
+ }
+
+
+ Rule {
+ id: rccCompiler
+ inputs: ["rc"]
+ auxiliaryInputs: ["hpp"]
+ outputFileTags: Cpp.resourceCompilerOutputTags()
+ outputArtifacts: Cpp.resourceCompilerOutputArtifacts(input)
+ prepare: DMC.prepareRccCompiler.apply(DMC, arguments)
+ }
+
+ FileTagger {
+ patterns: ["*.rc"]
+ fileTags: ["rc"]
+ }
+
+ Rule {
+ id: applicationLinker
+ multiplex: true
+ inputs: ["obj", "res", "linkerscript"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.applicationLinkerOutputTags(generateLinkerMapFile)
+ outputArtifacts: Cpp.applicationLinkerOutputArtifacts(product)
+ prepare: DMC.prepareLinker.apply(DMC, arguments)
+ }
+
+ Rule {
+ id: dynamicLibraryLinker
+ multiplex: true
+ inputs: ["obj", "res"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.dynamicLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.dynamicLibraryLinkerOutputArtifacts(product)
+ prepare: DMC.prepareLinker.apply(DMC, arguments)
+ }
+
+ Rule {
+ id: staticLibraryLinker
+ multiplex: true
+ inputs: ["obj"]
+ inputsFromDependencies: ["staticlibrary", "dynamiclibrary_import"]
+ outputFileTags: Cpp.staticLibraryLinkerOutputTags()
+ outputArtifacts: Cpp.staticLibraryLinkerOutputArtifacts(product)
+ prepare: DMC.prepareArchiver.apply(DMC, arguments)
+ }
+}