Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build a proper portable Zig build (zig upstream issue!?) #1873

Open
plajjan opened this issue Aug 27, 2024 · 1 comment
Open

Build a proper portable Zig build (zig upstream issue!?) #1873

plajjan opened this issue Aug 27, 2024 · 1 comment
Labels
build system enhancement New feature or request

Comments

@plajjan
Copy link
Contributor

plajjan commented Aug 27, 2024

Acton uses the Zig build system to do the low level build. The acton compiler first does its compilation passes and produces .c / .h output, which is then fed into the Zig build system. There are currently two ways in which zig build is run by the acton compiler:

  • for "persistent" projects, where we do essentially a vanilla zig build after generating a build.zig file
  • for compilation of standalone .act files, where we have our own hacked up build builder executable and just run that
    This issue is about trying to reduce the hackery for the second case. We prefer to align on the idiomatic Zig ways.

All Acton projects (how Acton source code is organized) look quite similar. They have a src/ directory with Acton source code and a out/types directory where the generated .c / .h files are stored. out/bin is for outputted binaries (where zig is told to put them). Projects that have dependencies are a tad more complex and we generate the build.zig and build.zig.zon customized per such project. The initial compilation of build_runner.zig + build.zig -> build executable takes time, which is acceptable, since it is then cached so subsequent runs is very fast.

Acton supports compiling standalone .act files, like you have ~/foo.act in your home dir and you can run acton foo.act to compile this into an executable binary. Under the hood, this works by creating a temporary directory like /tmp/actonc-123456 and creating a project structure in there, so we have /tmp/actonc-123456/src and compiled output goes into /tmp/actonc-123456/out/types etc. The challenge here is that if we generate a /tmp/actonc-123456/build.zig, it will first be compiled which can take upwards of 10 seconds. Unlike normal projects that are relatively persistent, these temporary projects used for standalone .act file compilation are completely ephemeral. Each compilation run will thus take at least 10 seconds and this is just not a very nice experience at all. Since compilation of standalone .act files is completely uniform (no dependencies or other things that make the build.zig unique), it really should be possible to cache, but I think Zig doesn't realize it is since the paths are always unique. Can we hint / lie to the caching system somehow, like "hey, look at the checksum of this file, you really do have it cached already". This is still problematic due to dependencies absolute paths though, see below...

(AFAIK) The build executable is produced by taking build_runner.zig and adding in the local build.zig file, so the build_runner can reach the build function in the build.zig module. A dependencies.zig file is generated and injected that contains Zig structs with all the dependencies. This file is normally generated by the zig compiler from build.zig.zon. Instead, we have our own hard-coded dependencies.zig. The big difference is that the zig compiler turns relative paths in build.zig.zon into absolute ones when it produces dependencies.zig and later the build executable, i.e. the build executable is hard-coded for some absolute paths, which makes it impossible to reuse for our temporary projects. By injecting our own dependencies.zig, we can use relative paths. Since we actually do run in various different directories and need to reach things outside of the local directory, we use symlinks to take us to the right place. The acton compiler creates these symlinks as necessary to guarantee that the zig builder runs in a "known environment".

Solutions I can think of

  • zig build to be so fast that compiling the build executable is instant and thus this whole problem goes away
  • can paths be relative in dependencies.zig to the build root (where build.zig is)?
    • I think overall Zig appears to be doing a great job with respect to openat, b.path() and using relative vs absolute paths in different places
    • however, isn't the point really to do normalization of paths, so for relative input paths, we need to know about what they are relative to, so we can translate that into something else!?
    • today it is translated into an absolute path, but can't it be a path relative to the build root???
  • just continue like today, it does work, so unless there are big changes to the Zig build system, I suppose we can continue

Pointers:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
build system enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants
@plajjan and others