Commit graph

622 commits

Author SHA1 Message Date
Andrew Kelley
7cc4a6965c build runner enhancements in preparation for test-cases
* std.zig.ErrorBundle: support rendering options for whether to include
   the reference trace, whether to include the source line, and TTY
   configuration.

 * build runner: don't print progress in dumb terminals

 * std.Build.CompileStep:
   - add a way to expect compilation errors via the new `expect_errors`
     field. This is an advanced setting that can change the intent of
     the CompileStep. If this slice has nonzero length, it means that
     the CompileStep exists to check for compile errors and return
     *success* if they match, and failure otherwise.
   - remove the object format parameter from `checkObject`. The object
     format is known based on the CompileStep's target.
   - Avoid passing -L and -I flags for nonexistent directories within
     search_prefixes. This prevents a warning, that should probably be
     upgraded to an error in Zig's CLI parsing code, when the linker
     sees an -L directory that does not exist.

 * std.Build.Step:
   - When spawning the zig compiler process, takes advantage of the new
     `std.Progress.Node.setName` API to avoid ticking up a meaningless
     number at every progress update.
2023-03-15 10:48:14 -07:00
Andrew Kelley
3186658e60 std.Build.CheckFileStep: add a way to expect exact
This is done in a bit of a haphazard way. Eventually the API needs to
break in favor of a "checks" system similar to how RunStep works.
2023-03-15 10:48:14 -07:00
Andrew Kelley
974a6fe757 std.Build.RunStep: support -fqemu solving bad dynamic linker 2023-03-15 10:48:14 -07:00
Andrew Kelley
9a9b008300 std.Build.CompileStep: add FileSource support to some paths
Library paths, RPaths, and framework paths now support being fulfilled
by FileSource arguments.
2023-03-15 10:48:14 -07:00
Andrew Kelley
f558c835a4 std.Build.CheckObjectStep: better error message
when reading the file fails
2023-03-15 10:48:14 -07:00
Andrew Kelley
3b06990730 std.Build.CompileStep: tweak the default step name 2023-03-15 10:48:14 -07:00
Andrew Kelley
0b8736f5ed re-enable CLI tests
CLI tests are now ported over to the new std.Build API and thus work
properly with concurrency.

 * add `std.Build.addCheckFile` for creating a
   `std.Build.CheckFileStep`.
 * add `std.Build.makeTempPath`. This function is intended to be called
   in the `configure` phase only. It returns an absolute directory path,
   which is potentially going to be a source of API breakage in the
   future, so keep that in mind when using this function.
 * add `std.Build.CheckFileStep.setName`.
 * `std.Build.CheckFileStep`: better error message when reading the
   input file fails.
 * `std.Build.RunStep`: add a `has_side_effects` flag for when you need
   to override the autodetection.
 * `std.Build.RunStep`: add the ability to obtain a FileSource for the
   directory that contains the written files.
 * `std.Build.WriteFileStep`: add a way to write bytes to an arbitrary
   path - absolute or relative to the package root. Be careful with this
   because it updates source files. This should not be used as part of
   the normal build process, but as a utility occasionally run by a
   developer with intent to modify source files and then commit those
   changes to version control. A file added this way is not available
   with `getFileSource`.
2023-03-15 10:48:13 -07:00
Andrew Kelley
a24af8e400 re-integrate stack trace tests with the new std.Build API
* RunStep: ability to set stdin
 * RunStep: ability to capture stdout and stderr as a FileSource
 * RunStep: add setName method
 * RunStep: hash the stdio checks
2023-03-15 10:48:13 -07:00
Andrew Kelley
f51413d2cf zig build: add an OOM-prevention system
The problem is that one may execute too many subprocesses concurrently
that, together, exceed an RSS value that causes the OOM killer to kill
something problematic such as the window manager. Or worse, nothing, and
the system freezes.

This is a real world problem. For example when building LLVM a simple
`ninja install` will bring your system to its knees if you don't know
that you should add `-DLLVM_PARALLEL_LINK_JOBS=1`.

In particular: compiling the zig std lib tests takes about 2G each,
which at 16x at once (8 cores + hyperthreading) is using all 32GB of my
RAM, causing the OOM killer to kill my window manager

The idea here is that you can annotate steps that might use a high
amount of system resources with an upper bound. So for example I could
mark the std lib tests as having an upper bound peak RSS of 3 GiB.

Then the build system will do 2 things:

1. ulimit the child process, so that it will fail if it would exceed
   that memory limit.
2. Notice how much system RAM is available and avoid running too many
   concurrent jobs at once that would total more than that.

This implements (1) not with an operating system enforced limit, but by
checking the maxrss after a child process exits.

However it does implement (2) correctly.

The available memory used by the build system defaults to the total
system memory, regardless of whether it is used by other processes at
the time of spawning the build runner. This value can be overridden with
the new --maxrss flag to `zig build`. This mechanism will ensure that
the sum total of upper bound RSS memory of concurrent tasks will not
exceed this value.

This system makes it so that project maintainers can annotate
problematic subprocesses, avoiding bug reports from users, who can
blissfully execute `zig build` without worrying about the project's
internals.

Nobody's computer crashes, and the build system uses as much parallelism
as possible without risking OOM. Users do not need to unnecessarily
resort to -j1 when the build system can figure this out for them.
2023-03-15 10:48:13 -07:00
Andrew Kelley
d3cbbe0b1e std.Build.Step: no-op steps report cached if all deps cached 2023-03-15 10:48:13 -07:00
Andrew Kelley
a4c35a6245 std.Build: audit use of updateFile
* remove std.Build.updateFile. I noticed some people use it from
   build.zig (declare phase) when it is intended only for use in the
   make phase.
   - This also was incorrectly reporting errors with std.log.
 * std.Build.InstallArtifactStep
   - report better errors on failure
   - report whether the step was cached or not
 * std.Build.InstallDirStep: report better error on failure
 * std.Build.InstallFileStep: report better error on failure
2023-03-15 10:48:13 -07:00
Andrew Kelley
1e63573d35 std.build.CompileStep: eliminate std.log usage 2023-03-15 10:48:13 -07:00
Andrew Kelley
bb1960c2a4 std.Build.InstallDirStep: avoid std.log
And better make use of open directory handles.
2023-03-15 10:48:13 -07:00
Andrew Kelley
405bf1b091 std.Build.ConfigHeaderStep: integrate with the cache system 2023-03-15 10:48:13 -07:00
Andrew Kelley
2cc33f5f4e std.Build.Step.cacheHit marks step as cached on hit 2023-03-15 10:48:13 -07:00
Andrew Kelley
2996eb5587 std.Build.RunStep: add maxrss, duration, and cached status 2023-03-15 10:48:13 -07:00
Andrew Kelley
2b23625510 std.Build.RunStep: report duration and cached status 2023-03-15 10:48:13 -07:00
Andrew Kelley
d695f36e70 build runner supports reporting cached status and duration 2023-03-15 10:48:13 -07:00
Andrew Kelley
8b054e190a std.Build.RunStep: work around a miscompilation
See #14783

Also, set the cwd directory handle when spawning the child process if
available.
2023-03-15 10:48:13 -07:00
Andrew Kelley
dcec4d55e3 eliminate stderr usage in std.Build make() functions
* Eliminate all uses of `std.debug.print` in make() functions, instead
  properly using the step failure reporting mechanism.
* Introduce the concept of skipped build steps. These do not cause the
  build to fail, and they do allow their dependants to run.
* RunStep gains a new flag, `skip_foreign_checks` which causes the
  RunStep to be skipped if stdio mode is `check` and the binary cannot
  be executed due to it being a foreign executable.
  - RunStep is improved to automatically use known interpreters to
    execute binaries if possible (integrating with flags such as
    -fqemu and -fwasmtime). It only does this after attempting a native
    execution and receiving a "exec file format" error.
  - Update RunStep to use an ArrayList for the checks rather than this
    ad-hoc reallocation/copying mechanism.
  - `expectStdOutEqual` now also implicitly adds an exit_code==0 check
    if there is not already an expected termination. This matches
    previously expected behavior from older API and can be overridden by
    directly setting the checks array.
* Add `dest_sub_path` to `InstallArtifactStep` which allows choosing an
  arbitrary subdirectory relative to the prefix, as well as overriding
  the basename.
  - Delete the custom InstallWithRename step that I found deep in the
    test/ directory.
* WriteFileStep will now update its step display name after the first
  file is added.
* Add missing stdout checks to various standalone test case build
  scripts.
2023-03-15 10:48:13 -07:00
Andrew Kelley
e0561ad79b std.Build.Cache.Directory: add a format() method 2023-03-15 10:48:13 -07:00
Andrew Kelley
a2dc49a0f3 fix Step.evalZigProcess to handle more than 1 message per poll 2023-03-15 10:48:13 -07:00
Andrew Kelley
58edefc6d1 zig build: many enhancements related to parallel building
Rework std.Build.Step to have an `owner: *Build` field. This
simplified the implementation of installation steps, as well as provided
some much-needed common API for the new parallelized build system.

--verbose is now defined very concretely: it prints to stderr just
before spawning a child process.

Child process execution is updated to conform to the new
parallel-friendly make() function semantics.

DRY up the failWithCacheError handling code. It now integrates properly
with the step graph instead of incorrectly dumping to stderr and calling
process exit.

In the main CLI, fix `zig fmt` crash when there are no errors and stdin
is used.

Deleted steps:
 * EmulatableRunStep - this entire thing can be removed in favor of a
   flag added to std.Build.RunStep called `skip_foreign_checks`.
 * LogStep - this doesn't really fit with a multi-threaded build runner
   and is effectively superseded by the new build summary output.

build runner:
 * add -fsummary and -fno-summary to override the default behavior,
   which is to print a summary if any of the build steps fail.
 * print the dep prefix when emitting error messages for steps.

std.Build.FmtStep:
 * This step now supports exclude paths as well as a check flag.
 * The check flag decides between two modes, modify mode, and check
   mode. These can be used to update source files in place, or to fail
   the build, respectively.

Zig's own build.zig:
 * The `test-fmt` step will do all the `zig fmt` checking that we expect
   to be done. Since the `test` step depends on this one, we can simply
   remove the explicit call to `zig fmt` in the CI.
 * The new `fmt` step will actually perform `zig fmt` and update source
   files in place.

std.Build.RunStep:
 * expose max_stdio_size is a field (previously an unchangeable
   hard-coded value).
 * rework the API. Instead of configuring each stream independently,
   there is a `stdio` field where you can choose between
   `infer_from_args`, `inherit`, or `check`. These determine whether the
   RunStep is considered to have side-effects or not. The previous
   field, `condition` is gone.
 * when stdio mode is set to `check` there is a slice of any number of
   checks to make, which include things like exit code, stderr matching,
   or stdout matching.
 * remove the ill-defined `print` field.
 * when adding an output arg, it takes the opportunity to give itself a
   better name.
 * The flag `skip_foreign_checks` is added. If this is true, a RunStep
   which is configured to check the output of the executed binary will
   not fail the build if the binary cannot be executed due to being for
   a foreign binary to the host system which is running the build graph.
   Command-line arguments such as -fqemu and -fwasmtime may affect
   whether a binary is detected as foreign, as well as system
   configuration such as Rosetta (macOS) and binfmt_misc (Linux).
   - This makes EmulatableRunStep no longer needed.
 * Fix the child process handling to properly integrate with the new
   bulid API and to avoid deadlocks in stdout/stderr streams by polling
   if necessary.

std.Build.RemoveDirStep now uses the open build_root directory handle
instead of an absolute path.
2023-03-15 10:48:13 -07:00
Andrew Kelley
b4997d0890 std.Build.RunStep: better default step name
Now it renames itself when an output argument is added.
2023-03-15 10:48:13 -07:00
Andrew Kelley
8c250828a2 std.Build.Step: avoid redundancy in default error message 2023-03-15 10:48:13 -07:00
Andrew Kelley
a7754d219a build system: better default name for ConfigHeaderStep 2023-03-15 10:48:13 -07:00
Andrew Kelley
8b2d872020 fix std.Build.TranslateCStep 2023-03-15 10:48:13 -07:00
Andrew Kelley
0e078790fe multiplex compiler progress messages into the build runner 2023-03-15 10:48:13 -07:00
Andrew Kelley
85b4b6e3b3 std.Build.InstallArtifactStep: better default step name 2023-03-15 10:48:13 -07:00
Andrew Kelley
7efeedcd89 std.Build.CompileStep: better default step name 2023-03-15 10:48:13 -07:00
Andrew Kelley
79440d2b47 std.Build.CompileStep: obtain the build output dir from protocol
Now building successfully works again.
2023-03-15 10:48:13 -07:00
Andrew Kelley
986a30e373 integrate the build runner and the compiler server
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.
2023-03-15 10:48:13 -07:00
Andrew Kelley
c5edd8b7f8 std.Build: better handling of stderr of child processes
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.
2023-03-15 10:48:12 -07:00
Andrew Kelley
8d38472293 std.Build: further enhance debug message for bad getPath()
Now it also shows the step stack trace of the step whose make function
is being run.
2023-03-15 10:48:12 -07:00
Andrew Kelley
02381c0372 std.Build: improve debugging of misconfigured steps
* 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.
2023-03-15 10:48:12 -07:00
Andrew Kelley
9580fbcf35 build system: capture stderr and report it later
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.
2023-03-15 10:48:12 -07:00
Andrew Kelley
1fa1484288 build runner: proper threaded dependency management
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.
2023-03-15 10:48:12 -07:00
Andrew Kelley
cff86cf7a1 build_runner now executes the step graph in parallel 2023-03-15 10:48:12 -07:00
Andrew Kelley
0b744d7d67 build runner: untangle dependency loop checking from making 2023-03-15 10:48:12 -07:00
Andrew Kelley
3169f0529b eliminate posix_spawn from the standard library
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.
2023-03-10 15:41:07 -05:00
Ali Chraghi
75ff34db9e std.Build.Cache: remove 'test-filetimestamp.tmp' once timestamp returned 2023-03-03 13:50:44 -05:00
Andrew Kelley
f6c9346773 std.Build.CompileStep.installConfigHeader: add missing step dependency 2023-02-25 23:22:17 -05:00
Andrew Kelley
26196be344 rename std.Build.InstallRawStep to ObjCopyStep
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.
2023-02-24 23:48:03 -05:00
Andrew Kelley
d3c9bfada6 std.Build.WriteFileStep: integrate with cache system
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.
2023-02-23 01:08:23 -05:00
mlugg
09a84c8384
Update std.Build to new module CLI, update zig1 and CMakeLists
Resolves: #14667
2023-02-21 01:59:37 +00:00
Andrew Kelley
adfc019d60
Merge pull request #11982 from marler8997/ignoreSigpipe
ignore SIGPIPE by default
2023-02-19 13:55:12 -05:00
Andrew Kelley
02f5d2673f Revert "Merge pull request #14661 from evacchi/zig-wasi-preopens"
This reverts commit 772a0eb68a, reversing
changes made to 0bb178bbb2.

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.
2023-02-19 09:40:55 -07:00
Luuk de Gram
772a0eb68a
Merge pull request #14661 from evacchi/zig-wasi-preopens 2023-02-19 17:09:58 +01:00
Andrew Kelley
aeaef8c0ff update std lib and compiler sources to new for loop syntax 2023-02-18 19:17:21 -07:00
Andrew Kelley
5e7b09ce9f std.Build.RunStep: fix default caching logic
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
2023-02-18 19:33:47 -05:00