import std; import Crafter.Build; namespace fs = std::filesystem; using namespace Crafter; // Two-config build: an exe linked against a sibling static library via // cfg.dependencies. Exercises cross-config module import resolution (the // exe imports Calc, which is defined in the lib's interface set) and the // dep-archive linking step. int main() { fs::path fixtureRoot = fs::current_path() / "tests" / "DependencyLink" / "fixture"; auto lib = std::make_unique(); lib->path = fixtureRoot / "mathlib"; lib->name = "calc"; lib->outputName = "calc"; lib->target = HostTarget(); lib->type = ConfigurationType::LibraryStatic; { std::array ifaces = { "Calc" }; std::array impls = {}; lib->GetInterfacesAndImplementations(ifaces, impls); } Configuration app; app.path = fixtureRoot; app.name = "calc-app"; app.outputName = "calc-app"; app.target = HostTarget(); app.type = ConfigurationType::Executable; app.dependencies = { lib.get() }; { std::array ifaces = {}; std::array impls = { "main" }; app.GetInterfacesAndImplementations(ifaces, impls); } if (app.implementations.size() != 1) { std::println(std::cerr, "expected 1 implementation, got {}", app.implementations.size()); return 1; } // The import resolves to the dependency's interface, not a local one. if (!app.implementations[0].moduleDependencies.empty()) { std::println(std::cerr, "expected no local module deps, got {}", app.implementations[0].moduleDependencies.size()); return 1; } if (app.implementations[0].externalModuleDependencies.size() != 1) { std::println(std::cerr, "expected 1 external module dep, got {}", app.implementations[0].externalModuleDependencies.size()); return 1; } if (app.implementations[0].externalModuleDependencies[0].first->name != "Calc") { std::println(std::cerr, "expected external dep 'Calc', got '{}'", app.implementations[0].externalModuleDependencies[0].first->name); return 1; } std::unordered_map> depResults; std::mutex depMutex; BuildResult r = Build(app, depResults, depMutex); if (!r.result.empty()) { std::println(std::cerr, "build failed: {}", r.result); return 1; } fs::path libArchive = lib->BinDir() / "libcalc.a"; if (!fs::exists(libArchive)) { std::println(std::cerr, "dep archive not produced at {}", libArchive.string()); return 1; } fs::path bin = app.BinDir() / "calc-app"; if (!fs::exists(bin)) { std::println(std::cerr, "binary not produced at {}", bin.string()); return 1; } auto run = RunCommandWithTimeout(bin.string(), std::chrono::seconds(10)); if (run.exitCode != 0 || run.timedOut || run.crashed) { std::println(std::cerr, "exe did not exit cleanly: exit={} output={}", run.exitCode, run.output); return 1; } if (run.output != "7") { std::println(std::cerr, "expected '7', got '{}'", run.output); return 1; } return 0; }