From db3ac096cf0ac0c033f89564202b4870509e6219 Mon Sep 17 00:00:00 2001 From: galargh Date: Fri, 10 Jan 2025 16:16:45 +0100 Subject: [PATCH] wip: try moving the artifacts higher --- .../solidity/build-system/build-system.ts | 114 ++++++++++++------ .../solidity/build-system/cache.ts | 10 +- 2 files changed, 84 insertions(+), 40 deletions(-) diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/build-system.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/build-system.ts index 87195675d5..c474ea44fe 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/build-system.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/build-system.ts @@ -129,10 +129,12 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { force: options?.force, quiet: options?.quiet, }; - const results: CompilerOutput[] = await pMap( + const results: Array = await pMap( compilationJobs, - (compilationJob) => - this.runCompilationJob(compilationJob, runCompilationJobOptions), + async (compilationJob) => + (await this.#artifactsCache.has(compilationJob.getBuildId())) + ? undefined + : this.runCompilationJob(compilationJob, runCompilationJobOptions), { concurrency: options?.concurrency ?? this.#defaultConcurrenty, // An error when running the compiler is not a compilation failure, but @@ -142,7 +144,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { ); const isSuccessfulBuild = results.every( - (result) => !this.#hasCompilationErrors(result), + (result) => result === undefined || !this.#hasCompilationErrors(result), ); const contractArtifactsGeneratedByCompilationJob: Map< @@ -158,11 +160,28 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { }; await Promise.all( compilationJobs.map(async (compilationJob, i) => { - const artifactsPerFile = await this.emitArtifacts( - compilationJob, - results[i], - emitArtifactsOptions, - ); + const result = results[i]; + let artifactsPerFile; + if (result === undefined) { + const cachedFiles = await this.#artifactsCache.getFiles( + compilationJob.getBuildId(), + this.#options.artifactsPath, + ); + + assertHardhatInvariant( + cachedFiles !== undefined, + "We checked if the compilation job was cached before", + ); + + artifactsPerFile = + await this.#groupEmitArtifactsResults(cachedFiles); + } else { + artifactsPerFile = await this.emitArtifacts( + compilationJob, + result, + emitArtifactsOptions, + ); + } contractArtifactsGeneratedByCompilationJob.set( compilationJob, @@ -174,7 +193,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { const resultsMap: Map = new Map(); - for (let i = 0; i < results.length; i++) { + for (let i = 0; i < compilationJobs.length; i++) { const compilationJob = compilationJobs[i]; const result = results[i]; @@ -189,15 +208,19 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { const buildId = compilationJob.getBuildId(); - const errors = await Promise.all( - (result.errors ?? []).map((error) => - this.remapCompilerError(compilationJob, error, true), - ), - ); + const errors = + result !== undefined + ? await Promise.all( + (result.errors ?? []).map((error) => + this.remapCompilerError(compilationJob, error, true), + ), + ) + : []; this.#printSolcErrorsAndWarnings(errors); - const successfulResult = !this.#hasCompilationErrors(result); + const successfulResult = + result === undefined || !this.#hasCompilationErrors(result); for (const [publicSourceName, root] of compilationJob.dependencyGraph .getRoots() @@ -212,6 +235,17 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { continue; } + if (result === undefined) { + resultsMap.set(formatRootPath(publicSourceName, root), { + type: FileBuildResultType.CACHE_HIT, + buildId, + contractArtifactsGenerated: + contractArtifactsGenerated.get(publicSourceName) ?? [], + }); + + continue; + } + resultsMap.set(formatRootPath(publicSourceName, root), { type: FileBuildResultType.BUILD_SUCCESS, buildId, @@ -406,6 +440,32 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { }; } + async #groupEmitArtifactsResults( + filePaths: string[], + ): Promise> { + const result = new Map(); + + for (const filePath of filePaths) { + const relativePath = path.relative(this.#options.artifactsPath, filePath); + if ( + path.dirname(relativePath) === "build-info" || + path.basename(relativePath) === "artifacts.d.ts" + ) { + continue; + } + if (await isDirectory(filePath)) { + result.set(relativePath, []); + } else { + const publicSourceName = path.dirname(relativePath); + const paths = result.get(publicSourceName) ?? []; + paths.push(filePath); + result.set(publicSourceName, paths); + } + } + + return result; + } + public async emitArtifacts( compilationJob: CompilationJob, compilerOutput: CompilerOutput, @@ -421,27 +481,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { ); if (cachedFiles !== undefined) { log(`Using cached artifacts for build ${buildId}`); - for (const filePath of cachedFiles) { - const relativePath = path.relative( - this.#options.artifactsPath, - filePath, - ); - if ( - path.dirname(relativePath) === "build-info" || - path.basename(relativePath) === "artifacts.d.ts" - ) { - continue; - } - if (await isDirectory(filePath)) { - result.set(relativePath, []); - } else { - const publicSourceName = path.dirname(relativePath); - const paths = result.get(publicSourceName) ?? []; - paths.push(filePath); - result.set(publicSourceName, paths); - } - } - return result; + return this.#groupEmitArtifactsResults(cachedFiles); } } diff --git a/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/cache.ts b/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/cache.ts index 456e401620..267f954c55 100644 --- a/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/cache.ts +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/cache.ts @@ -21,6 +21,10 @@ export class Cache { return path.join(this.#basePath, this.#namespace, key); } + public async has(key: string): Promise { + return exists(this.#getPath(key)); + } + public async setJson(key: string, value: T): Promise { const filePath = this.#getPath(key); await writeJsonFile(filePath, value); @@ -28,7 +32,7 @@ export class Cache { public async getJson(key: string): Promise { const filePath = this.#getPath(key); - return (await exists(filePath)) ? readJsonFile(filePath) : undefined; + return (await this.has(key)) ? readJsonFile(filePath) : undefined; } public async setFiles( @@ -57,8 +61,8 @@ export class Cache { key: string, rootPath: string, ): Promise { - const zipFilePath = this.#getPath(key); - if (await exists(zipFilePath)) { + if (await this.has(key)) { + const zipFilePath = this.#getPath(key); const zip = new AdmZip(zipFilePath); zip.extractAllTo(rootPath, true); const filePaths = zip