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!
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");
};
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:
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
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