compile contracts in batches

one batch per compiler version needed.
This commit is contained in:
F. Eugene Aumson 2018-08-13 23:27:52 -07:00
parent 783bc873db
commit 014d71d5ae

View File

@ -131,31 +131,50 @@ export class Compiler {
} else { } else {
contractNamesToCompile = this._specifiedContracts; contractNamesToCompile = this._specifiedContracts;
} }
for (const contractNameToCompile of contractNamesToCompile) { return this._compileContractsAsync(contractNamesToCompile);
await this._compileContractAsync(contractNameToCompile);
}
} }
/** /**
* Compiles contract and saves artifact to artifactsDir. * Compiles contract and saves artifact to artifactsDir.
* @param fileName Name of contract with '.sol' extension. * @param fileName Name of contract with '.sol' extension.
*/ */
private async _compileContractAsync(contractName: string): Promise<void> { private async _compileContractsAsync(contractNames: string[]): Promise<void> {
const inputsByVersion: {
[solcVersion: string]: {
standardInput: solc.StandardInput;
contractsToCompile: string[];
};
} = {};
const contractData: {
[contractPath: string]: {
currentArtifactIfExists: ContractArtifact | void;
sourceTreeHashHex: string;
contractName: string;
};
} = {};
for (const contractName of contractNames) {
const contractSource = this._resolver.resolve(contractName); const contractSource = this._resolver.resolve(contractName);
const absoluteContractPath = path.join(this._contractsDir, contractSource.path); contractData[contractSource.path] = {
const currentArtifactIfExists = await getContractArtifactIfExistsAsync(this._artifactsDir, contractName); contractName,
const sourceTreeHashHex = `0x${this._getSourceTreeHash(absoluteContractPath).toString('hex')}`; currentArtifactIfExists: await getContractArtifactIfExistsAsync(this._artifactsDir, contractName),
sourceTreeHashHex: `0x${this._getSourceTreeHash(
path.join(this._contractsDir, contractSource.path),
).toString('hex')}`,
};
let shouldCompile = false; let shouldCompile = false;
if (_.isUndefined(currentArtifactIfExists)) { if (_.isUndefined(contractData[contractSource.path].currentArtifactIfExists)) {
shouldCompile = true; shouldCompile = true;
} else { } else {
const currentArtifact = currentArtifactIfExists as ContractArtifact; const currentArtifact = contractData[contractSource.path].currentArtifactIfExists as ContractArtifact;
const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION; const isUserOnLatestVersion = currentArtifact.schemaVersion === constants.LATEST_ARTIFACT_VERSION;
const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings); const didCompilerSettingsChange = !_.isEqual(currentArtifact.compiler.settings, this._compilerSettings);
const didSourceChange = currentArtifact.sourceTreeHashHex !== sourceTreeHashHex; const didSourceChange =
currentArtifact.sourceTreeHashHex !== contractData[contractSource.path].sourceTreeHashHex;
shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange; shouldCompile = !isUserOnLatestVersion || didCompilerSettingsChange || didSourceChange;
} }
if (!shouldCompile) { if (!shouldCompile) {
return; continue;
} }
let solcVersion = this._solcVersionIfExists; let solcVersion = this._solcVersionIfExists;
if (_.isUndefined(solcVersion)) { if (_.isUndefined(solcVersion)) {
@ -163,27 +182,47 @@ export class Compiler {
const availableCompilerVersions = _.keys(binPaths); const availableCompilerVersions = _.keys(binPaths);
solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange);
} }
const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); if (_.isUndefined(inputsByVersion[solcVersion])) {
inputsByVersion[solcVersion] = {
logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); standardInput: {
const standardInput: solc.StandardInput = { language: 'Solidity',
language: 'Solidity', sources: {},
sources: { settings: this._compilerSettings,
[contractSource.path]: {
content: contractSource.source,
}, },
}, contractsToCompile: [],
settings: this._compilerSettings, };
}; }
const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput); inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source };
return this._verifyAndPersistCompilationAsync( inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path);
contractSource, }
contractName,
fullSolcVersion, for (const solcVersion in inputsByVersion) {
compiled, if (!inputsByVersion.hasOwnProperty(solcVersion)) {
sourceTreeHashHex, continue;
currentArtifactIfExists, }
);
const input = inputsByVersion[solcVersion];
logUtils.log(
`Compiling ${input.contractsToCompile.length} contracts (${
input.contractsToCompile
}) with Solidity v${solcVersion}...`,
);
const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion);
const compiled = this._compile(solcInstance, input.standardInput);
for (const contractPath of input.contractsToCompile) {
await this._verifyAndPersistCompilationAsync(
{ path: contractPath },
contractData[contractPath].contractName,
fullSolcVersion,
compiled,
contractData[contractPath].sourceTreeHashHex,
contractData[contractPath].currentArtifactIfExists,
);
}
}
} }
private async _verifyAndPersistCompilationAsync( private async _verifyAndPersistCompilationAsync(
contractSource: { path: string }, contractSource: { path: string },