-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
a zig build mode intended to be used when packaging an application or library for a system distribution #14281
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
Comments
As long as zig can be pointed at a local directory for each dependency instead of ever fetching itself, then the external packaging systems (and/or the tooling around it) can be made to work. |
I suspect that, in this mode, it will be necessary for zig to shell out to the system C/C++ compiler toolchain instead of relying on its own embedded clang library code. This is a very large can of worms, but, if we accept the foundational premise that zig build is intended to be truly used as a competitor to other build systems, this point is non-negotiable. |
Edit: moved to #14283 (comment) |
i think something akin to https://cmake.org/cmake/help/latest/envvar/CMAKE_PREFIX_PATH.html |
The equivalent parameter in zig build is --search-prefix |
yes but i mean a variable different but similar for finding zig packages instead of cmake packages |
Note what's happening over at NixOS/nixpkgs#241741. They are creating common logic for packaging Zig applications on NixOS and have this line:
This is a bit of a problem because
Furthermore, What we need is a way for nix and other systems to be able to specify their true intent, which is this:
We should make both of these things easy to specify, regardless of what is in the upstream application's build.zig script. Here is my concrete proposal:
Finally, we need to also tackle one more problem, which is that zig packages need to know when they are being built in a mode that means they should try to depend on system libraries rather than fetching dependencies via the zig build system. For this I think we will need one or more flags, but I haven't quite thought through all the ramifications and how exactly this will be integrated into systems like Debian or Nix, but that concern should not block the implementation of these other flags, which would help Nix right now. |
Accepting the proposal now. When closing the issue, there should be 2 follow-up issues opened:
|
In addition to those two flags specified in #14281 (comment), this proposal also introduces a
As for reconciliation of dependency versions, it will be the responsibility of build scripts to probe the system and decide if it is acceptable to proceed. Zig build system API will be provided for common tasks to aid this endeavor, such as checking the major version of a shared library. As for ability to build C/C++ source files by the system toolchain rather than by zig's toolchain, the decision to do this can be done automatically when in system mode, and the logic for being a system toolchain driver can go directly into the zig build system. |
Overall the proposed
My only concern with this proposal is that the default and path of least resistance here for zig projects seems to be calling dependency and doing nothing further to handle the possibility of that dependency being provided by the system. I see this resulting in distro maintainers needing to patch the build.zig files of many projects to fix this. Perhaps it would be possible to handle the simple case of this automatically by adding more declarative metadata to zig packages providing system libraries (e.g. the ffmpeg zig package could declare that it is equivalent to linkSystemLibrary("ffmpeg") in some way). I'm not clear on the details here though and such an approach may not be worth the complexity.
A build.zig API for requiring a specific shared library soversion would be very much appreciated.
I assume this also covers linking the system libc version instead of the zig provided one? |
Perhaps related #3671 . There can be additional field like const mach_glfw_dep = b.dependency("mach_glfw", .{});
exe.linkSomeLibrary(.{
.system_artifact = .{
.so_name = "glfw",
.pkgconf_name = "glfw3",
.vcpkg_name = "glfw3",
},
.zig_artifact = mach_glfw_dep.artifact("glfw"),
}); Then it uses either system_artifact or zig_artifact, depending on current mode. |
The ability for a library link to specify a dynamic counterpart (if any) to source from the system would be very welcome indeed, amongst the bigger picture proposed here. As a bullet point, the way Ghostty does this today is with a flag This is done very manually with a giant Looking forward to it. |
Organize everything around a Fetch task which does a bunch of stuff in a worker thread without touching any shared state, and then queues up Fetch tasks for its dependencies. This isn't the theoretical optimal package fetching performance because CPU cores don't necessarily map 1:1 with I/O tasks, and each fetch task contains a mixture of computations and I/O. However, it is expected for this to significantly outperform master branch, which fetches everything recursively with only one thread. The logic is now a lot more linear and easy to follow. Everything that is embarassingly parallel is done on the thread pool, and then after everything is fetched, the worker threads are joined and the main thread does the finishing touches of stitching together the dependencies.zig import files. There is only one tiny little critical section and it does not even have any error handling in it. This also lays the groundwork for #14281 because in system mode, all this fetching logic will be skipped, but the "finishing touches" mentioned above still need to be done. With this branch, that logic is separated out and no longer recursively tangled with fetching stuff. Additionally, this branch: * Implements inclusion directives in `build.zig.zon` for deciding which files belong the package (#14311). * Adds basic documentation for `build.zig.zon` files. * Adds support for fetching dependencies with the `file://` protocol scheme (#17364). * Adds a workaround for a Linux/btrfs file system bug (#17282). This commit is a work-in-progress. Still todo: 1. Hook up the CLI to the new system. 2. Restore the module table creation logic after all the fetching is done. 3. Fix compilation errors, get the tests passing, and regression test against real world projects.
Organize everything around a Fetch task which does a bunch of stuff in a worker thread without touching any shared state, and then queues up Fetch tasks for its dependencies. This isn't the theoretical optimal package fetching performance because CPU cores don't necessarily map 1:1 with I/O tasks, and each fetch task contains a mixture of computations and I/O. However, it is expected for this to significantly outperform master branch, which fetches everything recursively with only one thread. The logic is now a lot more linear and easy to follow. Everything that is embarassingly parallel is done on the thread pool, and then after everything is fetched, the worker threads are joined and the main thread does the finishing touches of stitching together the dependencies.zig import files. There is only one tiny little critical section and it does not even have any error handling in it. This also lays the groundwork for #14281 because in system mode, all this fetching logic will be skipped, but the "finishing touches" mentioned above still need to be done. With this branch, that logic is separated out and no longer recursively tangled with fetching stuff. Additionally, this branch: * Implements inclusion directives in `build.zig.zon` for deciding which files belong the package (#14311). * Adds basic documentation for `build.zig.zon` files. * Adds support for fetching dependencies with the `file://` protocol scheme (#17364). * Adds a workaround for a Linux/btrfs file system bug (#17282). This commit is a work-in-progress. Still todo: 1. Hook up the CLI to the new system. 2. Restore the module table creation logic after all the fetching is done. 3. Fix compilation errors, get the tests passing, and regression test against real world projects.
Organize everything around a Fetch task which does a bunch of stuff in a worker thread without touching any shared state, and then queues up Fetch tasks for its dependencies. This isn't the theoretical optimal package fetching performance because CPU cores don't necessarily map 1:1 with I/O tasks, and each fetch task contains a mixture of computations and I/O. However, it is expected for this to significantly outperform master branch, which fetches everything recursively with only one thread. The logic is now a lot more linear and easy to follow. Everything that is embarassingly parallel is done on the thread pool, and then after everything is fetched, the worker threads are joined and the main thread does the finishing touches of stitching together the dependencies.zig import files. There is only one tiny little critical section and it does not even have any error handling in it. This also lays the groundwork for #14281 because in system mode, all this fetching logic will be skipped, but the "finishing touches" mentioned above still need to be done. With this branch, that logic is separated out and no longer recursively tangled with fetching stuff. Additionally, this branch: * Implements inclusion directives in `build.zig.zon` for deciding which files belong the package (#14311). * Adds basic documentation for `build.zig.zon` files. * Adds support for fetching dependencies with the `file://` protocol scheme (#17364). * Adds a workaround for a Linux/btrfs file system bug (#17282). This commit is a work-in-progress. Still todo: 1. Hook up the CLI to the new system. 2. Restore the module table creation logic after all the fetching is done. 3. Fix compilation errors, get the tests passing, and regression test against real world projects.
Uh oh!
There was an error while loading. Please reload this page.
This proposal is accepted; please see these comments for the criteria for closing the issue:
Extracted from #14265.
The use case is as follows:
Someone wants to take an upstream application, and package it for a Linux distribution, or another kind of distribution such as Homebrew or Nix.
The application knows exactly what versions of each dependency it wants to build against, but distributions only provide a limited set of versions. Furthermore, the system distribution wants to be in charge of providing all dependencies, building the application from source without access to any files outside of those provided by the system itself, via its own dependency management system.
For this use case, instead of fetching dependencies from the URLs provided by zig build.zig.zon files, instead there should be some kind of override that makes the dependencies fetched from the system package manager.
Related: Stay Together For The Kids: Why System Package Managers and Language Package Managers Struggle to Cooperate
The text was updated successfully, but these errors were encountered: