From c027e1969bf2986d9a30da3951fb18d75be7af49 Mon Sep 17 00:00:00 2001 From: agra Date: Sun, 17 May 2026 13:49:25 +0300 Subject: [PATCH] stdlib: relocate modules under library/ - examples/modules/ -> library/modules/ (top-level, no more symlink hacks in consumer projects) - compiler discovers stdlib via _NSGetExecutablePath / readlink /proc/self/exe; searches dev layout (../../library), install layout (../library), and alongside-binary fallback - SX_STDLIB_PATH env var overrides for tests / dev convenience - SX_DEBUG_STDLIB env var dumps the discovery results - build.zig installs library/ alongside the binary - Compilation gains stdlib_paths field threaded through resolveImports - 50 tests pass; consumer projects can now build from any cwd --- build.zig | 10 ++ {examples => library}/modules/allocators.sx | 0 {examples => library}/modules/compiler.sx | 0 {examples => library}/modules/math/math.sx | 0 .../modules/math/matrix44.sx | 0 {examples => library}/modules/math/vector2.sx | 0 {examples => library}/modules/opengl.sx | 0 {examples => library}/modules/raylib.sx | 0 {examples => library}/modules/sdl3.sx | 0 {examples => library}/modules/socket.sx | 0 {examples => library}/modules/stb.sx | 0 {examples => library}/modules/stb_truetype.sx | 0 {examples => library}/modules/std.sx | 0 {examples => library}/modules/std/objc.sx | 0 {examples => library}/modules/std/uikit.sx | 0 {examples => library}/modules/test.sx | 0 {examples => library}/modules/test_c.sx | 0 .../modules/testpkg/cwd_test.sx | 0 .../modules/testpkg/greet.sx | 0 {examples => library}/modules/testpkg/math.sx | 0 {examples => library}/modules/wasm.sx | 0 src/core.zig | 5 +- src/imports.zig | 102 +++++++++++++++--- src/lsp/document.zig | 2 +- src/lsp/server.zig | 2 +- src/main.zig | 44 ++++---- 26 files changed, 130 insertions(+), 35 deletions(-) rename {examples => library}/modules/allocators.sx (100%) rename {examples => library}/modules/compiler.sx (100%) rename {examples => library}/modules/math/math.sx (100%) rename {examples => library}/modules/math/matrix44.sx (100%) rename {examples => library}/modules/math/vector2.sx (100%) rename {examples => library}/modules/opengl.sx (100%) rename {examples => library}/modules/raylib.sx (100%) rename {examples => library}/modules/sdl3.sx (100%) rename {examples => library}/modules/socket.sx (100%) rename {examples => library}/modules/stb.sx (100%) rename {examples => library}/modules/stb_truetype.sx (100%) rename {examples => library}/modules/std.sx (100%) rename {examples => library}/modules/std/objc.sx (100%) rename {examples => library}/modules/std/uikit.sx (100%) rename {examples => library}/modules/test.sx (100%) rename {examples => library}/modules/test_c.sx (100%) rename {examples => library}/modules/testpkg/cwd_test.sx (100%) rename {examples => library}/modules/testpkg/greet.sx (100%) rename {examples => library}/modules/testpkg/math.sx (100%) rename {examples => library}/modules/wasm.sx (100%) diff --git a/build.zig b/build.zig index 63abd4b..d381d17 100644 --- a/build.zig +++ b/build.zig @@ -158,6 +158,16 @@ pub fn build(b: *std.Build) void { b.installArtifact(exe); + // Install the stdlib alongside the binary so `/bin/sx` finds + // `/library/modules/...` via the install-layout fallback in + // `src/imports.zig::discoverStdlibPaths`. + const install_library = b.addInstallDirectory(.{ + .source_dir = b.path("library"), + .install_dir = .prefix, + .install_subdir = "library", + }); + b.getInstallStep().dependOn(&install_library.step); + const run_step = b.step("run", "Run the app"); const run_cmd = b.addRunArtifact(exe); run_step.dependOn(&run_cmd.step); diff --git a/examples/modules/allocators.sx b/library/modules/allocators.sx similarity index 100% rename from examples/modules/allocators.sx rename to library/modules/allocators.sx diff --git a/examples/modules/compiler.sx b/library/modules/compiler.sx similarity index 100% rename from examples/modules/compiler.sx rename to library/modules/compiler.sx diff --git a/examples/modules/math/math.sx b/library/modules/math/math.sx similarity index 100% rename from examples/modules/math/math.sx rename to library/modules/math/math.sx diff --git a/examples/modules/math/matrix44.sx b/library/modules/math/matrix44.sx similarity index 100% rename from examples/modules/math/matrix44.sx rename to library/modules/math/matrix44.sx diff --git a/examples/modules/math/vector2.sx b/library/modules/math/vector2.sx similarity index 100% rename from examples/modules/math/vector2.sx rename to library/modules/math/vector2.sx diff --git a/examples/modules/opengl.sx b/library/modules/opengl.sx similarity index 100% rename from examples/modules/opengl.sx rename to library/modules/opengl.sx diff --git a/examples/modules/raylib.sx b/library/modules/raylib.sx similarity index 100% rename from examples/modules/raylib.sx rename to library/modules/raylib.sx diff --git a/examples/modules/sdl3.sx b/library/modules/sdl3.sx similarity index 100% rename from examples/modules/sdl3.sx rename to library/modules/sdl3.sx diff --git a/examples/modules/socket.sx b/library/modules/socket.sx similarity index 100% rename from examples/modules/socket.sx rename to library/modules/socket.sx diff --git a/examples/modules/stb.sx b/library/modules/stb.sx similarity index 100% rename from examples/modules/stb.sx rename to library/modules/stb.sx diff --git a/examples/modules/stb_truetype.sx b/library/modules/stb_truetype.sx similarity index 100% rename from examples/modules/stb_truetype.sx rename to library/modules/stb_truetype.sx diff --git a/examples/modules/std.sx b/library/modules/std.sx similarity index 100% rename from examples/modules/std.sx rename to library/modules/std.sx diff --git a/examples/modules/std/objc.sx b/library/modules/std/objc.sx similarity index 100% rename from examples/modules/std/objc.sx rename to library/modules/std/objc.sx diff --git a/examples/modules/std/uikit.sx b/library/modules/std/uikit.sx similarity index 100% rename from examples/modules/std/uikit.sx rename to library/modules/std/uikit.sx diff --git a/examples/modules/test.sx b/library/modules/test.sx similarity index 100% rename from examples/modules/test.sx rename to library/modules/test.sx diff --git a/examples/modules/test_c.sx b/library/modules/test_c.sx similarity index 100% rename from examples/modules/test_c.sx rename to library/modules/test_c.sx diff --git a/examples/modules/testpkg/cwd_test.sx b/library/modules/testpkg/cwd_test.sx similarity index 100% rename from examples/modules/testpkg/cwd_test.sx rename to library/modules/testpkg/cwd_test.sx diff --git a/examples/modules/testpkg/greet.sx b/library/modules/testpkg/greet.sx similarity index 100% rename from examples/modules/testpkg/greet.sx rename to library/modules/testpkg/greet.sx diff --git a/examples/modules/testpkg/math.sx b/library/modules/testpkg/math.sx similarity index 100% rename from examples/modules/testpkg/math.sx rename to library/modules/testpkg/math.sx diff --git a/examples/modules/wasm.sx b/library/modules/wasm.sx similarity index 100% rename from examples/modules/wasm.sx rename to library/modules/wasm.sx diff --git a/src/core.zig b/src/core.zig index 7171430..bc24635 100644 --- a/src/core.zig +++ b/src/core.zig @@ -18,6 +18,7 @@ pub const Compilation = struct { source: [:0]const u8, diagnostics: errors.DiagnosticList, target_config: TargetConfig, + stdlib_paths: []const []const u8 = &.{}, // Pipeline results root: ?*Node = null, @@ -27,7 +28,7 @@ pub const Compilation = struct { sema_result: ?sema.SemaResult = null, ir_emitter: ?ir.LLVMEmitter = null, - pub fn init(allocator: std.mem.Allocator, io: std.Io, file_path: []const u8, source: [:0]const u8, target_config: TargetConfig) Compilation { + pub fn init(allocator: std.mem.Allocator, io: std.Io, file_path: []const u8, source: [:0]const u8, target_config: TargetConfig, stdlib_paths: []const []const u8) Compilation { return .{ .allocator = allocator, .io = io, @@ -37,6 +38,7 @@ pub const Compilation = struct { .import_sources = std.StringHashMap([:0]const u8).init(allocator), .module_scopes = std.StringHashMap(std.StringHashMap(void)).init(allocator), .target_config = target_config, + .stdlib_paths = stdlib_paths, }; } @@ -66,6 +68,7 @@ pub const Compilation = struct { &cache, &self.import_sources, &self.diagnostics, + self.stdlib_paths, ) catch return error.CompileError; // Preserve per-module visibility scopes for C import access checking diff --git a/src/imports.zig b/src/imports.zig index 3165f5b..94ef2b4 100644 --- a/src/imports.zig +++ b/src/imports.zig @@ -17,10 +17,13 @@ pub fn dirName(path: []const u8) []const u8 { return if (found) path[0..last_sep] else "."; } -/// Resolve an import path: try relative to base_dir first, fall back to cwd-relative. -/// If root_path is provided, CWD-relative fallback paths are made absolute. -/// Shared between compiler (resolveImports) and LSP (analyzeDocument). -pub fn resolveImportPath(allocator: std.mem.Allocator, io: std.Io, base_dir: []const u8, raw_path: []const u8, root_path: ?[]const u8) ![]const u8 { +/// Resolve an import path. Tries (in order): +/// 1. relative to `base_dir` (the importing file's directory) +/// 2. relative to CWD, absolutified via `root_path` if supplied +/// 3. relative to each path in `stdlib_paths` (the install-discovered stdlib) +/// Returns the first path that exists. Falls back to the raw path if nothing matches +/// so the caller's readFile produces a coherent "not found" error. +pub fn resolveImportPath(allocator: std.mem.Allocator, io: std.Io, base_dir: []const u8, raw_path: []const u8, root_path: ?[]const u8, stdlib_paths: []const []const u8) ![]const u8 { if (!std.mem.eql(u8, base_dir, ".")) { const rel_path = try std.fmt.allocPrint(allocator, "{s}/{s}", .{ base_dir, raw_path }); // Check if it exists as file relative to base_dir @@ -33,13 +36,86 @@ pub fn resolveImportPath(allocator: std.mem.Allocator, io: std.Io, base_dir: []c return rel_path; } else |_| {} } - // Fall back to raw path (cwd-relative); absolutify if root_path is known - if (root_path) |rp| { + // Try CWD-relative (absolutified if root_path is known). + const cwd_candidate = if (root_path) |rp| blk: { if (rp.len > 0 and raw_path.len > 0 and raw_path[0] != '/') { - return std.fmt.allocPrint(allocator, "{s}/{s}", .{ rp, raw_path }); + break :blk try std.fmt.allocPrint(allocator, "{s}/{s}", .{ rp, raw_path }); } + break :blk raw_path; + } else raw_path; + if (std.Io.Dir.readFileAlloc(.cwd(), io, cwd_candidate, allocator, .limited(10 * 1024 * 1024))) |_| { + return cwd_candidate; + } else |_| {} + if (std.Io.Dir.openDir(.cwd(), io, cwd_candidate, .{})) |dir| { + dir.close(io); + return cwd_candidate; + } else |_| {} + // Try each stdlib search path. + for (stdlib_paths) |sp| { + const cand = try std.fmt.allocPrint(allocator, "{s}/{s}", .{ sp, raw_path }); + if (std.Io.Dir.readFileAlloc(.cwd(), io, cand, allocator, .limited(10 * 1024 * 1024))) |_| { + return cand; + } else |_| {} + if (std.Io.Dir.openDir(.cwd(), io, cand, .{})) |dir| { + dir.close(io); + return cand; + } else |_| {} + } + return cwd_candidate; +} + +/// Discover candidate stdlib search paths from the running binary's location. +/// Honors the `SX_STDLIB_PATH` env var as an explicit override. Returns a slice +/// of absolute paths owned by the allocator. +pub fn discoverStdlibPaths(allocator: std.mem.Allocator) ![]const []const u8 { + var out = std.ArrayList([]const u8).empty; + + // Env override via libc getenv (cross-stdlib-version stable). + if (c_getenv("SX_STDLIB_PATH")) |env_path| { + try out.append(allocator, try allocator.dupe(u8, std.mem.span(env_path))); + } + + const exe_path = selfExePath(allocator) catch return try out.toOwnedSlice(allocator); + const exe_dir = dirName(exe_path); + // Stdlib paths are directories containing a `modules/` subdir; the import + // directive (e.g. `#import "modules/std.sx"`) supplies the rest. + // Dev: zig-out/bin/sx -> repo-root/library + try out.append(allocator, try std.fmt.allocPrint(allocator, "{s}/../../library", .{exe_dir})); + // Install: /bin/sx -> /library + try out.append(allocator, try std.fmt.allocPrint(allocator, "{s}/../library", .{exe_dir})); + // Alongside the binary. + try out.append(allocator, try std.fmt.allocPrint(allocator, "{s}/library", .{exe_dir})); + if (c_getenv("SX_DEBUG_STDLIB") != null) { + std.debug.print("[sx] exe_path={s}\n", .{exe_path}); + for (out.items, 0..) |p, i| std.debug.print("[sx] stdlib_paths[{d}]={s}\n", .{ i, p }); + } + return try out.toOwnedSlice(allocator); +} + +const builtin = @import("builtin"); + +extern "c" fn _NSGetExecutablePath(buf: [*]u8, len: *u32) c_int; +extern "c" fn getenv(name: [*:0]const u8) ?[*:0]const u8; + +fn c_getenv(name: [:0]const u8) ?[*:0]const u8 { + return getenv(name.ptr); +} + +fn selfExePath(allocator: std.mem.Allocator) ![]const u8 { + var buf: [4096]u8 = undefined; + switch (builtin.os.tag) { + .macos, .ios => { + var len: u32 = buf.len; + if (_NSGetExecutablePath(&buf, &len) != 0) return error.PathBufferTooSmall; + const span = std.mem.sliceTo(&buf, 0); + return try allocator.dupe(u8, span); + }, + .linux => { + const n = try std.posix.readlink("/proc/self/exe", &buf); + return try allocator.dupe(u8, n); + }, + else => return error.UnsupportedHostOS, } - return raw_path; } /// A resolved module: the fully-resolved declarations of a single .sx file, @@ -98,6 +174,7 @@ pub fn resolveImports( cache: *ModuleCache, source_map: ?*std.StringHashMap([:0]const u8), diagnostics: ?*errors.DiagnosticList, + stdlib_paths: []const []const u8, ) !ResolvedModule { var mod = ResolvedModule{ .path = file_path, @@ -167,7 +244,7 @@ pub fn resolveImports( } const imp = decl.data.import_decl; - const resolved_path = try resolveImportPath(allocator, io, base_dir, imp.path, null); + const resolved_path = try resolveImportPath(allocator, io, base_dir, imp.path, null, stdlib_paths); // Circular import check — only along the current chain if (chain.contains(resolved_path)) continue; @@ -195,7 +272,7 @@ pub fn resolveImports( // Push onto chain before recursing, pop after try chain.put(resolved_path, {}); const imp_dir = dirName(resolved_path); - const result = try resolveImports(allocator, io, imp_root, imp_dir, resolved_path, chain, cache, source_map, diagnostics); + const result = try resolveImports(allocator, io, imp_root, imp_dir, resolved_path, chain, cache, source_map, diagnostics, stdlib_paths); _ = chain.remove(resolved_path); // Cache @@ -203,7 +280,7 @@ pub fn resolveImports( break :blk result; } else |_| { // File read failed — try as directory import - const result = resolveDirectoryImport(allocator, io, resolved_path, chain, cache, source_map, diagnostics, decl.span) catch { + const result = resolveDirectoryImport(allocator, io, resolved_path, chain, cache, source_map, diagnostics, decl.span, stdlib_paths) catch { if (diagnostics) |diags| { diags.addFmt(.err, decl.span, "cannot read import '{s}' (not a file or directory)", .{resolved_path}); } @@ -235,6 +312,7 @@ fn resolveDirectoryImport( source_map: ?*std.StringHashMap([:0]const u8), diagnostics: ?*errors.DiagnosticList, span: ast.Span, + stdlib_paths: []const []const u8, ) anyerror!ResolvedModule { // Open the directory with iteration capability const dir = std.Io.Dir.openDir(.cwd(), io, dir_path, .{ .iterate = true }) catch { @@ -300,7 +378,7 @@ fn resolveDirectoryImport( }; try chain.put(file_path, {}); - const result = try resolveImports(allocator, io, imp_root, dir_path, file_path, chain, cache, source_map, diagnostics); + const result = try resolveImports(allocator, io, imp_root, dir_path, file_path, chain, cache, source_map, diagnostics, stdlib_paths); _ = chain.remove(file_path); try cache.put(file_path, result); diff --git a/src/lsp/document.zig b/src/lsp/document.zig index d40b1d5..9709c12 100644 --- a/src/lsp/document.zig +++ b/src/lsp/document.zig @@ -184,7 +184,7 @@ pub const DocumentStore = struct { for (root.data.root.decls) |decl| { if (decl.data != .import_decl) continue; const imp = decl.data.import_decl; - const resolved_path = try sx.imports.resolveImportPath(self.allocator, self.io, base_dir, imp.path, self.rootPathOpt()); + const resolved_path = try sx.imports.resolveImportPath(self.allocator, self.io, base_dir, imp.path, self.rootPathOpt(), &.{}); try import_list.append(self.allocator, .{ .ns = imp.name, .path = resolved_path, diff --git a/src/lsp/server.zig b/src/lsp/server.zig index fef5178..9912221 100644 --- a/src/lsp/server.zig +++ b/src/lsp/server.zig @@ -271,7 +271,7 @@ pub const Server = struct { if (findImportPathAtOffset(doc.source, offset)) |import_path| { const base_dir = sx.imports.dirName(file_path); const rp: ?[]const u8 = if (self.root_path.len > 0) self.root_path else null; - const resolved = try sx.imports.resolveImportPath(self.allocator, self.io, base_dir, import_path, rp); + const resolved = try sx.imports.resolveImportPath(self.allocator, self.io, base_dir, import_path, rp, &.{}); // For directory imports, try to read as file first if (std.Io.Dir.readFileAlloc(.cwd(), self.io, resolved, self.allocator, .limited(10 * 1024 * 1024))) |_| { diff --git a/src/main.zig b/src/main.zig index e934a63..8092c44 100644 --- a/src/main.zig +++ b/src/main.zig @@ -6,6 +6,10 @@ pub fn main(init: std.process.Init) !void { const io = init.io; const args = try init.minimal.args.toSlice(allocator); + // Stdlib discovered from binary location (or $SX_STDLIB_PATH override). + // Empty slice on hosts where discovery fails — imports fall back to CWD. + const stdlib_paths = sx.imports.discoverStdlibPaths(allocator) catch &[_][]const u8{}; + if (args.len < 2) { printUsage(); return; @@ -143,13 +147,13 @@ pub fn main(init: std.process.Init) !void { } break :blk base; }; - compile(allocator, io, path, output_name, target_config, show_timing, enable_cache) catch std.process.exit(1); + compile(allocator, io, path, output_name, target_config, show_timing, enable_cache, stdlib_paths) catch std.process.exit(1); } else if (std.mem.eql(u8, command, "ir")) { - emitIR(allocator, io, path, target_config) catch std.process.exit(1); + emitIR(allocator, io, path, target_config, stdlib_paths) catch std.process.exit(1); } else if (std.mem.eql(u8, command, "ir-dump")) { - dumpSxIR(allocator, io, path) catch std.process.exit(1); + dumpSxIR(allocator, io, path, stdlib_paths) catch std.process.exit(1); } else if (std.mem.eql(u8, command, "asm")) { - emitAsm(allocator, io, path, target_config) catch std.process.exit(1); + emitAsm(allocator, io, path, target_config, stdlib_paths) catch std.process.exit(1); } else if (std.mem.eql(u8, command, "run")) { if (target_config.isWasm()) { std.debug.print("error: 'run' is not supported for wasm targets. Use 'build' instead.\n", .{}); @@ -164,7 +168,7 @@ pub fn main(init: std.process.Init) !void { const source = readSource(allocator, io, path) catch std.process.exit(1); timer.record("read"); - var comp = sx.core.Compilation.init(allocator, io, path, source, target_config); + var comp = sx.core.Compilation.init(allocator, io, path, source, target_config, stdlib_paths); defer comp.deinit(); timer.mark(); @@ -239,7 +243,7 @@ pub fn main(init: std.process.Init) !void { const exit_code = sx.target.runJITFromObject(obj_buf) catch { // JIT failed — fall back to AOT timer.record("jit-fail"); - runAOT(allocator, io, path, target_config, &timer, enable_cache) catch std.process.exit(1); + runAOT(allocator, io, path, target_config, &timer, enable_cache, stdlib_paths) catch std.process.exit(1); timer.printAll(); return; }; @@ -363,12 +367,12 @@ fn readSource(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8) return try allocator.dupeZ(u8, source_bytes); } -fn compilePipeline(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing) !sx.core.Compilation { +fn compilePipeline(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing, stdlib_paths: []const []const u8) !sx.core.Compilation { timer.mark(); const source = try readSource(allocator, io, input_path); timer.record("read"); - var comp = sx.core.Compilation.init(allocator, io, input_path, source, target_config); + var comp = sx.core.Compilation.init(allocator, io, input_path, source, target_config, stdlib_paths); errdefer comp.deinit(); timer.mark(); @@ -390,9 +394,9 @@ fn compilePipeline(allocator: std.mem.Allocator, io: std.Io, input_path: []const return comp; } -fn dumpSxIR(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8) !void { +fn dumpSxIR(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, stdlib_paths: []const []const u8) !void { const source = try readSource(allocator, io, input_path); - var comp = sx.core.Compilation.init(allocator, io, input_path, source, .{}); + var comp = sx.core.Compilation.init(allocator, io, input_path, source, .{}, stdlib_paths); defer comp.deinit(); comp.parse() catch { comp.renderErrors(); return error.CompileError; }; @@ -408,16 +412,16 @@ fn dumpSxIR(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8) !v std.debug.print("{s}", .{result.items}); } -fn emitIR(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig) !void { +fn emitIR(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, stdlib_paths: []const []const u8) !void { var timer = Timing.init(io, false); - var comp = try compilePipeline(allocator, io, input_path, target_config, &timer); + var comp = try compilePipeline(allocator, io, input_path, target_config, &timer, stdlib_paths); defer comp.deinit(); comp.ir_emitter.?.printIR(); } -fn emitAsm(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig) !void { +fn emitAsm(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, stdlib_paths: []const []const u8) !void { var timer = Timing.init(io, false); - var comp = try compilePipeline(allocator, io, input_path, target_config, &timer); + var comp = try compilePipeline(allocator, io, input_path, target_config, &timer, stdlib_paths); defer comp.deinit(); const asm_path = target_config.output_path orelse blk: { const name = deriveOutputName(input_path); @@ -428,19 +432,19 @@ fn emitAsm(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, tar std.debug.print("emitted: {s}\n", .{asm_path}); } -fn compile(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, output_path: []const u8, target_config: sx.target.TargetConfig, show_timing: bool, enable_cache: bool) !void { +fn compile(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, output_path: []const u8, target_config: sx.target.TargetConfig, show_timing: bool, enable_cache: bool, stdlib_paths: []const []const u8) !void { var timer = Timing.init(io, show_timing); - try compileWithTimer(allocator, io, input_path, output_path, target_config, &timer, enable_cache); + try compileWithTimer(allocator, io, input_path, output_path, target_config, &timer, enable_cache, stdlib_paths); timer.printAll(); } -fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, output_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing, enable_cache: bool) !void { +fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, output_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing, enable_cache: bool, stdlib_paths: []const []const u8) !void { // Phase A: read + parse + resolveImports (fast: ~0.5ms) timer.mark(); const source = try readSource(allocator, io, input_path); timer.record("read"); - var comp = sx.core.Compilation.init(allocator, io, input_path, source, target_config); + var comp = sx.core.Compilation.init(allocator, io, input_path, source, target_config, stdlib_paths); defer comp.deinit(); timer.mark(); @@ -584,9 +588,9 @@ fn compileWithTimer(allocator: std.mem.Allocator, io: std.Io, input_path: []cons std.Io.Dir.deleteDir(.cwd(), io, tmp_dir) catch {}; } -fn runAOT(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing, enable_cache: bool) !void { +fn runAOT(allocator: std.mem.Allocator, io: std.Io, input_path: []const u8, target_config: sx.target.TargetConfig, timer: *Timing, enable_cache: bool, stdlib_paths: []const []const u8) !void { const tmp_bin = if (comptime @import("builtin").os.tag == .windows) "sx_run_tmp.exe" else "/tmp/sx_run_tmp"; - try compileWithTimer(allocator, io, input_path, tmp_bin, target_config, timer, enable_cache); + try compileWithTimer(allocator, io, input_path, tmp_bin, target_config, timer, enable_cache, stdlib_paths); defer { std.Io.Dir.deleteFile(.cwd(), io, tmp_bin) catch {}; }