diff --git a/yarn-project/noir-compiler/src/cli/contract.ts b/yarn-project/noir-compiler/src/cli/contract.ts index 20b61de076a..c01ea134626 100644 --- a/yarn-project/noir-compiler/src/cli/contract.ts +++ b/yarn-project/noir-compiler/src/cli/contract.ts @@ -69,13 +69,11 @@ export function compileContract(program: Command, name = 'contract', log: LogFn const tsPath = resolve(projectPath, typescript, `${contract.name}.ts`); log(`Writing ${contract.name} typescript interface to ${path.relative(currentDir, tsPath)}`); let relativeArtifactPath = path.relative(path.dirname(tsPath), artifactPath); - log(`Relative path: ${relativeArtifactPath}`); if (relativeArtifactPath === `${contract.name}.json`) { // relative path edge case, prepending ./ for local import - the above logic just does // `${contract.name}.json`, which is not a valid import for a file in the same directory relativeArtifactPath = `./${contract.name}.json`; } - log(`Relative path after correction: ${relativeArtifactPath}`); const tsWrapper = generateTypescriptContractInterface(contract, relativeArtifactPath); mkdirpSync(path.dirname(tsPath)); writeFileSync(tsPath, tsWrapper); diff --git a/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.test.ts b/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.test.ts index 94996a54dd2..5f9ba570d4d 100644 --- a/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.test.ts +++ b/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.test.ts @@ -18,6 +18,9 @@ describe('DependencyManager', () => { lib2: { path: '/lib2', }, + lib3: { + path: '/lib3', + }, }, package: { name: 'test_contract', @@ -38,7 +41,7 @@ describe('DependencyManager', () => { it('resolves root dependencies', async () => { await manager.resolveDependencies(); - expect(manager.getEntrypointDependencies()).toEqual(['lib1', 'lib2']); + expect(manager.getEntrypointDependencies()).toEqual(['lib1', 'lib2', 'lib3']); }); it('resolves library dependencies', async () => { @@ -75,7 +78,7 @@ class TestDependencyResolver implements NoirDependencyResolver { package: new NoirPackage('/lib2', '/lib2/src', { dependencies: { lib3: { - path: '/lib3', + path: '../lib3', }, }, package: { diff --git a/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.ts b/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.ts index 0581917f556..44bdd25743a 100644 --- a/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.ts +++ b/yarn-project/noir-compiler/src/compile/noir/dependencies/dependency-manager.ts @@ -46,7 +46,7 @@ export class NoirDependencyManager { * Resolves dependencies for a package. */ public async resolveDependencies(): Promise { - await this.#recursivelyResolveDependencies('', this.#entryPoint); + await this.#breadthFirstResolveDependencies(); } /** @@ -59,26 +59,46 @@ export class NoirDependencyManager { return dep?.version; } - async #recursivelyResolveDependencies(packageName: string, noirPackage: NoirPackage): Promise { - for (const [name, config] of Object.entries(noirPackage.getDependencies())) { - // TODO what happens if more than one package has the same name but different versions? - if (this.#libraries.has(name)) { - this.#log(`skipping already resolved dependency ${name}`); + async #breadthFirstResolveDependencies(): Promise { + /** Represents a package to resolve dependencies for */ + type Job = { + /** Package name */ + packageName: string; + /** The package location */ + noirPackage: NoirPackage; + }; + + const queue: Job[] = [ + { + packageName: '', + noirPackage: this.#entryPoint, + }, + ]; + + while (queue.length > 0) { + const { packageName, noirPackage } = queue.shift()!; + for (const [name, config] of Object.entries(noirPackage.getDependencies())) { + // TODO what happens if more than one package has the same name but different versions? + if (this.#libraries.has(name)) { + this.#log(`skipping already resolved dependency ${name}`); + this.#dependencies.set(packageName, [...(this.#dependencies.get(packageName) ?? []), name]); + + continue; + } + const dependency = await this.#resolveDependency(noirPackage, config); + if (dependency.package.getType() !== 'lib') { + this.#log(`Non-library package ${name}`, config); + throw new Error(`Dependency ${name} is not a library`); + } + + this.#libraries.set(name, dependency); this.#dependencies.set(packageName, [...(this.#dependencies.get(packageName) ?? []), name]); - continue; + queue.push({ + noirPackage: dependency.package, + packageName: name, + }); } - - const dependency = await this.#resolveDependency(noirPackage, config); - if (dependency.package.getType() !== 'lib') { - this.#log(`Non-library package ${name}`, config); - throw new Error(`Dependency ${name} is not a library`); - } - - this.#libraries.set(name, dependency); - this.#dependencies.set(packageName, [...(this.#dependencies.get(packageName) ?? []), name]); - - await this.#recursivelyResolveDependencies(name, dependency.package); } }