The compiler now provides a server protocol for an interactive session
with another process. The build runner uses this protocol to communicate
compilation errors semantically from zig compiler subprocesses to the
build runner.
The protocol is exposed via stdin/stdout, or on a network socket,
depending on whether the CLI flag `--listen=-` or e.g.
`--listen=127.0.0.1:1337` is used.
Additionally:
* add the zig version string to the build runner cache prefix
* remove --prominent-compile-errors CLI flag because it no longer does
anything. Compilation errors are now unconditionally displayed at the
bottom of the build summary output when using the terminal-based
build runner.
* Remove the color field from std.Build. The build steps are no longer
supposed to interact with stderr directly. Instead they communicate
semantically back to the build runner, which has its own logic about
TTY configuration.
* Use the cleanExit() pattern in the build runner.
* Build steps can now use error.MakeFailed when they have already
properly reported an error, or they can fail with any other error
code in which case the build runner will create a simple message
based on this error code.
With this commit, the build runner now communicates progress towards
completion of the step graph to the terminal, while also printing the
stderr of child processes as soon as possible, without clobbering each
other, and without clobbering the CLI progress output.
* Step.init() now takes an options struct
* Step.init() now captures a small stack trace and stores it in the
Step so that it can be accessed when printing user-friendly debugging
information, including the lines of code that created the step in
question.
Instead of dumping directly to stderr. This prevents processes running
simultaneously from racing their stderr against each other.
For now it only reports at the end, but an improvement would be to
report as soon as a failed step occurs.
After sorting the step stack so that dependencies can be popped before
their dependants are popped, there is still a situation left to handle
correctly:
Example:
A depends on:
B
C
D depends on:
E
F
They will be ordered like this:
A B C D E F
If there are 6+ cores, then all of them will be evaluated at once,
incorrectly evaluating A and D before their dependencies.
Starting evaluation of F and then E is correct, but waiting until they
are done is not correct because it should start working on B and C as
well.
This commit solves the problem by computing dependants in the dependency
loop checking logic, and then having workers queue up their dependants
when they finish their own work.
Today I found out that posix_spawn is trash. It's actually implemented
on top of fork/exec inside of libc (or libSystem in the case of macOS).
So, anything posix_spawn can do, we can do better. In particular, what
we can do better is handle spawning of child processes that are
potentially foreign binaries. If you try to spawn a wasm binary, for
example, posix spawn does the following:
* Goes ahead and creates a child process.
* The child process writes "foo.wasm: foo.wasm: cannot execute binary file"
to stderr (yes, it prints the filename twice).
* The child process then exits with code 126.
This behavior is indistinguishable from the binary being successfully
spawned, and then printing to stderr, and exiting with a failure -
something that is an extremely common occurrence.
Meanwhile, using the lower level fork/exec will simply return ENOEXEC
code from the execve syscall (which is mapped to zig error.InvalidExe).
The posix_spawn behavior means the zig build runner can't tell the
difference between a failure to run a foreign binary, and a binary that
did run, but failed in some other fashion. This is unacceptable, because
attempting to excecve is the proper way to support things like Rosetta.
And make it not do any installation, only objcopying. We already have
install steps for doing installation.
This commit also makes ObjCopyStep properly integrate with caching.
And additionally support writing files to source files. This means a
custom build step in zig's own build.zig is no longer needed for copying
zig.h because it is handled by WriteFileStep.
This reverts commit 772a0eb68ac95b7e24508580499b49872fdb541f, reversing
changes made to 0bb178bbb2451238a326c6e916ecf38fbc34cab1.
This needs a rebase against master branch - it has build-breaking merge
conflicts. I also added a "changes requested" review on the original
pull request.
RunStep is supposed to auto-detect whether the intend is for
side-effects or for producing an output file. The auto-detection logic
was incorrect, and this commit fixes it.
I tested this manually locally. Automated testing will require a more
significant investment in the test harness, which I will work on in a
future enhancement.
closes#14666
This makes it so that when there is a tree of std.Build objects, only
one zig-cache is used (the top-level application) instead of polluting
package directories with zig-cache folders.
* Use std.Build.Cache.Directory instead of a string for storing the
cache roots and build roots.
* Set up a std.Build.Cache in build_runner.zig and use it in
std.Build.RunStep for avoiding redundant work.
Now that this API is used by the build system, these debug logs are
problematic because build scripts run in debug mode, making these logs
noisy output.
This provides file path as a command line argument to the command being
run, and returns a FileSource which can be used as inputs to other APIs
throughout the build system.
Unfortunately, it is implemented by pooping a ton of temporary files
into zig-cache/tmp for the time being. I think one of the very next
improvements to the build system should be moving the compiler's cache
system to the standard library and using it in the build system. I had a
look at the dependencies and it is already pretty untangled.
Deprecate CompileStep.run. The problem with this function is that it
does the RunStep with the same build.zig context as the CompileStep, but
this is not desirable when running an executable that is provided by a
dependency package. Instead, users should use `b.addRunArtifact`.
This has the additional benefit of conforming to the existing naming
conventions.
Additionally, support enum literals in config header options values.
Breaking API change to std.Build.addConfigHeader. It now uses an options
struct.
Introduce std.Build.CompileStep.installConfigHeader which also accepts
an options struct. This is used to add a generated config file into the
set of installed header files for a particular compilation artifact.
std.Build.ConfigHeaderStep now additionally supports a "blank" style
where a header is generated from scratch. It no longer exposes
`output_dir`. Instead it exposes a FileSource via `output_file`.
It now additionally accepts an `include_path` option which affects the
include path of CompileStep when using the `#include` directive, as well
as affecting the default installation subdirectory for header
installation purposes.
The hash used for the directory to store the generated config file now
includes the contents of the generated file. This fixes possible race
conditions when generating multiple header files simultaneously.
The values hash table is now an array hash map, to preserve order for
the "blank" use case.
I also took the opportunity to remove output_dir from TranslateCStep and
WriteFileStep. This is technically a breaking change, but it was always
naughty to access these fields.
Add ability to generate a c header file from scratch, and then both
compile with it and install it if needed.
Example:
```zig
const avconfig_h = b.addConfigHeader(.{ .path = "libavutil/avconfig.h" }, .generated, .{
.AV_HAVE_BIGENDIAN = 0, // TODO: detect based on target
.AV_HAVE_FAST_UNALIGNED = 1, // TODO: detect based on target
});
lib.addConfigHeader(avconfig_h);
lib.installConfigHeader(avconfig_h);
```
New API introduced: std.Build.addModule
This function exposes a zig module with the given name, which can be
used by packages that depend on this one via std.Build.Dependency.module.
std.Build.Pkg and related functionality is deleted. Every use case has a
straightforward upgrade path using the new Module struct.
std.Build.OptionsStep.getPackage is replaced by
std.Build.OptionsStep.createModule.
std.Build.CompileStep.addPackagePath is replaced by
std.Build.CompileStep.addAnonymousModule.
This partially addresses #14307 by renaming some of the instances of
"package" to "module".
Closes#14278
* std.zig.parse is moved to std.zig.Ast.parse
* the new function has an additional parameter that requires passing
Mode.zig or Mode.zon
* moved parser.zig code to Parse.zig
* added parseZon function next to parseRoot function
Usage of `catch unreachable` in build scripts is completely harmless
because build scripts are always run in Debug mode, however, it sets a
poor example for beginners to learn from.