std.Build: add lazyImport (@import for lazy dependencies)
#18988
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #18987
Follow-up to #18778 (which added lazy dependencies) and the discussion in #18808 that followed
This adds
b.lazyImport, which (in the context of a build script) is to@importwhatb.lazyDependencyis tob.dependencyand can be used to import a lazy dependency's build.zig struct.It enables the use case where a package wants to lazily depend on an
@import-style dependency and not fetch it until it is first needed, for example when building for a specific target.Implementation details
Given the
nameof a dependency, we want to locate that package.Just like with
dependencyandlazyDependency, in order to find the package we need to first obtain a list over which dependencies are available to the dependee, then find the package with the matching name in that list. Fordependency/lazyDependency, this list isb.available_deps.However, because
lazyImportreturns a comptime-only return type, we can't use runtime arguments likeb.available_deps.All the lists of dependencies of all participating packages can be found in
@import("root").dependencies, but given only thenameof the package have no way to know at comptime for which package we are callinglazyImport.The only "clean" solution to this problem that I can come up with is to take a build.zig struct as the second argument:
This enables us to compare
asking_build_zigagainst the build.zig struct of every package in@import("root").dependenciesto figure out for which package we are callinglazyImport, then search through that package's dependencies as usual.For good measure we can also throw in a runtime safety check that asserts that the
binstance and the build.zig struct both represent the same package.In practice this means that you almost always invoke the function with
@This()as the second argument, such as inb.lazyImport(@This(), "foo").Testing
This API can't currently easily be tested by the compiler's test suite.
If any maintainers would like to check out this branch and test it locally, I have prepared a little test project that uses
lazyImportup to two levels of indirection, which I used myself to test the changes:test.tar.gz
The project is set up as follows:
rootlazily depends onalfarootlazily depends onbravobravolazily depends oncharlieI used
python -m http.serverto serve the packages overhttp://localhost:8000/; you might need to edit them if you want to serve them in a different way.Running
zig buildwill trigger one initial compile of the build script + two recompiles, then install two plaintext files.