Skip to content

Proposal: remove per-module targets #22285

Open
@mlugg

Description

@mlugg

#18160 was responsible for expanding Zig modules to include lots of state, such as link libraries, C source files, and optimization mode. One such property which can now be set on a per-module basis is the target.

Clearly, targets with (for instance) different object formats cannot be combined into a single output executable; it is also unclear whether there is a sane way to combine, for instance, different CPU architectures in one executable. The real stated use case in #18160 for this feature is to allow modules to be compiled with different CPU feature sets.

Presumably, the idea here is that a piece of source code can be compiled N times with N different CPU feature sets, allowing a single binary to run correctly and optimally across a variety of CPU models. However, the problem with this is that Zig does not allow a single file to exist in multiple modules. As such, this use case immediately breaks down: you cannot compile the same code N times for different CPU feature sets using modules alone.

Meanwhile, modules having different targets introduces other complexities. Clearly, this is difficult to support in the compiler; indeed, it doesn't really work today at all. Additionally, it introduces the problem that the standard library either cannot be shared, or needs to be compiled for the "least feature set" of all targets. Aside from code bloat, non-sharing of the standard library leads to the same usability issues as the ability to have one file in multiple modules would; namely, that std.ArrayListUnmanaged(u8) from module A is not necessarily the same type as std.ArrayListUnmanaged(u8) from module B. This leads to another issue with modules having different targets: it is unclear how these modules are actually allowed to interact. Can datastructures be exchanged between them?

Given that this feature fails to solve the problem it sets out to solve, and introduces many more issues and complexities along the way, I propose to remove this feature. The target should become a global option; for the build system, it should be set on std.Build.Step.Compile rather than on std.Build.Module.

Notes

  • The use case of having one binary which supports multiple CPU feature sets can be satisfied by compiling your application's hot path as an object file N separate times, and having your main application link all of those object files, calling the hot path over a well-defined API boundary.
  • This proposal does not suggest removing per-module optimization modes. While this feature is still not solved -- for instance, it is unclear what optimization mode the standard library should have -- it has clear utility, unlike per-module targets, and is strictly less problematic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingImplementing this issue could cause existing code to no longer compile or have different behavior.proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.zig build systemstd.Build, the build runner, `zig build` subcommand, package management

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions