embark-solc/lib/Compiler.js

154 lines
4.8 KiB
JavaScript
Raw Normal View History

2018-05-26 12:31:46 -04:00
const async = require('async');
const shelljs = require('shelljs');
const fs = require('fs');
2018-07-23 15:14:03 -04:00
const path = require('path');
2018-05-26 12:31:46 -04:00
function compileSolcContract(logger, file, allowedDirectories, solcConfig, callback) {
let input = {};
const remappings = file.importRemappings.map((mapping) => `${path.dirname(file.filename)}:${mapping.prefix}=${mapping.target}`);
const filename = file.pluginPath ? path.join(file.pluginPath, file.filename) : file.filename;
input[filename] = {content: shelljs.cat(filename).replace(/\r\n/g, '\n'), path: filename};
let jsonObj = {
language: 'Solidity',
sources: input,
settings: {
optimizer: {
enabled: solcConfig['optimize'],
runs: solcConfig['optimize-runs']
},
outputSelection: {
'*': {
'': ['ast'],
'*': [
'abi',
'devdoc',
'evm.bytecode',
'evm.deployedBytecode',
'evm.gasEstimates',
'evm.legacyAssembly',
'evm.methodIdentifiers',
'metadata',
'userdoc'
]
}
}
}
};
const command = `solc --standard-json --allow-paths ${allowedDirectories.join(',')} ${remappings.join(' ')}`;
shelljs.ShellString(JSON.stringify(jsonObj)).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) => {
2018-05-26 12:31:46 -04:00
if (stderr) {
logger.warn(stderr);
}
if (code !== 0) {
return callback(`solc exited with error code ${code}`);
}
if (!stdout) {
return callback('solc execution returned nothing');
2018-05-26 12:31:46 -04:00
}
const result = stdout.match(/(\d+.\d+.\d+)/);
callback(null, result[1]);
});
}
function compileSolc(embark, contractFiles, cb) {
2018-05-26 12:31:46 -04:00
if (!contractFiles || !contractFiles.length) {
return cb();
}
2018-05-30 15:52:42 -04:00
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;
2018-05-30 15:52:42 -04:00
const solc = shelljs.which('solc');
if (!solc) {
2018-09-12 09:38:03 -04:00
logger.error('solc is not installed on your machine');
2018-05-30 15:52:42 -04:00
logger.info('You can install it by following the instructions on: http://solidity.readthedocs.io/en/latest/installing-solidity.html');
2018-09-12 09:38:03 -04:00
return cb('Compiler not installed');
2018-05-30 15:52:42 -04:00
}
2018-05-26 12:31:46 -04:00
logger.info("compiling solidity contracts with command line solc...");
const allowedDirectories = contractFiles.map((contractFile) => path.dirname(contractFile.path))
.filter((x, i, a) => a.indexOf(x) === i);
2018-05-26 12:31:46 -04:00
let compiled_object = {};
async.each(contractFiles,
function (file, callback) {
compileSolcContract(logger, file, allowedDirectories, solcConfig, (err, compileString) => {
2018-05-26 12:31:46 -04:00
if (err) {
return callback(err);
2018-05-26 12:31:46 -04:00
}
let json = JSON.parse(compileString).contracts;
2018-05-30 15:52:42 -04:00
for (let contractFile in json) {
for (let contractName in json[contractFile]) {
let contract = json[contractFile][contractName];
2018-05-26 12:31:46 -04:00
const className = contractName;
const filename = contractFile;
2018-07-24 13:37:59 -04:00
compiled_object[className] = {};
compiled_object[className].code = contract.evm.bytecode.object;
compiled_object[className].runtimeBytecode = contract.evm.deployedBytecode.object;
compiled_object[className].realRuntimeBytecode = contract.evm.deployedBytecode.object.slice(0, -68);
compiled_object[className].swarmHash = contract.evm.deployedBytecode.object.slice(-68).slice(0, 64);
compiled_object[className].gasEstimates = contract.evm.gasEstimates;
compiled_object[className].functionHashes = contract.evm.methodIdentifiers;
compiled_object[className].abiDefinition = contract.abi;
compiled_object[className].filename = filename;
}
2018-05-26 12:31:46 -04:00
}
callback();
2018-05-26 12:31:46 -04:00
});
},
function (err) {
cb(err, compiled_object);
2018-07-23 15:14:03 -04:00
if(outputBinary){
embark.events.on("outputDone", function() {
Object.keys(compiled_object).map(function(className, _index) {
2018-09-21 15:41:22 -04:00
fs.writeFile(path.join(outputDir, className + ".bin"), compiled_object[className].code, (err) => {
2018-07-23 13:29:13 -04:00
if (err) {
logger.error("Error writing binary file: " + JSON.stringify(err));
}
});
});
2018-07-23 15:14:03 -04:00
});
}
2018-05-26 12:31:46 -04:00
});
}
module.exports = {
compileSolc,
compileSolcContract,
getSolcVersion
2018-05-26 12:31:46 -04:00
};