diff options
author | Matt Godbolt <matt@godbolt.org> | 2019-03-21 20:31:42 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-21 20:31:42 -0500 |
commit | b87322568ed7f73a8583cdce707f68f07a0995dd (patch) | |
tree | 387ffc9ba2487bea8c6ab9eb7c40d03cd1e74dc6 /lib/base-compiler.js | |
parent | b8815fbdb20261634919d976310c13e945249250 (diff) | |
parent | a47efe6d65f86024f46be5ef96139bb2f67dca73 (diff) | |
download | compiler-explorer-b87322568ed7f73a8583cdce707f68f07a0995dd.tar.gz compiler-explorer-b87322568ed7f73a8583cdce707f68f07a0995dd.zip |
Merge branch 'master' into llvm
Diffstat (limited to 'lib/base-compiler.js')
-rw-r--r-- | lib/base-compiler.js | 119 |
1 files changed, 85 insertions, 34 deletions
diff --git a/lib/base-compiler.js b/lib/base-compiler.js index 41e549b2e..7b19b4149 100644 --- a/lib/base-compiler.js +++ b/lib/base-compiler.js @@ -30,10 +30,12 @@ const temp = require('temp'), AsmParser = require('./asm-parser'), utils = require('./utils'), _ = require('underscore'), + packager = require('./packager').Packager, exec = require('./exec'), logger = require('./logger').logger, compilerOptInfo = require("compiler-opt-info"), argumentParsers = require("./compilers/argument-parsers"), + CompilerArguments = require("./compiler-arguments"), cfg = require('./cfg'), languages = require('./languages').list; @@ -66,8 +68,13 @@ class BaseCompiler { this.asm = new AsmParser(this.compilerProps); this.llvmIr = new LlvmIrParser(this.compilerProps); + this.possibleArguments = new CompilerArguments(this.compiler.id); this.possibleTools = _.values(compilerInfo.tools); this.possibleLibs = compilerInfo.libs; + + this.outputFilebase = "output"; + + this.packager = new packager(); } newTempDir() { @@ -110,6 +117,10 @@ class BaseCompiler { execOptions = this.getDefaultExecOptions(); } + if (!execOptions.customCwd) { + execOptions.customCwd = path.dirname(inputFilename); + } + return this.exec(compiler, options, execOptions).then(result => { result.inputFilename = inputFilename; result.stdout = utils.parseOutput(result.stdout, inputFilename); @@ -137,9 +148,11 @@ class BaseCompiler { } execBinary(executable, maxSize, executeParameters) { + // We might want to save this in the compilation environment once execution is made available + const timeoutMs = this.env.ceProps('binaryExecTimeoutMs', 2000); return exec.sandbox(executable, executeParameters, { maxOutput: maxSize, - timeoutMs: 2000 + timeoutMs: timeoutMs }) // TODO make config .then(execResult => { execResult.stdout = utils.parseOutput(execResult.stdout); @@ -290,34 +303,68 @@ class BaseCompiler { return this.runCompiler(compiler, options, inputFilename, execOptions); } - getOrBuildExecutable(key) { - // todo: ask cache for executable if it already exists + buildExecutableInFolder(key, dirPath) { + const inputFilename = path.join(dirPath, this.compileFilename); + return this.writeFile(inputFilename, key.source).then(() => { + return { + inputFilename: inputFilename, + dirPath: dirPath + }; + }).then((dirResult) => { + const outputFilename = this.getExecutableFilename(dirResult.dirPath, this.outputFilebase); - return this.newTempDir() - .then(dirPath => { - const inputFilename = path.join(dirPath, this.compileFilename); - return this.writeFile(inputFilename, key.source).then(() => ({ - inputFilename: inputFilename, - dirPath: dirPath - })); - }).then((dirResult) => { - const outputFilebase = "output"; - const outputFilename = this.getExecutableFilename(dirResult.dirPath, outputFilebase); - - let buildFilters = Object.assign({}, key.filters); - buildFilters.binary = true; - buildFilters.execute = true; - - const compilerArguments = _.compact( - this.prepareArguments(key.options, buildFilters, key.backendOptions, - dirResult.inputFilename, outputFilename) - ); - - return this.buildExecutable(key.compiler.exe, compilerArguments, - dirResult.inputFilename, this.getDefaultExecOptions()).then(result => { + let buildFilters = Object.assign({}, key.filters); + buildFilters.binary = true; + buildFilters.execute = true; + + const compilerArguments = _.compact( + this.prepareArguments(key.options, buildFilters, key.backendOptions, + dirResult.inputFilename, outputFilename) + ); + + return this.buildExecutable(key.compiler.exe, compilerArguments, + dirResult.inputFilename, this.getDefaultExecOptions()) + .then(result => { result.executableFilename = outputFilename; return result; }); + }); + } + + getOrBuildExecutable(key) { + return this.newTempDir() + .then(dirPath => { + return this.env.executableGet(key, dirPath).then(outputFilename => { + logger.debug("Using cached package " + outputFilename); + return this.packager.unpack(outputFilename, dirPath).then(() => { + return { + code: 0, + inputFilename: path.join(dirPath, this.compileFilename), + dirPath: dirPath, + executableFilename: this.getExecutableFilename(dirPath, this.outputFilebase) + }; + }); + }).catch((err) => { + logger.debug("Tried to get executable from cache, but... " + err); + + return this.buildExecutableInFolder(key, dirPath).then(result => { + if (result.code !== 0) { + return result; + } else { + return this.newTempDir().then(packDir => { + const packagedfile = path.join(packDir, "package.tgz"); + return this.packager.package(result.executableFilename, packagedfile).then(() => { + return this.env.executablePut(key, packagedfile).then(() => { + fs.remove(packDir); + return result; + }); + }).catch((e) => { + logger.error(e); + }); + }); + } + }); + }); }); } @@ -333,7 +380,7 @@ class BaseCompiler { if (buildResult.code !== 0) { return buildResult; } else { - return this.runExecutable(buildResult.executableFilename, + return this.runExecutable(buildResult.executableFilename, executeParameters); } }); @@ -396,8 +443,7 @@ class BaseCompiler { const inputFilename = info.inputFilename; const inputFilenameSafe = this.filename(inputFilename); const dirPath = info.dirPath; - const outputFilebase = "output"; - const outputFilename = this.getOutputFilename(dirPath, outputFilebase); + const outputFilename = this.getOutputFilename(dirPath, this.outputFilebase); options = _.compact( this.prepareArguments(options, filters, backendOptions, inputFilename, outputFilename) @@ -459,7 +505,7 @@ class BaseCompiler { } if (this.compiler.supportsOptOutput && this.optOutputRequested(options)) { - const optPath = path.join(dirPath, `${outputFilebase}.opt.yaml`); + const optPath = path.join(dirPath, `${this.outputFilebase}.opt.yaml`); if (fs.existsSync(optPath)) { asmResult.hasOptOutput = true; asmResult.optPath = optPath; @@ -505,8 +551,7 @@ class BaseCompiler { return result; }) .then(result => { - const outputFilebase = "output"; - const outputFilename = this.getOutputFilename(result.dirPath, outputFilebase); + const outputFilename = this.getOutputFilename(result.dirPath, this.outputFilebase); const postToolsPromise = this.runToolsOfType( result.inputFilename, tools, "postcompilation", @@ -533,11 +578,17 @@ class BaseCompiler { .then(result => filters.demangle ? this.postProcessAsm(result, filters) : result) .then(result => { if (this.compiler.supportsCfg && backendOptions && backendOptions.produceCfg) { - result.cfg = cfg.generateStructure(this.compiler.version, result.asm); + result.cfg = cfg.generateStructure(this.compiler.compilerType, + this.compiler.version, result.asm); } return result; }) .then(result => { + result.popularArguments = this.possibleArguments.getPopularArguments(options); + + return result; + }) + .then(result => { if (result.okToCache) { this.env.cachePut(key, result); } @@ -612,8 +663,8 @@ class BaseCompiler { isCfgCompiler(compilerVersion) { return compilerVersion.includes("clang") || - compilerVersion.indexOf("g++") === 0 || - compilerVersion.indexOf("gdc") === 0; + compilerVersion.match(/^([\w-]*-)?g((\+\+)|(cc)|(dc))/g) !== null; + } processAstOutput(output) { |