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 349a39a8db0..8decc6d5a40 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 @@ -44,6 +44,7 @@ import { getContractArtifact, getDuplicatedContractNamesDeclarationFile, } from "./artifacts.js"; +import { Cache } from "./cache.js"; import { CompilationJobImplementation } from "./compilation-job.js"; import { downloadConfiguredCompilers, getCompiler } from "./compiler/index.js"; import { buildDependencyGraph } from "./dependency-graph-building.js"; @@ -67,11 +68,16 @@ export interface SolidityBuildSystemOptions { export class SolidityBuildSystemImplementation implements SolidityBuildSystem { readonly #options: SolidityBuildSystemOptions; + readonly #compilerOutputCache: Cache; readonly #defaultConcurrenty = Math.max(os.cpus().length - 1, 1); #downloadedCompilers = false; constructor(options: SolidityBuildSystemOptions) { this.#options = options; + this.#compilerOutputCache = new Cache( + options.cachePath, + "hardhat:core:solidity:build-system:compiler-output", + ); } public async getRootFilePaths(): Promise { @@ -112,8 +118,6 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { const compilationJobs = [...new Set(compilationJobsPerFile.values())]; - // TODO: Filter the compilation jobs based on the cache - const results: CompilerOutput[] = await pMap( compilationJobs, (compilationJob) => this.runCompilationJob(compilationJob), @@ -312,6 +316,17 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { compilationJob: CompilationJob, options?: RunCompilationJobOptions, ): Promise { + if (options?.force !== true) { + const buildId = compilationJob.getBuildId(); + + const cachedCompilerOutput = + await this.#compilerOutputCache.getJson(buildId); + if (cachedCompilerOutput !== undefined) { + log(`Using cached compiler output for build ${buildId}`); + return cachedCompilerOutput; + } + } + await this.#downloadConfiguredCompilers(options?.quiet); let numberOfFiles = 0; @@ -332,7 +347,19 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem { "The long version of the compiler should match the long version of the compilation job", ); - return compiler.compile(compilationJob.getSolcInput()); + const compilerOutput = await compiler.compile( + compilationJob.getSolcInput(), + ); + + if (options?.force !== true) { + const buildId = compilationJob.getBuildId(); + + if (!this.#hasCompilationErrors(compilerOutput)) { + await this.#compilerOutputCache.setJson(buildId, compilerOutput); + } + } + + return compilerOutput; } public async remapCompilerError( 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 new file mode 100644 index 00000000000..445eec045a1 --- /dev/null +++ b/v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/cache.ts @@ -0,0 +1,32 @@ +import path from "node:path"; + +import { + exists, + readJsonFile, + writeJsonFile, +} from "@ignored/hardhat-vnext-utils/fs"; + +export class Cache { + readonly #basePath: string; + readonly #namespace: string; + + constructor(basePath: string, namespace: string) { + this.#basePath = basePath; + this.#namespace = namespace; + + console.log(`Using cache at ${this.#basePath}`); + } + + public async getJson(key: string): Promise { + const filePath = path.join(this.#basePath, this.#namespace, key); + if (await exists(filePath)) { + return readJsonFile(filePath); + } + return undefined; + } + + public async setJson(key: string, value: T): Promise { + const filePath = path.join(this.#basePath, this.#namespace, key); + await writeJsonFile(filePath, value); + } +} diff --git a/v-next/hardhat/src/types/solidity/build-system.ts b/v-next/hardhat/src/types/solidity/build-system.ts index 821622e61e9..9601b32b20e 100644 --- a/v-next/hardhat/src/types/solidity/build-system.ts +++ b/v-next/hardhat/src/types/solidity/build-system.ts @@ -62,6 +62,12 @@ export type GetCompilationJobsOptions = Omit< * The options of the `runCompilationJob` method. */ export interface RunCompilationJobOptions { + /** + * If `true`, this option foces the build system to rerun the compilation job, + * even if its output is cached. + */ + force?: boolean; + /** * If `true`, the compilation process doesn't print any output. */ @@ -265,7 +271,7 @@ export interface SolidityBuildSystem { * This method should only be used after a complete build has succeeded, as * it relies on the build system to have generated all the necessary artifact * files. - + * @param rootFilePaths All the root files of the project. */ cleanupArtifacts(rootFilePaths: string[]): Promise;