Using usingnamespace to create single namespace for many smaller files?

My pinephone API is growing quickly, and I want to better organise the
files. I just tried to assemble a single ‘api-pinephone.zig’ file,
from the many smaller SoC API .zig files.

I assumed with a .zig file just being a regular struct? the file would
just contain a list of usingnamespace @import("api-soc-part1.zig"); etc lines, but this doesnt compile.

How do I merge the smaller API .zig files into a single namespace
please? Obviously without having a single giant source file! :slight_smile:

PS I based this assumption on the documentation:

“Every Zig source file is implicitly a struct declaration; you can
imagine that the file’s contents are literally surrounded by struct {
… }.”

usingnamespace example:

const S = struct {
    usingnamespace @import("std");
};

Don’t use usingnamespace, that’s deprecated.

What I do is using ‘re-export’ files, just like in JS/TS projects.

For instance start here and look at the chipz.zig file:

…and then go down to the subdirectories, for instance:

…and look again at the chips.zig file.

(in JS/TS projects those re-export files would typically be called index.js/ts)

This import organization creates a single top-level namespace chipz with sub-namespaces chipz.common, chipz.chips, chipz.systems and chipz.host and concrete types at the leafs, for instance the gfx namespace can then be imported like this:

const gfx = @import("chipz").host.gfx;

Apart from that basic ‘re-export’ idea it’s up to you how you organize the files into actual modules, for instance in this chipz project I still expose the ‘submodules’ in addition to the top-level chipz module, those submodules are then imported within the project, while the top-level chipz module is meant to be exported to upstream projects (would actually be nice if the Zig build system had some concept of private vs public modules).

PS: if you want to hoist items from an imported file into a single flat namespace you probably need to do this item by item now… e.g. something like this:

pub const drawRect = @import("rectangle.zig").draw;
pub const drawTriangle = @import("triangle.zig").draw;

…there’s probably a trick to do that in a comptime loop, not sure.

2 Likes

Thanks, yeah some type of comptime / reflection thing might be worth a look, good idea, otherwise I was thinking a build step to append/join the files, but feels a bit yuk.

On the other hand I like your hierarchical structure. Maybe it becomes more clear as I progress, but hiding some of the gritty register stuff a bit deeper was one of the motivations, and having a simpler user API. Just a big flat directory currently whilst I hammer things out.

Good to know about not-usingnamespace thanks.

btw your project looks super interesting. I had to quickly close it before I got sucked down Z80 memory lane :slight_smile:

1 Like

I think a hierarchical namespace which is organized in ‘subsystems’ is always a good idea.

The users can then still import just the symbols they need into into their flat namespace.

E.g. example from the stdlib:

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

Thanks for the thoughts, they are already helping me clarify the design.

So I have 20+ hardware .zig files that map 1:1 to various modules of the SoC.

‘Above’ that I have my API .zig files covering features of the phone. So for example my API for temperature peeks & pokes a few different bits in the hardware layer.

But now I want to build a ‘public’ application layer API, so I do things like pp.tempC() or pp.RedLED(true). So at that layer I want something flat and simple.

Of course without ‘private’ it is all available to the hacker, but stepping outside of the top package already makes it clear there is risk.

I think what you said about just re-exporting things is probably what I wanted. Since that allows me tighter control of what appears in the public API. Maybe at some point I add some java style annotations and automate the generation of the public API, but I am just barely booting to a framebuffer at this point :slight_smile:

Thanks again for the input!

1 Like

As far as I know there is createModule which may be what you need.

2 Likes