Why use `@import("root")`?

Why would someone use @import("root")?

The langref says:

@import("root") - Root source file This is usually src/main.zig but depends on what file is built. 

In my current library project, I just have a bunch of files in a folder, one of which is root.zig. And the files all reference each other using relative import statements:

├── commands.zig
├── ENI.zig
├── esc.zig
├── FrameBuilder.zig
├── mailbox
│   ├── coe
│   │   ├── client.zig
│   │   └── server.zig
│   ├── coe.zig
│   └── design.md
├── mailbox.zig
├── MainDevice.zig
├── nic.zig
├── pdi.zig
├── root.zig
├── Scanner.zig
├── sii.zig
├── SubDevice.zig
├── telegram.zig
└── wire.zig

For example:

MainDevice.zig

const std = @import("std");
const assert = std.debug.assert;

const nic = @import("nic.zig");
const wire = @import("wire.zig");
const telegram = @import("telegram.zig");
const commands = @import("commands.zig");
const esc = @import("esc.zig");
const sii = @import("sii.zig");
const SubDevice = @import("SubDevice.zig");
const ENI = @import("ENI.zig");
const pdi = @import("pdi.zig");
const FrameBuilder = @import("FrameBuilder.zig");

const MainDevice = @This();

port: *nic.Port,
settings: Settings,
eni: *const ENI,
subdevices: []SubDevice,

I guess if I was in a deeply nested file and I wanted to reference something more easily than using a bunch of ../../../../../?

As a library, you might want to access your users root module (main.zig) to look at its declarations, e.g std_options:

const root = @import("root");

/// Stdlib-wide options that can be overridden by the root file.
pub const options: Options = if (@hasDecl(root, "std_options")) root.std_options else .{};
5 Likes

However complicated a project. It should never have this depth in my opinion.
Sometimes, browsing through source, I see these deeply nested folders. You can’t find anything!

Some of my projects are completely flat, using dots in the filenames.

But… I have the same problem: I don’t like this refering to …/base/mything.zig

I think it’s more interesting for library authors, because the library can import the “root” module this way.

To be honest, I am not sure how long this will be possible because it sounds it goes a bit against what incremental compilation is trying to achieve, but I am using it for defining project-specific hooks when using my napigen library

In there, everything is generic and it has default implementation for most of the types, however, sometimes, you want to override how zig types are mapped to JS. And for that, you can define napigenRead() and napigenWrite() methods in your root module, and the napigen library is importing this module, and looking for these methods.

(Or, at least this is how it was last time I have touched this code, I have no idea if it still works with latest Zig)