Skip to content

Conversation

@Techatrix
Copy link
Member

ZLS had an inaccurate view of how modules work in the build system. It would previously merge every module in the entire build graph into one single module which can easily lead to incorrect results in any non trivial project that contains multiple modules. This PR will keep track of each individual module so that analysis can differentiate between them just like how the compiler does it.

Some examples of what has been improved:

  • @import("root") now actually figures out in which module a given file is in.
  • auto complete for @import will only show the modules that have been directly added to the module that the current file belongs to
  • @import("some_name") will resolve the correct module if there are multiple modules that have imported different modules with "some_name" as their name.

One issue this PR doesn't fully address is when there are multiple modules with the same root source file that have conflicting definitions. This is only achievable using multiple compilation units because Zig fortunately disallows sharing a root source file within a single compilation unit.

Related PR #2308

@Techatrix Techatrix force-pushed the techatrix/model-build-system branch 2 times, most recently from 725af1e to 31481f3 Compare November 19, 2025 19:41
@dotcarmen
Copy link
Contributor

@import("root") now actually figures out in which module a given file is in.

fyi - it seems that can't really be relied upon

https://gist.github.com/dotcarmen/7f186613f1f839427a839c33306af9dd <- the output is:

hello, world!
exe says hello

what happens when a module is imported by multiple roots? i think it's best to not resolve @import("root") to anything to avoid any footguns

@Techatrix Techatrix force-pushed the techatrix/model-build-system branch from 31481f3 to fa96d31 Compare December 5, 2025 21:33
@Techatrix
Copy link
Member Author

fyi - it seems that can't really be relied upon

https://gist.github.com/dotcarmen/7f186613f1f839427a839c33306af9dd <- the output is:

I turns out that I have misunderstood the semantic of @import("root") as I assumed it would be the root source file a given file is inside but it is root source file of the compilation unit(s) a given file is in. I have updated the PR to handle this which should fix the issue in the example you provided.

what happens when a module is imported by multiple roots?

Resolve it to all of them. ZLS has something called "either types" that can be used to represent a type that can be one of a given set of types but it's unknown which one it will be.

So const root = @import("root") would be internally represented as:

const root = switch (unknown) {
    0 => @import("main.zig"),
    1 => @import("main2.zig"),
};

If main.zig and main2.zig if both root modules that import the file we are in.

complete example: https://gist.github.com/Techatrix/80b625e5965ca6177ff4360713ffded3

@dotcarmen
Copy link
Contributor

dotcarmen commented Dec 9, 2025

i've been running this build pretty successfully, however, as of 0.16.0-dev.1484+d0ba6642b, i'm getting an error about LazyPath.getPath being called during the configure phase

this only occurred after i added b.addTranslateC step

const gop_import = try gop.value_ptr.import_table.map.getOrPut(allocator, name);
// This does not account for the possibility of collisions (i.e. modules with same root source file import different modules under the same name).
if (!gop_import.found_existing) {
gop_import.value_ptr.* = try std.fs.path.resolve(allocator, &.{ cwd, import.root_source_file.?.getPath2(import.owner, null) });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the line that results in the aforementioned panic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants