Skip to content

Commit 6fb3c27

Browse files
committed
Introduce multi-compiler abstraction with SolidityCompilerConfig base interface
1 parent acb1384 commit 6fb3c27

File tree

15 files changed

+479
-73
lines changed

15 files changed

+479
-73
lines changed

.changeset/cold-deer-buy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"hardhat": patch
3+
---
4+
5+
Introduce multi-compiler abstraction with SolidityCompilerConfig base interface

v-next/hardhat/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"./console.sol": "./console.sol",
4040
"./internal/coverage": "./dist/src/internal/builtin-plugins/coverage/exports.js",
4141
"./internal/gas-analytics": "./dist/src/internal/builtin-plugins/gas-analytics/exports.js",
42+
"./internal/solidity": "./dist/src/internal/builtin-plugins/solidity/exports.js",
4243
"./utils/contract-names": "./dist/src/utils/contract-names.js",
4344
"./utils/result": "./dist/src/utils/result.js",
4445
"./types/runtime": "./dist/src/internal/deprecated-module-imported-from-hardhat2-plugin.js",

v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/build-system.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import type { CompileCache } from "./cache.js";
22
import type { DependencyGraphImplementation } from "./dependency-graph.js";
33
import type { Artifact } from "../../../../types/artifacts.js";
4-
import type { SolcConfig, SolidityConfig } from "../../../../types/config.js";
4+
import type {
5+
SolidityCompilerConfig,
6+
SolcConfig,
7+
SolidityConfig,
8+
} from "../../../../types/config.js";
59
import type { HookManager } from "../../../../types/hooks.js";
610
import type {
711
SolidityBuildSystem,
@@ -79,14 +83,26 @@ import { shouldSuppressWarning } from "./warning-suppression.js";
7983
const log = debug("hardhat:core:solidity:build-system");
8084

8185
/**
82-
* Resolves the preferWasm setting for a given solc config, falling back
86+
* Returns true if the given compiler config is a SolcConfig.
87+
*/
88+
export function isSolcConfig(
89+
config: SolidityCompilerConfig,
90+
): config is SolcConfig {
91+
return config.type === undefined || config.type === "solc";
92+
}
93+
94+
/**
95+
* Resolves the preferWasm setting for a given compiler config, falling back
8396
* to the build profile's preferWasm if not set on the compiler.
8497
*/
8598
function resolvePreferWasm(
86-
solcConfig: SolcConfig,
99+
compilerConfig: SolidityCompilerConfig,
87100
buildProfilePreferWasm: boolean,
88101
): boolean {
89-
return solcConfig.preferWasm ?? buildProfilePreferWasm;
102+
if (isSolcConfig(compilerConfig)) {
103+
return compilerConfig.preferWasm ?? buildProfilePreferWasm;
104+
}
105+
return false;
90106
}
91107

92108
// Compiler warnings to suppress from build output.
@@ -439,7 +455,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
439455
);
440456

441457
let subgraphsWithConfig: Array<
442-
[SolcConfig, DependencyGraphImplementation]
458+
[SolidityCompilerConfig, DependencyGraphImplementation]
443459
> = [];
444460
for (const [rootFile, resolvedFile] of dependencyGraph.getRoots()) {
445461
log(
@@ -576,7 +592,7 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
576592
log(`Merging compilation jobs`);
577593

578594
const mergedSubgraphsByConfig: Map<
579-
SolcConfig,
595+
SolidityCompilerConfig,
580596
DependencyGraphImplementation
581597
> = new Map();
582598

@@ -692,10 +708,18 @@ export class SolidityBuildSystemImplementation implements SolidityBuildSystem {
692708
`Compiling ${numberOfRootFiles} root files and ${numberOfFiles - numberOfRootFiles} dependency files with solc ${runnableCompilationJob.solcConfig.version} using ${compiler.compilerPath}`,
693709
);
694710

695-
assertHardhatInvariant(
696-
runnableCompilationJob.solcLongVersion === compiler.longVersion,
697-
"The long version of the compiler should match the long version of the compilation job",
698-
);
711+
// For custom compilers (path set), compare short version only (long version may differ)
712+
if (runnableCompilationJob.solcConfig.path !== undefined) {
713+
assertHardhatInvariant(
714+
runnableCompilationJob.solcConfig.version === compiler.version,
715+
"The version of the compiler should match the version of the compilation job",
716+
);
717+
} else {
718+
assertHardhatInvariant(
719+
runnableCompilationJob.solcLongVersion === compiler.longVersion,
720+
"The long version of the compiler should match the long version of the compilation job",
721+
);
722+
}
699723

700724
const input = await runnableCompilationJob.getSolcInput();
701725

v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/compilation-job.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { DependencyGraphImplementation } from "./dependency-graph.js";
22
import type { BuildInfo } from "../../../../types/artifacts.js";
3-
import type { SolcConfig } from "../../../../types/config.js";
3+
import type { SolidityCompilerConfig } from "../../../../types/config.js";
44
import type { HookManager } from "../../../../types/hooks.js";
55
import type { CompilationJob } from "../../../../types/solidity/compilation-job.js";
66
import type { CompilerInput } from "../../../../types/solidity/compiler-io.js";
@@ -21,7 +21,7 @@ import { getEvmVersionFromSolcVersion } from "./solc-info.js";
2121

2222
export class CompilationJobImplementation implements CompilationJob {
2323
public readonly dependencyGraph: DependencyGraph;
24-
public readonly solcConfig: SolcConfig;
24+
public readonly solcConfig: SolidityCompilerConfig;
2525
public readonly solcLongVersion: string;
2626

2727
readonly #hooks: HookManager;
@@ -34,7 +34,7 @@ export class CompilationJobImplementation implements CompilationJob {
3434

3535
constructor(
3636
dependencyGraph: DependencyGraphImplementation,
37-
solcConfig: SolcConfig,
37+
solcConfig: SolidityCompilerConfig,
3838
solcLongVersion: string,
3939
hooks: HookManager,
4040
sharedContentHashes: Map<string, string> = new Map(),

v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/compiler/compiler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import * as semver from "semver";
3939
* @throws Error if the compilation process exits with a non-zero exit code.
4040
* @throws HardhatInvariantError if the any of the io streams are null.
4141
*/
42-
async function spawnCompile(
42+
export async function spawnCompile(
4343
command: string,
4444
args: string[],
4545
input: CompilerInput,

v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/compiler/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,10 @@ async function getCompilerFromPath(
129129

130130
log(`Version output: ${stdout}`);
131131

132-
const match = stdout.match(/(?<longVersion>\d+\.\d+\.\d+\+commit\.\w+)/);
132+
// Match solc-style version (with +commit hash) or plain semver (for non-solc compilers)
133+
const match =
134+
stdout.match(/(?<longVersion>\d+\.\d+\.\d+\+commit\.\w+)/) ??
135+
stdout.match(/(?<shortVersion>\d+\.\d+\.\d+)/);
133136

134137
if (match === null || match.groups === undefined) {
135138
throw new HardhatError(
@@ -138,7 +141,8 @@ async function getCompilerFromPath(
138141
);
139142
}
140143

141-
const { longVersion } = match.groups;
144+
const longVersion =
145+
match.groups.longVersion ?? `${match.groups.shortVersion}+custom`;
142146

143147
log(`Long version: ${longVersion}`);
144148

v-next/hardhat/src/internal/builtin-plugins/solidity/build-system/solc-config-selection.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type {
2-
SolcConfig,
2+
SolidityCompilerConfig,
33
SolidityBuildProfileConfig,
44
} from "../../../../types/config.js";
55
import type { CompilationJobCreationError } from "../../../../types/solidity/build-system.js";
@@ -44,7 +44,7 @@ export class SolcConfigSelector {
4444
*/
4545
public selectBestSolcConfigForSingleRootGraph(
4646
subgraph: DependencyGraph,
47-
): { success: true; config: SolcConfig } | CompilationJobCreationError {
47+
): { success: true; config: SolidityCompilerConfig } | CompilationJobCreationError {
4848
const roots = subgraph.getRoots();
4949

5050
assertHardhatInvariant(

v-next/hardhat/src/internal/builtin-plugins/solidity/config.ts

Lines changed: 50 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { HardhatUserConfig } from "../../../config.js";
22
import type {
3+
SolidityCompilerConfig,
4+
SolidityCompilerUserConfig,
35
HardhatConfig,
46
MultiVersionSolidityUserConfig,
57
SingleVersionSolidityUserConfig,
@@ -39,6 +41,7 @@ const commonSolcUserConfigType = z.object({
3941
});
4042

4143
const solcUserConfigType = z.object({
44+
type: z.string().optional(),
4245
version: z.string(),
4346
settings: z.any().optional(),
4447
path: z.string().optional(),
@@ -291,7 +294,7 @@ function resolveBuildProfileConfig(
291294
): SolidityBuildProfileConfig {
292295
if ("version" in solidityConfig) {
293296
return {
294-
compilers: [resolveSolcConfig(solidityConfig, production)],
297+
compilers: [resolveSolidityCompilerConfig(solidityConfig, production)],
295298
overrides: {},
296299
isolated: solidityConfig.isolated ?? production,
297300
preferWasm: solidityConfig.preferWasm ?? false,
@@ -300,13 +303,13 @@ function resolveBuildProfileConfig(
300303

301304
return {
302305
compilers: solidityConfig.compilers.map((compiler) =>
303-
resolveSolcConfig(compiler, production),
306+
resolveSolidityCompilerConfig(compiler, production),
304307
),
305308
overrides: Object.fromEntries(
306309
Object.entries(solidityConfig.overrides ?? {}).map(
307310
([userSourceName, override]) => [
308311
userSourceName,
309-
resolveSolcConfig(override, production),
312+
resolveSolidityCompilerConfig(override, production),
310313
],
311314
),
312315
),
@@ -315,11 +318,11 @@ function resolveBuildProfileConfig(
315318
};
316319
}
317320

318-
function resolveSolcConfig(
319-
solcConfig: SolcUserConfig,
321+
function resolveSolidityCompilerConfig(
322+
compilerConfig: SolidityCompilerUserConfig,
320323
production: boolean = false,
321-
): SolcConfig {
322-
const defaultSolcConfigSettings: SolcConfig["settings"] = {
324+
): SolidityCompilerConfig {
325+
const defaultSettings: SolidityCompilerConfig["settings"] = {
323326
outputSelection: {
324327
"*": {
325328
"": ["ast"],
@@ -335,32 +338,54 @@ function resolveSolcConfig(
335338
};
336339

337340
if (production) {
338-
defaultSolcConfigSettings.optimizer = {
341+
defaultSettings.optimizer = {
339342
enabled: true,
340343
runs: 200,
341344
};
342345
}
343346

344-
// Resolve per-compiler preferWasm:
345-
// If explicitly set, use that value.
346-
// Otherwise, for ARM64 Linux in production, default to true only for
347-
// versions without official ARM64 builds.
348-
let resolvedPreferWasm: boolean | undefined = solcConfig.preferWasm;
349-
if (resolvedPreferWasm === undefined && missesSomeOfficialNativeBuilds()) {
350-
resolvedPreferWasm =
351-
production && !hasOfficialArm64Build(solcConfig.version)
352-
? true
353-
: undefined;
347+
const resolvedSettings = deepMerge(
348+
defaultSettings,
349+
compilerConfig.settings ?? {},
350+
);
351+
352+
// Resolve solc-specific preferWasm if this is a SolcUserConfig
353+
if (isSolcUserConfig(compilerConfig)) {
354+
// Resolve per-compiler preferWasm:
355+
// If explicitly set, use that value.
356+
// Otherwise, for ARM64 Linux in production, default to true only for
357+
// versions without official ARM64 builds.
358+
let resolvedPreferWasm: boolean | undefined = compilerConfig.preferWasm;
359+
if (resolvedPreferWasm === undefined && missesSomeOfficialNativeBuilds()) {
360+
resolvedPreferWasm =
361+
production && !hasOfficialArm64Build(compilerConfig.version)
362+
? true
363+
: undefined;
364+
}
365+
const solcResolved: SolcConfig = {
366+
type: compilerConfig.type,
367+
version: compilerConfig.version,
368+
settings: resolvedSettings,
369+
path: compilerConfig.path,
370+
preferWasm: resolvedPreferWasm,
371+
};
372+
return solcResolved;
354373
}
355374

356375
return {
357-
version: solcConfig.version,
358-
settings: deepMerge(defaultSolcConfigSettings, solcConfig.settings ?? {}),
359-
path: solcConfig.path,
360-
preferWasm: resolvedPreferWasm,
376+
type: compilerConfig.type,
377+
version: compilerConfig.version,
378+
settings: resolvedSettings,
379+
path: compilerConfig.path,
361380
};
362381
}
363382

383+
function isSolcUserConfig(
384+
config: SolidityCompilerUserConfig,
385+
): config is SolcUserConfig {
386+
return config.type === undefined || config.type === "solc";
387+
}
388+
364389
function copyFromDefault(
365390
defaultSolidityConfig:
366391
| SingleVersionSolidityUserConfig
@@ -369,18 +394,20 @@ function copyFromDefault(
369394
if ("version" in defaultSolidityConfig) {
370395
return {
371396
version: defaultSolidityConfig.version,
397+
type: defaultSolidityConfig.type,
372398
};
373399
}
374400

375401
return {
376402
compilers: defaultSolidityConfig.compilers.map((c) => ({
377403
version: c.version,
404+
type: c.type,
378405
})),
379406
overrides: Object.fromEntries(
380407
Object.entries(defaultSolidityConfig.overrides ?? {}).map(
381408
([userSourceName, override]) => [
382409
userSourceName,
383-
{ version: override.version },
410+
{ version: override.version, type: override.type },
384411
],
385412
),
386413
),
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { isSolcConfig } from "./build-system/build-system.js";
2+
export { spawnCompile } from "./build-system/compiler/compiler.js";

v-next/hardhat/src/internal/builtin-plugins/solidity/type-extensions.ts

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { SolcConfig } from "../../../types/config.js";
1+
import type { SolidityCompilerConfig } from "../../../types/config.js";
22
import type {
33
BuildOptions,
44
CompilationJobCreationError,
@@ -20,10 +20,14 @@ declare module "../../../types/config.js" {
2020
| MultiVersionSolidityUserConfig
2121
| BuildProfilesSolidityUserConfig;
2222

23-
export interface SolcUserConfig {
23+
export interface SolidityCompilerUserConfig {
24+
type?: string;
2425
version: string;
2526
settings?: any;
2627
path?: string;
28+
}
29+
30+
export interface SolcUserConfig extends SolidityCompilerUserConfig {
2731
preferWasm?: boolean;
2832
}
2933

@@ -35,8 +39,8 @@ declare module "../../../types/config.js" {
3539
export interface MultiVersionSolcUserConfig {
3640
isolated?: boolean;
3741
preferWasm?: boolean;
38-
compilers: SolcUserConfig[];
39-
overrides?: Record<string, SolcUserConfig>;
42+
compilers: Array<SolcUserConfig | SolidityCompilerUserConfig>;
43+
overrides?: Record<string, SolcUserConfig | SolidityCompilerUserConfig>;
4044
}
4145

4246
export interface CommonSolidityUserConfig {
@@ -63,18 +67,22 @@ declare module "../../../types/config.js" {
6367
solidity?: SolidityUserConfig;
6468
}
6569

66-
export interface SolcConfig {
70+
export interface SolidityCompilerConfig {
71+
type?: string;
6772
version: string;
6873
settings: any;
6974
path?: string;
75+
}
76+
77+
export interface SolcConfig extends SolidityCompilerConfig {
7078
preferWasm?: boolean;
7179
}
7280

7381
export interface SolidityBuildProfileConfig {
7482
isolated: boolean;
7583
preferWasm: boolean;
76-
compilers: SolcConfig[];
77-
overrides: Record<string, SolcConfig>;
84+
compilers: SolidityCompilerConfig[];
85+
overrides: Record<string, SolidityCompilerConfig>;
7886
}
7987

8088
export interface SolidityConfig {
@@ -234,12 +242,12 @@ declare module "../../../types/hooks.js" {
234242
context: HookContext,
235243
compiler: Compiler,
236244
solcInput: CompilerInput,
237-
solcConfig: SolcConfig,
245+
compilerConfig: SolidityCompilerConfig,
238246
next: (
239247
nextContext: HookContext,
240248
nextCompiler: Compiler,
241249
nextSolcInput: CompilerInput,
242-
nextSolcConfig: SolcConfig,
250+
nextSolidityCompilerConfig: SolidityCompilerConfig,
243251
) => Promise<CompilerOutput>,
244252
): Promise<CompilerOutput>;
245253

0 commit comments

Comments
 (0)