Zig's comptime evaluation is already powerful enough to allows conditional importing without having to have the @import target be a comptime expression. For example:
const target = if (builtin.mode == .Debug) "debug_mutex.zig" else "release_mutex.zig";
const mutex = @import(target);
This could be rewritten - and I would even say would be preferred to be rewritten - as:
const debug_mutex = @import("debug_mutex.zig");
const release_mutex = @import("release_mutex.zig");
const mutex = if (builtin.mode == .Debug) debug_mutex else release_mutex;
If import syntax is required to be trivially resolvable to either a file or a package name, then Zig can find all the source files for testing without this kind of thing:
There is still a problem though, because if zig ran all tests indiscriminately, this would stop working:
https://github.com/ziglang/zig/blob/7c38651a65b48b8cc683bc31a40952d9b469ec4d/std/os/linux.zig#L1537-L1541
The general problem here is that @import has compile-time side effects:
export or @export - potentially conflicting.@compileError to trigger based on build mode or something else in top level comptime blocks.@cImport which causes a compile errorIt would be weird to activate these side effects for tests but not for other builds. And these side effects are important; they're not going away.
So I think the benefits of this proposal are not clear. But I think this is a sort of important topic in Zig so it deserves an issue that we can reference.
One thing to consider here is that the path might be a compile time variable from somewhere like @import("build_options").
One thing to consider here is that the path might be a compile time variable from somewhere like
@import("build_options").
const tag = @import("build_options").which_package_do_you_want;
const thing = switch (tag) {
.one => @import("one.zig"),
.two => @import("two.zig"),
}
This pattern will work for the linked use case, and it will help with static code analysis tools. Is there another use case that would be problematic?
How would you handle the case of when a user might want to specify a path to include? (e.g. through command line args or maybe a loaded "build configuration" file)
That could be better handled by having the build file declare a package pointing to that file.
How would the build file declare a package if @import only allows for string _literals_? I might be missing something here.
Edit: Sorry, realized that this was under the assumption that addPackage used @import in its implementation, which I now realize is not the case(?)
@minierolls
zig build-exe my-source.zig --pkg-begin package_name /some/path/to/package.zig --pkg-end
will add a package called package_name pointing to /some/path/to/package.zig
As @andrewrk suggested, i want to propose the following improvement in addition to "only strings":
As @import is a built-in, it might allow both string literals (always user packages) and enum literals (.root, .self, .std, those are always magic) to be imported:
const network = @import("network");
const std = @import(.std);
This would make clear that these packages are magic and provided by the compiler whereas every string is to be given on the command line or in build.zig. It would also free those magic package names and make a clear distinction.
This change is even non-breaking, as it can be easily fixed with zig fmt
Is "std" really _magic_? Is it not just a compiler-provided addPackagePath, or whatever it's called.
@Tetralux
Is "std" really magic? Is it not just a compiler-provided addPackagePath, or whatever it's called.
Both proposed "root" and "self" (see #6279) are special as they differ for each file in the project. The same is for "std" as it is not added by the user but is (afaik) always provided by the compiler (which makes them magic as i don't have control over that atm)