Files
8bitworkshop/gen/worker/tools/mcpp.js
T

138 lines
5.5 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.preprocessMCPP = preprocessMCPP;
exports.prepareCompilerInput = prepareCompilerInput;
const util_1 = require("../../common/util");
const toolmeta_1 = require("../../common/toolmeta");
const builder_1 = require("../builder");
const listingutils_1 = require("../listingutils");
const platforms_1 = require("../platforms");
const wasmutils_1 = require("../wasmutils");
function makeCPPSafe(s) {
return s.replace(/[^A-Za-z0-9_]/g, '_');
}
/** Copy the headers under src.dir into an Emscripten FS at /share/include. */
function copyWASIIncludes(FS, src) {
const prefix = src.dir + '/';
const made = new Set();
const mkdirs = (path) => {
let parts = path.split('/');
for (let i = 2; i < parts.length; i++) {
let dir = parts.slice(0, i).join('/');
if (!made.has(dir)) {
if (!FS.analyzePath(dir).exists)
FS.mkdir(dir);
made.add(dir);
}
}
};
for (let file of src.fs.getFiles()) {
if (file.name.startsWith(prefix)) {
let path = '/share/include/' + file.name.substring(prefix.length);
mkdirs(path);
FS.writeFile(path, file.getBytes(), { encoding: 'binary' });
}
}
}
/**
* Preprocess the step's main source. `filesys` names the Emscripten FS
* package mounted at /share, or gives headers to copy into /share/include.
*/
function preprocessMCPP(step, filesys, extraArgs = []) {
var _a, _b;
(0, wasmutils_1.load)("mcpp");
var platform = step.platform;
var params = platforms_1.PLATFORM_PARAMS[platform] || platforms_1.PLATFORM_PARAMS[(0, util_1.getBasePlatform)(platform)];
if (!params)
throw Error("Platform not supported: " + platform);
// <stdin>:2: error: Can't open include file "foo.h"
var errors = [];
var match_fn = (0, listingutils_1.makeErrorMatcher)(errors, /<stdin>:(\d+): (.+)/, 1, 2, step.path);
var MCPP = wasmutils_1.emglobal.mcpp({
noInitialRun: true,
noFSInit: true,
print: wasmutils_1.print_fn,
printErr: match_fn,
});
var FS = MCPP.FS;
if (typeof filesys === 'string')
(0, wasmutils_1.setupFS)(FS, filesys);
else if (filesys)
copyWASIIncludes(FS, filesys);
(0, builder_1.populateFiles)(step, FS, {
mainFilePath: step.path,
processFn: (path, code) => {
if (typeof code === 'string') {
code = (0, builder_1.processEmbedDirective)(code);
}
return code;
}
});
(0, builder_1.populateExtraFiles)(step, FS, params.extra_compile_files);
// TODO: make configurable by other compilers
var arch = params.arch || 'z80';
var args = [
"-D", "__8BITWORKSHOP__",
"-D", "__SDCC_" + arch,
"-D", makeCPPSafe(platform.toUpperCase()),
"-I", "/share/include",
"-Q",
step.path, "main.i"
];
if (step.mainfile) {
args.unshift.apply(args, ["-D", "__MAIN__"]);
}
let platform_def = platform.toUpperCase().replaceAll(/[^a-zA-Z0-9]/g, '_');
args.unshift.apply(args, ["-D", `__PLATFORM_${platform_def}__`]);
args.unshift(...extraArgs);
// //#symbol c NAME=VALUE: the compiler only sees preprocessed text, so the
// define has to reach mcpp for #ifdef/#ifndef (and array sizes) to see it
for (let d of ((_b = (_a = step.params) === null || _a === void 0 ? void 0 : _a.symbols) === null || _b === void 0 ? void 0 : _b.compiler) || [])
args.unshift("-D", d);
if (params.extra_preproc_args) {
args.push.apply(args, params.extra_preproc_args);
}
(0, wasmutils_1.execMain)(step, MCPP, args);
if (errors.length)
return { errors: errors };
var iout = FS.readFile("main.i", { encoding: 'utf8' });
// per-line, not `replace(/^#line /gm, ...)` -- the multiline global matcher
// overflows the small worker stack ("too much recursion") on large output
iout = iout.split('\n').map((line) => line.startsWith('#line ') ? '\n# ' + line.substring(6) : line).join('\n');
try {
var errout = FS.readFile("mcpp.err", { encoding: 'utf8' });
if (errout.length) {
// //main.c:2: error: Can't open include file "stdiosd.h"
var errors = (0, listingutils_1.extractErrors)(/([^:]+):(\d+): (.+)/, errout.split("\n"), step.path, 2, 3, 1);
if (errors.length == 0) {
errors = (0, builder_1.errorResult)(errout).errors;
}
return { errors: errors };
}
}
catch (e) {
//
}
return { code: iout };
}
/**
* Preprocess the step's main source with mcpp, load the result into the
* compiler's own filesystem, and prepend the tool's extra args and defines.
* Returns an error result, or null on success.
*/
function prepareCompilerInput(step, tool, FS, params, args) {
(0, builder_1.fixParamsWithDefines)(step.path, params); // before mcpp: //#symbol c reaches it
var preproc = preprocessMCPP(step, null);
if (preproc.errors)
return { errors: preproc.errors };
(0, builder_1.populateFiles)(step, FS);
FS.writeFile(step.path, preproc.code);
if (params.extra_compile_args) {
args.unshift.apply(args, params.extra_compile_args);
}
// //#symbol c / //#flag c
args.unshift.apply(args, (0, toolmeta_1.defineArgs)(tool, params.symbols && params.symbols.compiler)
.concat((0, toolmeta_1.extraArgsFor)(tool, params.buildArgs)));
return null;
}
//# sourceMappingURL=mcpp.js.map