mirror of
https://github.com/embarklabs/embark-solc.git
synced 2025-02-28 22:40:26 +00:00
Compilation error `Unknown key “path”` was present when using Solidity 0.5.x. This PR removes the path property from the compilation sources as it is not needed.
213 lines
6.7 KiB
JavaScript
213 lines
6.7 KiB
JavaScript
const async = require('async');
|
|
const shelljs = require('shelljs');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
function compileSolcContract(logger, compileSettings, allowedDirectories, callback) {
|
|
const command = `solc --standard-json --allow-paths ${allowedDirectories.join(',')}`;
|
|
|
|
shelljs.ShellString(JSON.stringify(compileSettings)).exec(command, {silent: true}, (code, stdout, stderr) => {
|
|
if (stderr) {
|
|
logger.warn(stderr);
|
|
}
|
|
|
|
if (code !== 0) {
|
|
return callback(`solc exited with error code ${code}`);
|
|
}
|
|
|
|
if (!stdout) {
|
|
return callback('solc execution returned nothing');
|
|
}
|
|
|
|
callback(null, stdout.replace(/\n/g, ''));
|
|
});
|
|
}
|
|
|
|
function getSolcVersion(logger, callback) {
|
|
shelljs.exec('solc --version', {silent: true}, (code, stdout, stderr) => {
|
|
if (stderr) {
|
|
logger.warn(stderr);
|
|
}
|
|
|
|
if (code !== 0) {
|
|
return callback(`solc exited with error code ${code}`);
|
|
}
|
|
|
|
if (!stdout) {
|
|
return callback('solc execution returned nothing');
|
|
}
|
|
|
|
const result = stdout.match(/(\d+.\d+.\d+)/);
|
|
callback(null, result[1]);
|
|
});
|
|
}
|
|
|
|
function compileSolc(embark, contractFiles, contractDirectories, options, callback) {
|
|
if (!contractFiles || !contractFiles.length) {
|
|
return callback();
|
|
}
|
|
|
|
const logger = embark.logger;
|
|
const outputBinary = embark.pluginConfig.outputBinary;
|
|
const outputDir = embark.config.buildDir + embark.config.contractDirectories[0];
|
|
const solcConfig = embark.config.embarkConfig.options.solc;
|
|
|
|
let allowedDirectories = [];
|
|
const remappings = [];
|
|
const compilationSettings = {
|
|
language: 'Solidity',
|
|
sources: {},
|
|
settings: {
|
|
optimizer: {
|
|
enabled: solcConfig['optimize'],
|
|
runs: solcConfig['optimize-runs']
|
|
},
|
|
remappings,
|
|
outputSelection: {
|
|
'*': {
|
|
'': ['ast'],
|
|
'*': [
|
|
'abi',
|
|
'devdoc',
|
|
'evm.bytecode',
|
|
'evm.deployedBytecode',
|
|
'evm.gasEstimates',
|
|
'evm.legacyAssembly',
|
|
'evm.methodIdentifiers',
|
|
'metadata',
|
|
'userdoc'
|
|
]
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
async.waterfall([
|
|
function checkSolc(next) {
|
|
const solc = shelljs.which('solc');
|
|
if (!solc) {
|
|
logger.error('solc is not installed on your machine');
|
|
logger.info('You can install it by following the instructions on: http://solidity.readthedocs.io/en/latest/installing-solidity.html');
|
|
return next('Compiler not installed');
|
|
}
|
|
logger.info("compiling solidity contracts with command line solc...");
|
|
next();
|
|
},
|
|
|
|
function getContentAndRemappings(next) {
|
|
async.each(contractFiles, (file, eachCb) => {
|
|
file.prepareForCompilation(options.isCoverage).then((content) => {
|
|
// add contract directory and all it's recusrive import direcotries to allowed directories
|
|
let dir = path.dirname(file.path);
|
|
if (!allowedDirectories.includes(dir)) allowedDirectories.push(dir);
|
|
|
|
file.importRemappings.forEach((importRemapping) => {
|
|
dir = path.dirname(importRemapping.target);
|
|
if (!allowedDirectories.includes(dir)) allowedDirectories.push(dir);
|
|
|
|
const remapping = `${importRemapping.prefix}=${importRemapping.target}`;
|
|
if (!remappings.includes(remapping)) {
|
|
remappings.push(remapping);
|
|
}
|
|
});
|
|
|
|
compilationSettings.sources[file.path] = {
|
|
content: content.replace(/\r\n/g, '\n')
|
|
};
|
|
|
|
eachCb();
|
|
}).catch(eachCb);
|
|
}, next);
|
|
},
|
|
|
|
function compile(next) {
|
|
compileSolcContract(logger, compilationSettings, allowedDirectories, (err, compileString) => {
|
|
if (err) {
|
|
return next(err);
|
|
}
|
|
let json;
|
|
try {
|
|
json = JSON.parse(compileString);
|
|
} catch (e) {
|
|
logger.error(e.message || e);
|
|
return callback(`Compiling returned an unreadable result`);
|
|
}
|
|
const contracts = json.contracts;
|
|
|
|
// Check for errors
|
|
if (json.errors) {
|
|
let isError = false;
|
|
json.errors.forEach(error => {
|
|
if (error.severity === 'error') {
|
|
isError = true;
|
|
logger.error(error.formattedMessage);
|
|
} else {
|
|
logger.warn(error.formattedMessage);
|
|
}
|
|
});
|
|
if (isError) {
|
|
return next(`Error while compiling`);
|
|
}
|
|
}
|
|
next(null, contracts);
|
|
});
|
|
},
|
|
|
|
function populateCompiledObject(contracts, next) {
|
|
const compiledObject = {};
|
|
for (let contractFile in contracts) {
|
|
for (let contractName in contracts[contractFile]) {
|
|
let contract = contracts[contractFile][contractName];
|
|
let filename = contractFile;
|
|
const originalFilename = filename;
|
|
for (let directory of contractDirectories) {
|
|
let match = new RegExp("^" + directory);
|
|
filename = filename.replace(match, '');
|
|
}
|
|
|
|
let className = contractName;
|
|
const contractFileMatch = className.match(/.sol:(.*)/);
|
|
if (contractFileMatch) {
|
|
className = contractFileMatch[1];
|
|
}
|
|
|
|
compiledObject[className] = {};
|
|
compiledObject[className].code = contract.evm.bytecode.object;
|
|
compiledObject[className].linkReferences = contract.evm.bytecode.linkReferences;
|
|
compiledObject[className].runtimeBytecode = contract.evm.deployedBytecode.object;
|
|
compiledObject[className].realRuntimeBytecode = contract.evm.deployedBytecode.object.slice(0, -68);
|
|
compiledObject[className].swarmHash = contract.evm.deployedBytecode.object.slice(-68).slice(0, 64);
|
|
compiledObject[className].gasEstimates = contract.evm.gasEstimates;
|
|
compiledObject[className].functionHashes = contract.evm.methodIdentifiers;
|
|
compiledObject[className].abiDefinition = contract.abi;
|
|
compiledObject[className].filename = filename;
|
|
compiledObject[className].originalFilename = originalFilename;
|
|
}
|
|
}
|
|
|
|
next(null, compiledObject);
|
|
}
|
|
|
|
], (err, compiledObject) => {
|
|
callback(err, compiledObject);
|
|
|
|
if (outputBinary) {
|
|
embark.events.once("outputDone", () => {
|
|
async.eachOf(compiledObject, (contract, className, eachCb) => {
|
|
fs.writeFile(path.join(outputDir, className + ".bin"), compiledObject[className].code, eachCb);
|
|
}, (err) => {
|
|
if (err) {
|
|
logger.error("Error writing binary file", err.message || err);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
compileSolc,
|
|
compileSolcContract,
|
|
getSolcVersion
|
|
};
|