blob: 55110c92c3e4d5415c4c1d4ca0048ae7ef6a679a [file] [log] [blame] [raw]
// Copyright (c) 2018, Compiler Explorer Authors
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
"use strict";
const
exec = require('../exec'),
utils = require('../utils'),
_ = require('underscore'),
logger = require('../logger').logger,
path = require('path');
class BaseTool {
constructor(toolInfo, env) {
this.tool = toolInfo;
this.env = env;
this.tool.exclude = this.tool.exclude ? this.tool.exclude.split(':') : [];
}
getId() {
return this.tool.id;
}
getType() {
return this.tool.type || "independent";
}
isCompilerExcluded(compilerId) {
return this.tool.exclude.find((excl) => compilerId.includes(excl));
}
exec(toolExe, args, options) {
return exec.execute(toolExe, args, options);
}
getDefaultExecOptions() {
return {
timeoutMs: this.env.ceProps("compileTimeoutMs", 7500),
maxErrorOutput: this.env.ceProps("max-error-output", 5000),
wrapper: this.env.compilerProps("compiler-wrapper")
};
}
createErrorResponse(message) {
return {
id: this.tool.id,
name: this.tool.name,
code: -1,
languageId: "stderr",
stdout: utils.parseOutput(message)
};
}
// mostly copy&paste from base-compiler.js
findLibVersion(selectedLib, compiler) {
const foundLib = _.find(compiler.libs, (o, libId) => libId === selectedLib.id);
if (!foundLib) return false;
const foundVersion = _.find(foundLib.versions, (o, versionId) => versionId === selectedLib.version);
return foundVersion;
}
// mostly copy&paste from base-compiler.js
getIncludeArguments(libraries, compiler) {
const includeFlag = "-I";
return _.flatten(_.map(libraries, (selectedLib) => {
const foundVersion = this.findLibVersion(selectedLib, compiler);
if (!foundVersion) return false;
return _.map(foundVersion.path, (path) => includeFlag + path);
}));
}
runTool(compilationInfo, inputFilepath, args, stdin) {
let execOptions = this.getDefaultExecOptions();
if (inputFilepath) execOptions.customCwd = path.dirname(inputFilepath);
execOptions.input = stdin;
args = args ? args : [];
args = args.filter((arg) => !arg.includes('/'));
if (inputFilepath) args.push(inputFilepath);
const exeDir = path.dirname(this.tool.exe);
return this.exec(this.tool.exe, args, execOptions).then(result => {
const transformedFilepath = result.filenameTransform(inputFilepath);
return {
id: this.tool.id,
name: this.tool.name,
code: result.code,
languageId: this.tool.languageId,
stderr: utils.parseOutput(result.stderr, transformedFilepath, exeDir),
stdout: utils.parseOutput(result.stdout, transformedFilepath, exeDir)
};
}).catch((e) => {
logger.error("Error while running tool: ", e);
return this.createErrorResponse("Error while running tool");
});
}
}
module.exports = BaseTool;