From 3865c5d052949f8ec6cc26545933edb6e17ceb00 Mon Sep 17 00:00:00 2001 From: Denis Shienkov Date: Fri, 16 Aug 2019 15:47:01 +0300 Subject: baremetal: Improve JS code in KEIL module a bit * Move an architecture-specific code to a functions in the keil.js file. * Remove the redundant copy-paste code. * Align order for assembler, compiler, linker and archiver flags to the unified form, like: * Add some comments. * Fix handling of c{xx}LanguageVersion property. * Fix JS warnings about the variables re-definition. Change-Id: I708a446292e6f5c6bfb56ef3fa92815123808ccf Reviewed-by: Christian Kandeler --- share/qbs/imports/qbs/Probes/KeilProbe.qbs | 3 +- share/qbs/modules/cpp/keil.js | 363 +++++++++++++++++++++-------- share/qbs/modules/cpp/keil.qbs | 83 +------ 3 files changed, 273 insertions(+), 176 deletions(-) diff --git a/share/qbs/imports/qbs/Probes/KeilProbe.qbs b/share/qbs/imports/qbs/Probes/KeilProbe.qbs index 1955fe480..34afecb64 100644 --- a/share/qbs/imports/qbs/Probes/KeilProbe.qbs +++ b/share/qbs/imports/qbs/Probes/KeilProbe.qbs @@ -81,8 +81,7 @@ PathProbe { versionMajor = version.major; versionMinor = version.minor; versionPatch = version.patch; + found = version.found && architecture && endianness; } - - found = version.found && architecture && endianness; } } diff --git a/share/qbs/modules/cpp/keil.js b/share/qbs/modules/cpp/keil.js index c19fdd738..4b3665715 100644 --- a/share/qbs/modules/cpp/keil.js +++ b/share/qbs/modules/cpp/keil.js @@ -36,19 +36,104 @@ 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"); -var WindowsUtils = require("qbs.WindowsUtils"); -function guessArchitecture(macros) -{ +function compilerName(qbs) { + switch (qbs.architecture) { + case "mcs51": + return "c51"; + case "arm": + return "armcc"; + } + throw "Unable to deduce compiler name for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function assemblerName(qbs) { + switch (qbs.architecture) { + case "mcs51": + return "a51"; + case "arm": + return "armasm"; + } + throw "Unable to deduce assembler name for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function linkerName(qbs) { + switch (qbs.architecture) { + case "mcs51": + return "bl51"; + case "arm": + return "armlink"; + } + throw "Unable to deduce linker name for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function archiverName(qbs) { + switch (qbs.architecture) { + case "mcs51": + return "lib51"; + case "arm": + return "armar"; + } + throw "Unable to deduce archiver name for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function staticLibrarySuffix(qbs) { + switch (qbs.architecture) { + case "mcs51": + case "arm": + return ".lib"; + } + throw "Unable to deduce static library suffix for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function executableSuffix(qbs) { + switch (qbs.architecture) { + case "mcs51": + return ".abs"; + case "arm": + return ".axf"; + } + throw "Unable to deduce executable suffix for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function objectSuffix(qbs) { + switch (qbs.architecture) { + case "mcs51": + return ".obj"; + case "arm": + return ".o"; + } + throw "Unable to deduce object file suffix for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function imageFormat(qbs) { + switch (qbs.architecture) { + case "mcs51": + // Keil OMF51 or OMF2 Object Module Format (which is an + // extension of the original Intel OMF51). + return "omf"; + case "arm": + return "elf"; + } + throw "Unable to deduce image format for unsupported architecture: '" + + qbs.architecture + "'"; +} + +function guessArchitecture(macros) { if (macros["__C51__"]) return "mcs51"; else if (macros["__CC_ARM"] === 1) return "arm"; } -function guessEndianness(macros) -{ +function guessEndianness(macros) { if (macros["__C51__"]) { // The 8051 processors are 8-bit. So, the data with an integer type // represented by more than one byte is stored as big endian in the @@ -61,19 +146,18 @@ function guessEndianness(macros) } } -function guessVersion(macros) -{ +function guessVersion(macros) { if (macros["__C51__"]) { - var version = macros["__C51__"]; - return { major: parseInt(version / 100), - minor: parseInt(version % 100), + var mcsVersion = macros["__C51__"]; + return { major: parseInt(mcsVersion / 100), + minor: parseInt(mcsVersion % 100), patch: 0, found: true } } else if (macros["__CC_ARM"]) { - var version = macros["__ARMCC_VERSION"]; - return { major: parseInt(version / 1000000), - minor: parseInt(version / 10000) % 100, - patch: parseInt(version) % 10000, + var armVersion = macros["__ARMCC_VERSION"]; + return { major: parseInt(armVersion / 1000000), + minor: parseInt(armVersion / 10000) % 100, + patch: parseInt(armVersion) % 10000, found: true } } } @@ -132,26 +216,18 @@ function dumpMacros(compilerFilePath, tag, nullDevice) { var map1 = dumpC51CompilerMacros(compilerFilePath, tag, nullDevice); var map2 = dumpArmCompilerMacros(compilerFilePath, tag, nullDevice); var map = {}; - for (var attrname in map1) - map[attrname] = map1[attrname]; - for (var attrname in map2) - map[attrname] = map2[attrname]; + for (var key1 in map1) + map[key1] = map1[key1]; + for (var key2 in map2) + map[key2] = map2[key2]; return map; } function dumpDefaultPaths(compilerFilePath, architecture) { - var includePaths = []; - - if (architecture === "mcs51") { - var path = compilerFilePath.replace(/bin[\\\/](.*)$/i, "inc"); - includePaths.push(path); - } else if (architecture === "arm") { - var path = compilerFilePath.replace(/bin[\\\/](.*)$/i, "include"); - includePaths.push(path); - } - + var incDir = (architecture === "arm") ? "include" : "inc"; + var includePath = compilerFilePath.replace(/bin[\\\/](.*)$/i, incDir); return { - "includePaths": includePaths + "includePaths": [includePath] }; } @@ -247,9 +323,8 @@ function filterStdOutput(cmd) { } function compilerFlags(project, product, input, output, explicitlyDependsOn) { - // Determine which C-language we"re compiling. + // Determine which C-language we're compiling. var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); - var architecture = input.qbs.architecture; var args = []; var allDefines = []; @@ -271,10 +346,29 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) { if (compilerIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths); + var architecture = input.qbs.architecture; if (architecture === "mcs51") { + // Input. args.push(FileInfo.toWindowsSeparators(input.filePath)); + + // Output. args.push("OBJECT (" + FileInfo.toWindowsSeparators(output.filePath) + ")"); + // Defines. + if (allDefines.length > 0) + args = args.concat("DEFINE (" + allDefines.join(",") + ")"); + + // Includes. + if (allIncludePaths.length > 0) { + var adjusted = adjustPathsToWindowsSeparators(allIncludePaths); + args = args.concat("INCDIR (" + adjusted.join(";") + ")"); + } + + // Debug information flags. + if (input.cpp.debugInformation) + args.push("DEBUG"); + + // Optimization level flags. switch (input.cpp.optimization) { case "small": args.push("OPTIMIZE (SIZE)"); @@ -287,28 +381,36 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) { break; } - if (input.cpp.debugInformation) - args.push("DEBUG"); - - var warnings = input.cpp.warningLevel; - if (warnings === "none") { + // Warning level flags. + switch (input.cpp.warningLevel) { + case "none": args.push("WARNINGLEVEL (0)"); - } else if (warnings === "all") { + break; + case "all": args.push("WARNINGLEVEL (2)"); args.push("FARWARNING"); - } - - if (allDefines.length > 0) - args = args.concat("DEFINE (" + allDefines.join(",") + ")"); - - if (allIncludePaths.length > 0) { - var adjusted = adjustPathsToWindowsSeparators(allIncludePaths); - args = args.concat("INCDIR (" + adjusted.join(";") + ")"); + break; } } else if (architecture === "arm") { + // Input. args.push("-c", input.filePath); + + // Output. args.push("-o", output.filePath); + // Defines. + args = args.concat(allDefines.map(function(define) { return '-D' + define })); + + // Includes. + args = args.concat(allIncludePaths.map(function(include) { return '-I' + include })); + + // Debug information flags. + if (input.cpp.debugInformation) { + args.push("--debug"); + args.push("-g"); + } + + // Optimization level flags. switch (input.cpp.optimization) { case "small": args.push("-Ospace") @@ -321,43 +423,57 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) { break; } - if (input.cpp.debugInformation) { - args.push("--debug"); - args.push("-g"); - } - - var warnings = input.cpp.warningLevel; - if (warnings === "none") { + // Warning level flags. + switch (input.cpp.warningLevel) { + case "none": args.push("-W"); - } else if (warnings === "all") { + break; + default: // By default all warnings are enabled. + break; } if (tag === "c") { - // Note: Here we use the '==' operator because the '===' - // operator does not work! - if (input.cpp.cLanguageVersion == "c99") + // C language version flags. + var knownCLanguageValues = ["c99", "c90"]; + var cLanguageVersion = Cpp.languageVersion( + input.cpp.cLanguageVersion, knownCLanguageValues, "C"); + switch (cLanguageVersion) { + case "c99": args.push("--c99"); + break; + case "c90": + args.push("--c90"); + break; + } } else if (tag === "cpp") { - args.push("--cpp"); - // Note: Here we use the '==' operator because the '===' - // operator does not work! - if (input.cpp.cxxLanguageVersion == "c++11") + // C++ language version flags. + var knownCppLanguageValues = ["c++11", "c++03"]; + var cppLanguageVersion = Cpp.languageVersion( + input.cpp.cxxLanguageVersion, knownCppLanguageValues, "C++"); + switch (cppLanguageVersion) { + case "c++11": args.push("--cpp11"); + break; + default: + // Default C++ language is C++03. + args.push("--cpp"); + break; + } + // Exceptions flags. var enableExceptions = input.cpp.enableExceptions; if (enableExceptions !== undefined) args.push(enableExceptions ? "--exceptions" : "--no_exceptions"); + // RTTI flags. var enableRtti = input.cpp.enableRtti; if (enableRtti !== undefined) args.push(enableRtti ? "--rtti" : "--no_rtti"); } - - args = args.concat(allDefines.map(function(define) { return '-D' + define })); - args = args.concat(allIncludePaths.map(function(include) { return '-I' + include })); } + // Misc flags. args = args.concat(ModUtils.moduleProperty(input, "platformFlags"), ModUtils.moduleProperty(input, "flags"), ModUtils.moduleProperty(input, "platformFlags", tag), @@ -367,9 +483,8 @@ function compilerFlags(project, product, input, output, explicitlyDependsOn) { } function assemblerFlags(project, product, input, output, explicitlyDependsOn) { - // Determine which C-language we"re compiling + // Determine which C-language we're compiling var tag = ModUtils.fileTagForTargetLanguage(input.fileTags.concat(output.fileTags)); - var architecture = input.qbs.architecture; var args = []; var allDefines = []; @@ -391,37 +506,35 @@ function assemblerFlags(project, product, input, output, explicitlyDependsOn) { if (compilerIncludePaths) allIncludePaths = allIncludePaths.uniqueConcat(compilerIncludePaths); + var architecture = input.qbs.architecture; if (architecture === "mcs51") { + // Input. args.push(FileInfo.toWindowsSeparators(input.filePath)); - args.push("OBJECT (" + FileInfo.toWindowsSeparators(output.filePath) + ")"); - if (input.cpp.debugInformation) - args.push("DEBUG"); + // Output. + args.push("OBJECT (" + FileInfo.toWindowsSeparators(output.filePath) + ")"); + // Defines. if (allDefines.length > 0) args = args.concat("DEFINE (" + allDefines.join(",") + ")"); + // Includes. if (allIncludePaths.length > 0) { var adjusted = adjustPathsToWindowsSeparators(allIncludePaths); args = args.concat("INCDIR (" + adjusted.join(";") + ")"); } + + // Debug information flags. + if (input.cpp.debugInformation) + args.push("DEBUG"); } else if (architecture === "arm") { + // Input. args.push(input.filePath); - args.push("-o", output.filePath); - - if (input.cpp.debugInformation) { - args.push("--debug"); - args.push("-g"); - } - var warnings = input.cpp.warningLevel; - if (warnings === "none") - args.push("--no_warn"); - - var endianness = input.cpp.endianness; - if (endianness) - args.push((endianness === "little") ? "--littleend" : "--bigend"); + // Output. + args.push("-o", output.filePath); + // Defines. allDefines.forEach(function(define) { var parts = define.split("="); args.push("--pd"); @@ -433,9 +546,26 @@ function assemblerFlags(project, product, input, output, explicitlyDependsOn) { args.push(parts[0] + " SETA " + parts[1]); }); + // Includes. args = args.concat(allIncludePaths.map(function(include) { return '-I' + include })); + + // Debug information flags. + if (input.cpp.debugInformation) { + args.push("--debug"); + args.push("-g"); + } + + // Warning level flags. + if (input.cpp.warningLevel === "none") + args.push("--no_warn"); + + // Byte order flags. + var endianness = input.cpp.endianness; + if (endianness) + args.push((endianness === "little") ? "--littleend" : "--bigend"); } + // Misc flags. args = args.concat(ModUtils.moduleProperty(input, "platformFlags", tag), ModUtils.moduleProperty(input, "flags", tag), ModUtils.moduleProperty(input, "driverFlags", tag)); @@ -444,89 +574,116 @@ function assemblerFlags(project, product, input, output, explicitlyDependsOn) { function linkerFlags(project, product, input, outputs) { var args = []; - var architecture = product.qbs.architecture; + var architecture = product.qbs.architecture; if (architecture === "mcs51") { + // Note: The C51 linker does not distinguish an object files and + // a libraries, it interpret all this stuff as an input objects, + // so, we need to pass it together in one string. + var allObjectPaths = []; function addObjectPath(obj) { allObjectPaths.push(obj.filePath); } + // Inputs. if (inputs.obj) inputs.obj.map(function(obj) { addObjectPath(obj) }); - var libraryDependencies = collectLibraryDependencies(product); - libraryDependencies.forEach(function(dep) { addObjectPath(dep); }) + // Library dependencies. + var libraryObjects = collectLibraryDependencies(product); + libraryObjects.forEach(function(dep) { addObjectPath(dep); }) + // Add all input objects as arguments (application and library object files). var adjusted = adjustPathsToWindowsSeparators(allObjectPaths); args = args.concat(adjusted.join(",")); - // We need to wrap an output file name with quotes. Otherwise + // Output. + // Note: We need to wrap an output file name with quotes. Otherwise // the linker will ignore a specified file name. args.push("TO", '"' + FileInfo.toWindowsSeparators(outputs.application[0].filePath) + '"'); + // Map file generation flag. if (!product.cpp.generateMapFile) args.push("NOMAP"); } else if (architecture === "arm") { + // Inputs. if (inputs.obj) args = args.concat(inputs.obj.map(function(obj) { return obj.filePath })); + // Output. args.push("--output", outputs.application[0].filePath); - if (product.cpp.generateMapFile) - args.push("--list", outputs.map_file[0].filePath); - + // Library paths. var libraryPaths = product.cpp.libraryPaths; if (libraryPaths) args.push("--userlibpath=" + libraryPaths.join(",")); + // Library dependencies. var libraryDependencies = collectLibraryDependencies(product); args = args.concat(libraryDependencies.map(function(dep) { return dep.filePath; })); - var linkerScripts = inputs.linkerscript - ? inputs.linkerscript.map(function(a) { return a.filePath; }) : []; - for (i in linkerScripts) - args.push("--scatter", linkerScripts[i]); + // Debug information flag. + var debugInformation = product.cpp.debugInformation; + if (debugInformation !== undefined) + args.push(debugInformation ? "--debug" : "--no_debug"); + // Map file generation flag. + if (product.cpp.generateMapFile) + args.push("--list", outputs.map_file[0].filePath); + + // Entry point flag. if (product.cpp.entryPoint) args.push("--entry", product.cpp.entryPoint); - var debugInformation = product.cpp.debugInformation; - if (debugInformation !== undefined) - args.push(debugInformation ? "--debug" : "--no_debug"); + // Linker scripts flags. + var linkerScripts = inputs.linkerscript + ? inputs.linkerscript.map(function(a) { return a.filePath; }) : []; + linkerScripts.forEach(function(script) { args.push("--scatter", script); }); } + // Misc flags. args = args.concat(ModUtils.moduleProperty(product, "driverLinkerFlags")); return args; } function archiverFlags(project, product, input, outputs) { var args = []; - var architecture = product.qbs.architecture; + var architecture = product.qbs.architecture; if (architecture === "mcs51") { + // Library creation command. args.push("TRANSFER"); - var allObjectPaths = []; + var allObjectPaths = []; function addObjectPath(obj) { allObjectPaths.push(obj.filePath); } + // Inputs. if (inputs.obj) inputs.obj.map(function(obj) { addObjectPath(obj) }); + // Add all input objects as arguments. var adjusted = adjustPathsToWindowsSeparators(allObjectPaths); args = args.concat(adjusted.join(",")); - // We need to wrap a output file name with quotes. Otherwise + // Output. + // Note: We need to wrap a output file name with quotes. Otherwise // the linker will ignore a specified file name. args.push("TO", '"' + FileInfo.toWindowsSeparators(outputs.staticlibrary[0].filePath) + '"'); } else if (architecture === "arm") { + // Note: The ARM archiver command line expect the output file + // first, and then a set of input objects. + + // Output. args.push("--create", outputs.staticlibrary[0].filePath); + // Inputs. if (inputs.obj) args = args.concat(inputs.obj.map(function(obj) { return obj.filePath })); + // Debug information flag. if (product.cpp.debugInformation) args.push("--debug_symbols"); } @@ -538,7 +695,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli var args = compilerFlags(project, product, input, output, explicitlyDependsOn); var compilerPath = input.cpp.compilerPath; var architecture = input.cpp.architecture; - var cmd = new Command(compilerPath, args) + var cmd = new Command(compilerPath, args); cmd.description = "compiling " + input.fileName; cmd.highlight = "compiler"; cmd.maxExitCode = getMaxExitCode(architecture); @@ -550,7 +707,7 @@ function prepareCompiler(project, product, inputs, outputs, input, output, expli function prepareAssembler(project, product, inputs, outputs, input, output, explicitlyDependsOn) { var args = assemblerFlags(project, product, input, output, explicitlyDependsOn); var assemblerPath = input.cpp.assemblerPath; - var cmd = new Command(assemblerPath, args) + var cmd = new Command(assemblerPath, args); cmd.description = "assembling " + input.fileName; cmd.highlight = "compiler"; filterStdOutput(cmd); @@ -561,7 +718,7 @@ function prepareLinker(project, product, inputs, outputs, input, output) { var primaryOutput = outputs.application[0]; var args = linkerFlags(project, product, input, outputs); var linkerPath = product.cpp.linkerPath; - var cmd = new Command(linkerPath, args) + var cmd = new Command(linkerPath, args); cmd.description = "linking " + primaryOutput.fileName; cmd.highlight = "linker"; filterStdOutput(cmd); @@ -571,7 +728,7 @@ function prepareLinker(project, product, inputs, outputs, input, output) { function prepareArchiver(project, product, inputs, outputs, input, output) { var args = archiverFlags(project, product, input, outputs); var archiverPath = product.cpp.archiverPath; - var cmd = new Command(archiverPath, args) + var cmd = new Command(archiverPath, args); cmd.description = "linking " + output.fileName; cmd.highlight = "linker"; filterStdOutput(cmd); diff --git a/share/qbs/modules/cpp/keil.qbs b/share/qbs/modules/cpp/keil.qbs index cb6094f51..2d29112cd 100644 --- a/share/qbs/modules/cpp/keil.qbs +++ b/share/qbs/modules/cpp/keil.qbs @@ -78,85 +78,26 @@ CppModule { property string cCompilerName: compilerName property string cxxCompilerName: compilerName - compilerName: { - switch (qbs.architecture) { - case "mcs51": - return "c51" + compilerExtension; - case "arm": - return "armcc" + compilerExtension; - } - } + compilerName: KEIL.compilerName(qbs) + compilerExtension compilerPath: FileInfo.joinPaths(toolchainInstallPath, compilerName) - assemblerName: { - switch (qbs.architecture) { - case "mcs51": - return "a51" + compilerExtension; - case "arm": - return "armasm" + compilerExtension; - } - } + assemblerName: KEIL.assemblerName(qbs) + compilerExtension assemblerPath: FileInfo.joinPaths(toolchainInstallPath, assemblerName) - linkerName: { - switch (qbs.architecture) { - case "mcs51": - return "bl51" + compilerExtension; - case "arm": - return "armlink" + compilerExtension; - } - } + linkerName: KEIL.linkerName(qbs) + compilerExtension linkerPath: FileInfo.joinPaths(toolchainInstallPath, linkerName) - property string archiverName: { - switch (qbs.architecture) { - case "mcs51": - return "lib51" + compilerExtension; - case "arm": - return "armar" + compilerExtension; - } - } + property string archiverName: KEIL.archiverName(qbs) + compilerExtension property string archiverPath: FileInfo.joinPaths(toolchainInstallPath, archiverName) runtimeLibrary: "static" - staticLibrarySuffix: { - switch (qbs.architecture) { - case "mcs51": - return ".lib"; - case "arm": - return ".lib"; - } - } - - executableSuffix: { - switch (qbs.architecture) { - case "mcs51": - return ".abs"; - case "arm": - return ".axf"; - } - } + staticLibrarySuffix: KEIL.staticLibrarySuffix(qbs) + executableSuffix: KEIL.executableSuffix(qbs) - property string objectSuffix: { - switch (qbs.architecture) { - case "mcs51": - return ".obj"; - case "arm": - return ".o"; - } - } + property string objectSuffix: KEIL.objectSuffix(qbs) - imageFormat: { - switch (qbs.architecture) { - case "mcs51": - // Keil OMF51 or OMF2 Object Module Format (which is an - // extension of the original Intel OMF51). - return "omf"; - case "arm": - return "elf"; - } - } + imageFormat: KEIL.imageFormat(qbs) enableExceptions: false enableRtti: false @@ -171,7 +112,7 @@ CppModule { + input.fileName + input.cpp.objectSuffix } - prepare: KEIL.prepareAssembler.apply(KEIL, arguments); + prepare: KEIL.prepareAssembler.apply(KEIL, arguments) } FileTagger { @@ -190,7 +131,7 @@ CppModule { + input.fileName + input.cpp.objectSuffix } - prepare: KEIL.prepareCompiler.apply(KEIL, arguments); + prepare: KEIL.prepareCompiler.apply(KEIL, arguments) } Rule { @@ -223,7 +164,7 @@ CppModule { return artifacts; } - prepare:KEIL.prepareLinker.apply(KEIL, arguments); + prepare: KEIL.prepareLinker.apply(KEIL, arguments) } Rule { @@ -239,6 +180,6 @@ CppModule { PathTools.staticLibraryFilePath(product)) } - prepare: KEIL.prepareArchiver.apply(KEIL, arguments); + prepare: KEIL.prepareArchiver.apply(KEIL, arguments) } } -- cgit v1.2.3