diff options
Diffstat (limited to 'share/qbs/modules/cpp')
-rw-r--r-- | share/qbs/modules/cpp/CppModule.qbs | 1 | ||||
-rw-r--r-- | share/qbs/modules/cpp/cpp.js | 105 | ||||
-rw-r--r-- | share/qbs/modules/cpp/dmc.js | 462 | ||||
-rw-r--r-- | share/qbs/modules/cpp/dmc.qbs | 177 |
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) + } +} |