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,28 +182,48 @@ export class Compiler {
const availableCompilerVersions = _.keys(binPaths); const availableCompilerVersions = _.keys(binPaths);
solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange); solcVersion = semver.maxSatisfying(availableCompilerVersions, solcVersionRange);
} }
if (_.isUndefined(inputsByVersion[solcVersion])) {
inputsByVersion[solcVersion] = {
standardInput: {
language: 'Solidity',
sources: {},
settings: this._compilerSettings,
},
contractsToCompile: [],
};
}
inputsByVersion[solcVersion].standardInput.sources[contractSource.path] = { content: contractSource.source };
inputsByVersion[solcVersion].contractsToCompile.push(contractSource.path);
}
for (const solcVersion in inputsByVersion) {
if (!inputsByVersion.hasOwnProperty(solcVersion)) {
continue;
}
const input = inputsByVersion[solcVersion];
logUtils.log(
`Compiling ${input.contractsToCompile.length} contracts (${
input.contractsToCompile
}) with Solidity v${solcVersion}...`,
);
const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion); const { solcInstance, fullSolcVersion } = await getSolcAsync(solcVersion);
logUtils.log(`Compiling ${contractName} with Solidity v${solcVersion}...`); const compiled = this._compile(solcInstance, input.standardInput);
const standardInput: solc.StandardInput = {
language: 'Solidity', for (const contractPath of input.contractsToCompile) {
sources: { await this._verifyAndPersistCompilationAsync(
[contractSource.path]: { { path: contractPath },
content: contractSource.source, contractData[contractPath].contractName,
},
},
settings: this._compilerSettings,
};
const compiled: solc.StandardOutput = this._compile(solcInstance, standardInput);
return this._verifyAndPersistCompilationAsync(
contractSource,
contractName,
fullSolcVersion, fullSolcVersion,
compiled, compiled,
sourceTreeHashHex, contractData[contractPath].sourceTreeHashHex,
currentArtifactIfExists, contractData[contractPath].currentArtifactIfExists,
); );
} }
}
}
private async _verifyAndPersistCompilationAsync( private async _verifyAndPersistCompilationAsync(
contractSource: { path: string }, contractSource: { path: string },
contractName: string, contractName: string,