Commit graph

166 commits

Author SHA1 Message Date
Benjamin Jurk
4b5351bc0d
update deprecated ArrayListUnmanaged usage (#25958) 2025-11-20 14:46:23 -08:00
Matthew Lugg
bc524a2b1a
std.Build: fix crashes running fuzz tests 2025-11-20 10:42:21 +00:00
Harold
2f240d0819 std.Build.Step.Compile: add support for '-z defs' flag 2025-11-19 20:13:54 +01:00
Ryan Liptak
da77d306b6 Move/coalesce RcIncludes enum to std.zig.RcIncludes 2025-11-07 19:16:52 -08:00
Ryan Liptak
f587209e04 Move/coalesce CompressDebugSections enum to std.zig.CompressDebugSections 2025-11-07 19:15:55 -08:00
Carl Åstholm
54f2a7c833 Move std.Target.SubSystem to std.zig.Subsystem
Also updates the field names to conform with the rest of std.
2025-11-05 01:31:26 +01:00
Matthew Lugg
74931fe25c
std.debug.lockStderrWriter: also return ttyconf
`std.Io.tty.Config.detect` may be an expensive check (e.g. involving
syscalls), and doing it every time we need to print isn't really
necessary; under normal usage, we can compute the value once and cache
it for the whole program's execution. Since anyone outputting to stderr
may reasonably want this information (in fact they are very likely to),
it makes sense to cache it and return it from `lockStderrWriter`. Call
sites who do not need it will experience no significant overhead, and
can just ignore the TTY config with a `const w, _` destructure.
2025-10-30 09:31:28 +00:00
Andrew Kelley
43c2ba375d std: accessZ -> access 2025-10-29 06:20:50 -07:00
Jacob Young
f58200e3f2 Elf2: create a new linker from scratch
This iteration already has significantly better incremental support.

Closes #24110
2025-09-21 14:09:14 -07:00
Andrew Kelley
79f267f6b9 std.Io: delete GenericReader
and delete deprecated alias std.io
2025-08-29 17:14:26 -07:00
Ian Johnson
d4df65e355 std.Build.Step.Compile: fix race condition in args file creation
Fixes #23993

Previously, if multiple build processes tried to create the same args file, there was a race condition with the use of the non-atomic `writeFile` function which could cause a spawned compiler to read an empty or incomplete args file. This commit avoids the race condition by first writing to a temporary file with a random path and renaming it to the desired path.
2025-08-26 12:02:50 +01:00
Andrew Kelley
749f10af49 std.ArrayList: make unmanaged the default 2025-08-11 15:52:49 -07:00
mlugg
e98aeeb73f std.Build: keep compiler alive under -fincremental --webui
Previously, this only applied when using `-fincremental --watch`, but
`--webui` makes the build runner stay alive just like `--watch` does, so
the same logic applies here. Without this, attempting to perform
incremental updates with `--webui` performs full rebuilds. (I did test
that before merging the PR, but at that time I was passing `--watch`
too -- which has since been disallowed -- so I missed that it doesn't
work as expected without that option!)
2025-08-02 08:56:19 +01:00
mlugg
dcc3e6e1dd build system: replace fuzzing UI with build UI, add time report
This commit replaces the "fuzzer" UI, previously accessed with the
`--fuzz` and `--port` flags, with a more interesting web UI which allows
more interactions with the Zig build system. Most notably, it allows
accessing the data emitted by a new "time report" system, which allows
users to see which parts of Zig programs take the longest to compile.

The option to expose the web UI is `--webui`. By default, it will listen
on `[::1]` on a random port, but any IPv6 or IPv4 address can be
specified with e.g. `--webui=[::1]:8000` or `--webui=127.0.0.1:8000`.
The options `--fuzz` and `--time-report` both imply `--webui` if not
given. Currently, `--webui` is incompatible with `--watch`; specifying
both will cause `zig build` to exit with a fatal error.

When the web UI is enabled, the build runner spawns the web server as
soon as the configure phase completes. The frontend code consists of one
HTML file, one JavaScript file, two CSS files, and a few Zig source
files which are built into a WASM blob on-demand -- this is all very
similar to the old fuzzer UI. Also inherited from the fuzzer UI is that
the build system communicates with web clients over a WebSocket
connection.

When the build finishes, if `--webui` was passed (i.e. if the web server
is running), the build runner does not terminate; it continues running
to serve web requests, allowing interactive control of the build system.

In the web interface is an overall "status" indicating whether a build
is currently running, and also a list of all steps in this build. There
are visual indicators (colors and spinners) for in-progress, succeeded,
and failed steps. There is a "Rebuild" button which will cause the build
system to reset the state of every step (note that this does not affect
caching) and evaluate the step graph again.

If `--time-report` is passed to `zig build`, a new section of the
interface becomes visible, which associates every build step with a
"time report". For most steps, this is just a simple "time taken" value.
However, for `Compile` steps, the compiler communicates with the build
system to provide it with much more interesting information: time taken
for various pipeline phases, with a per-declaration and per-file
breakdown, sorted by slowest declarations/files first. This feature is
still in its early stages: the data can be a little tricky to
understand, and there is no way to, for instance, sort by different
properties, or filter to certain files. However, it has already given us
some interesting statistics, and can be useful for spotting, for
instance, particularly complex and slow compile-time logic.
Additionally, if a compilation uses LLVM, its time report includes the
"LLVM pass timing" information, which was previously accessible with the
(now removed) `-ftime-report` compiler flag.

To make time reports more useful, ZIR and compilation caches are ignored
by the Zig compiler when they are enabled -- in other words, `Compile`
steps *always* run, even if their result should be cached. This means
that the flag can be used to analyze a project's compile time without
having to repeatedly clear cache directory, for instance. However, when
using `-fincremental`, updates other than the first will only show you
the statistics for what changed on that particular update. Notably, this
gives us a fairly nice way to see exactly which declarations were
re-analyzed by an incremental update.

If `--fuzz` is passed to `zig build`, another section of the web
interface becomes visible, this time exposing the fuzzer. This is quite
similar to the fuzzer UI this commit replaces, with only a few cosmetic
tweaks. The interface is closer than before to supporting multiple fuzz
steps at a time (in line with the overall strategy for this build UI,
the goal will be for all of the fuzz steps to be accessible in the same
interface), but still doesn't actually support it. The fuzzer UI looks
quite different under the hood: as a result, various bugs are fixed,
although other bugs remain. For instance, viewing the source code of any
file other than the root of the main module is completely broken (as on
master) due to some bogus file-to-module assignment logic in the fuzzer
UI.

Implementation notes:

* The `lib/build-web/` directory holds the client side of the web UI.

* The general server logic is in `std.Build.WebServer`.

* Fuzzing-specific logic is in `std.Build.Fuzz`.

* `std.Build.abi` is the new home of `std.Build.Fuzz.abi`, since it now
  relates to the build system web UI in general.

* The build runner now has an **actual** general-purpose allocator,
  because thanks to `--watch` and `--webui`, the process can be
  arbitrarily long-lived. The gpa is `std.heap.DebugAllocator`, but the
  arena remains backed by `std.heap.page_allocator` for efficiency. I
  fixed several crashes caused by conflation of `gpa` and `arena` in the
  build runner and `std.Build`, but there may still be some I have
  missed.

* The I/O logic in `std.Build.WebServer` is pretty gnarly; there are a
  *lot* of threads involved. I anticipate this situation improving
  significantly once the `std.Io` interface (with concurrency support)
  is introduced.
2025-08-01 23:48:21 +01:00
Carl Åstholm
413179ccfc std.Build: Deprecate Step.Compile APIs that mutate the root module
Not only are `Step.Compile` methods like `linkLibC()` redundant because
`Module` exposes the same APIs, it also might not be immediately obvious
to users that these methods modify the underlying root module, which can
be a footgun and lead to unintended results if the module is exported to
package consumers or shared by multiple compile steps.

Using `compile.root_module.link_libc = true` makes it more clear to
users which of the compile step and the module owns which options.
2025-07-26 12:06:42 +02:00
Andrew Kelley
cce32bd1d5 fix build runner 2025-07-07 22:43:52 -07:00
Andrew Kelley
0e37ff0d59 std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap
between old and new API

make std.testing.expectFmt work at compile-time

std.fmt no longer has a dependency on std.unicode. Formatted printing
was never properly unicode-aware. Now it no longer pretends to be.

Breakage/deprecations:
* std.fs.File.reader -> std.fs.File.deprecatedReader
* std.fs.File.writer -> std.fs.File.deprecatedWriter
* std.io.GenericReader -> std.io.Reader
* std.io.GenericWriter -> std.io.Writer
* std.io.AnyReader -> std.io.Reader
* std.io.AnyWriter -> std.io.Writer
* std.fmt.format -> std.fmt.deprecatedFormat
* std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape
* std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape
* std.fmt.fmtSliceHexLower -> {x}
* std.fmt.fmtSliceHexUpper -> {X}
* std.fmt.fmtIntSizeDec -> {B}
* std.fmt.fmtIntSizeBin -> {Bi}
* std.fmt.fmtDuration -> {D}
* std.fmt.fmtDurationSigned -> {D}
* {} -> {f} when there is a format method
* format method signature
  - anytype -> *std.io.Writer
  - inferred error set -> error{WriteFailed}
  - options -> (deleted)
* std.fmt.Formatted
  - now takes context type explicitly
  - no fmt string
2025-07-07 22:43:51 -07:00
Andrew Kelley
0b3f0124dc std.io: move getStdIn, getStdOut, getStdErr functions to fs.File
preparing to rearrange std.io namespace into an interface

how to upgrade:

std.io.getStdIn() -> std.fs.File.stdin()
std.io.getStdOut() -> std.fs.File.stdout()
std.io.getStdErr() -> std.fs.File.stderr()
2025-07-07 22:43:51 -07:00
Jacob Young
917640810e Target: pass and use locals by pointer instead of by value
This struct is larger than 256 bytes and code that copies it
consistently shows up in profiles of the compiler.
2025-06-19 11:45:06 -04:00
Jacob Young
16d78bc0c0 Build: add install commands to --verbose output 2025-06-19 11:45:06 -04:00
Jacob Young
df4068cabd Build: change how the target is printed in step names
e.g. `x86_64-windows.win10...win11_dt-gnu` -> `x86_64-windows-gnu`

When the OS version is the default this is redundant with checking the
default in the standard library.
2025-06-19 11:45:06 -04:00
mlugg
b5f73f8a7b
compiler: rework emit paths and cache modes
Previously, various doc comments heavily disagreed with the
implementation on both what lives where on the filesystem at what time,
and how that was represented in code. Notably, the combination of emit
paths outside the cache and `disable_lld_caching` created a kind of
ad-hoc "cache disable" mechanism -- which didn't actually *work* very
well, 'most everything still ended up in this cache. There was also a
long-standing issue where building using the LLVM backend would put a
random object file in your cwd.

This commit reworks how emit paths are specified in
`Compilation.CreateOptions`, how they are represented internally, and
how the cache usage is specified.

There are now 3 options for `Compilation.CacheMode`:
* `.none`: do not use the cache. The paths we have to emit to are
  relative to the compiler cwd (they're either user-specified, or
  defaults inferred from the root name). If we create any temporary
  files (e.g. the ZCU object when using the LLVM backend) they are
  emitted to a directory in `local_cache/tmp/`, which is deleted once
  the update finishes.
* `.whole`: cache the compilation based on all inputs, including file
  contents. All emit paths are computed by the compiler (and will be
  stored as relative to the local cache directory); it is a CLI error to
  specify an explicit emit path. Artifacts (including temporary files)
  are written to a directory under `local_cache/tmp/`, which is later
  renamed to an appropriate `local_cache/o/`. The caller (who is using
  `--listen`; e.g. the build system) learns the name of this directory,
  and can get the artifacts from it.
* `.incremental`: similar to `.whole`, but Zig source file contents, and
  anything else which incremental compilation can handle changes for, is
  not included in the cache manifest. We don't need to do the dance
  where the output directory is initially in `tmp/`, because our digest
  is computed entirely from CLI inputs.

To be clear, the difference between `CacheMode.whole` and
`CacheMode.incremental` is unchanged. `CacheMode.none` is new
(previously it was sort of poorly imitated with `CacheMode.whole`). The
defined behavior for temporary/intermediate files is new.

`.none` is used for direct CLI invocations like `zig build-exe foo.zig`.
The other cache modes are reserved for `--listen`, and the cache mode in
use is currently just based on the presence of the `-fincremental` flag.

There are two cases in which `CacheMode.whole` is used despite there
being no `--listen` flag: `zig test` and `zig run`. Unless an explicit
`-femit-bin=xxx` argument is passed on the CLI, these subcommands will
use `CacheMode.whole`, so that they can put the output somewhere without
polluting the cwd (plus, caching is potentially more useful for direct
usage of these subcommands).

Users of `--listen` (such as the build system) can now use
`std.zig.EmitArtifact.cacheName` to find out what an output will be
named. This avoids having to synchronize logic between the compiler and
all users of `--listen`.
2025-06-12 13:55:40 +01:00
Andrew Kelley
100b76e17a std.Build.Step.Compile: clarify step name
In particular this makes it more obvious what step is compiling a unit
test versus which is running it.
2025-06-04 12:25:49 -04:00
mlugg
aeed5f9ebd
compiler: introduce incremental debug server
In a compiler built with debug extensions, pass `--debug-incremental` to
spawn the "incremental debug server". This is a TCP server exposing a
REPL which allows querying a bunch of compiler state, some of which is
stored only when that flag is passed. Eventually, this will probably
move into `std.zig.Server`/`std.zig.Client`, but this is easier to work
with right now. The easiest way to interact with the server is `telnet`.
2025-05-25 04:43:43 +01:00
Alex Rønne Petersen
9d8adb38a1
std.Build: Make no_builtin a property of Module instead of Step.Compile.
This reflects how the compiler actually treats it.

Closes #23424.
2025-05-12 17:08:22 +02:00
Alex Rønne Petersen
fe5dbc2474
std.Build: Change Step.Compile.no_builtin from bool to ?bool.
To be in line with other, similar options.
2025-05-12 17:07:50 +02:00
mlugg
927f233ff8 compiler: allow emitting tests to an object file
This is fairly straightforward; the actual compiler changes are limited
to the CLI, since `Compilation` already supports this combination.

A new `std.Build` API is introduced to allow representing this. By
passing the `emit_object` option to `std.Build.addTest`, you get a
`Step.Compile` which emits an object file; you can then use that as you
would any other object, such as either installing it for external use,
or linking it into another step.

A standalone test is added to cover the build system API. It builds a
test into an object, and links it into a final executable, which it then
runs.

Using this build system mechanism prevents the build system from
noticing that you're running a `zig test`, so the build runner and test
runner do not communicate over stdio. However, that's okay, because the
real-world use cases for this feature don't want to do that anyway!

Resolves: #23374
2025-04-22 22:50:36 +01:00
Andrew Kelley
4e700fdf8e
Merge pull request #22516 from Jan200101/PR/build_id_option
std.Build: add build-id option
2025-04-11 16:37:46 -04:00
imreallybadatnames™️
7733b5dbe6
Merge pull request #23501 from imreallybadatnames/master
Step.Compile: use LtoMode enum for lto option
2025-04-09 05:16:36 +00:00
GalaxyShard
b5a5260546 std.Build: implement addEmbedPath for adding C #embed search directories 2025-03-27 09:47:42 +01:00
Felix "xq" Queißner
0ed905b9c6 Enables parsing for '-Wl,-rpath,' in pkg-config output, allows better support for NixOS linking. 2025-03-26 22:55:18 +01:00
Jan200101
013a228960 std.Build: add build-id option 2025-03-07 10:59:02 +01:00
David Rubin
9432a9b6e1 build: add bundle_ubsan_rt 2025-02-25 11:22:33 -08:00
Alex Rønne Petersen
f87b443af1 link.MachO: Add support for the -x flag (discard local symbols).
This can also be extended to ELF later as it means roughly the same thing there.

This addresses the main issue in #21721 but as I don't have a macOS machine to
do further testing on, I can't confirm whether zig cc is able to pass the entire
cgo test suite after this commit. It can, however, cross-compile a basic program
that uses cgo to x86_64-macos-none which previously failed due to lack of -x
support. Unlike previously, the resulting symbol table does not contain local
symbols (such as C static functions).

I believe this satisfies the related donor bounty: https://ziglang.org/news/second-donor-bounty
2025-02-22 06:35:19 +01:00
Alex Rønne Petersen
481b7bf3f0
std.Target: Remove functions that just wrap component functions.
Functions like isMinGW() and isGnuLibC() have a good reason to exist: They look
at multiple components of the target. But functions like isWasm(), isDarwin(),
isGnu(), etc only exist to save 4-8 characters. I don't think this is a good
enough reason to keep them, especially given that:

* It's not immediately obvious to a reader whether target.isDarwin() means the
  same thing as target.os.tag.isDarwin() precisely because isMinGW() and similar
  functions *do* look at multiple components.
* It's not clear where we would draw the line. The logical conclusion before
  this commit would be to also wrap Arch.isX86(), Os.Tag.isSolarish(),
  Abi.isOpenHarmony(), etc... this obviously quickly gets out of hand.
* It's nice to just have a single correct way of doing something.
2025-02-17 19:18:19 +01:00
GalaxyShard
a3ee5215bb
std.Build: Add option to specify language of CSourceFiles
Closes: #20655
2025-01-30 14:04:47 +01:00
Andrew Kelley
0d6b17b6a5
Merge pull request #22511 from apwadkar/master
Fix compiler errors in std.process and std.Build.Step.Compile
2025-01-20 22:02:38 -05:00
Adheesh Wadkar
23facb6a16 Fix dependsOnSystemLibrary compile error 2025-01-20 15:37:57 -06:00
mlugg
b8e568504e
std.Build: extend test_runner option to specify whether runner uses std.zig.Server
The previous logic here was trying to assume that custom test runners
never used `std.zig.Server` to communicate with the build runner;
however, it was flawed, because modifying the `test_runner` field on
`Step.Compile` would not update this flag. That might have been
intentional (allowing a way for the user to specify a custom test runner
which *does* use the compiler server protocol), but if so, it was a
flawed API, since it was too easy to update one field without updating
the other.

Instead, bundle these two pieces of state into a new type
`std.Build.Step.Compile.TestRunner`. When passing a custom test runner,
you are now *provided* to specify whether it is a "simple" runner, or
whether it uses the compiler server protocol.

This is a breaking change, but is unlikely to affect many people, since
custom test runners are seldom used in the wild.
2025-01-20 00:14:58 +00:00
pfg
c748eb2416
std.Build: fix setLibCFile() to add step dependencies 2025-01-17 20:42:55 +01:00
mlugg
0bb93ca053
std.Build: simplify module dependency handling
At the expense of a slight special case in the build runner, we can make
the handling of dependencies between modules a little shorter and much
easier to follow.

When module and step graphs are being constructed during the "configure"
phase, we do not set up step dependencies triggered by modules. Instead,
after the configure phase, the build runner traverses the whole
step/module graph, starting from the root top-level steps, and
configures all step dependencies implied by modules. The "make" phase
then proceeds as normal. Also, the old `Module.dependencyIterator` logic
is replaced by two separate iterables. `Module.getGraph` takes the root
module of a compilation, and returns all modules in its graph; while
`Step.Compile.getCompileDependencies` takes a `*Step.Compile` and
returns all `*Step.Compile` it depends on, recursively, possibly
excluding dynamic libraries. The old `Module.dependencyIterator`
combined these two functions into one unintuitive iterator; they are now
separated, which in particular helps readability at the usage sites
which only need one or the other.
2024-12-18 01:47:51 +05:00
mlugg
3aa8020904
std.Build.Step.Compile.Options: change root_module field type to *Module 2024-12-18 01:47:51 +05:00
mlugg
faafeb51af
std.Build.Step.Compile: change root_module field type to *Module
This commit changes the `root_module` field of `std.Build.Step.Compile`
to be a `*Module` rather than a `Module`. This is a breaking change, but
an incredibly minor one (the full potential extent of the breakage can
be seen in the modified standalone test).

This change will be necessary for an upcoming improvement, so it was
convenient to make it here.
2024-12-18 01:47:50 +05:00
Eric Joldasov
3d393dba6f
std.Build: remove deprecated APIs
These APIs were all deprecated prior to the release of 0.13.0, so can be
safety removed in the current release cycle.

`std.Build`:
* `host` -> `graph.host`

`std.Build.Step.Compile`:
* `setLinkerScriptPath` -> `setLinkerScript`
* `defineCMacro` -> `root_module.addCMacro`
* `linkFrameworkNeeded`-> `root_module.linkFramework`
* `linkFrameworkWeak`-> `root_module.linkFramework`

`std.Build.Step.ObjCopy`:
* `getOutputSource` -> `getOutput`

`std.Build.Step.Options`:
* `addOptionArtifact` -> `addOptionPath`
* `getSource` -> `getOutput`

`std.Build.Step.Run`:
* `extra_file_dependencies` -> `addFileInput`
* `addDirectorySourceArg` -> `addDirectoryArg`
* `addPrefixedDirectorySourceArg` -> `addPrefixedDirectoryArg`
2024-12-18 01:47:50 +05:00
Jay Petacat
97b8d662e6 std.Build: Detect pkg-config names with "lib" prefix 2024-11-29 15:11:14 -05:00
Andrew Kelley
4706ec81d4 introduce a CLI flag to enable .so scripts; default off
The compiler defaults this value to off so that users whose system
shared libraries are all ELF files don't have to pay the cost of
checking every file to find out if it is a text file instead.

When a GNU ld script is encountered, the error message instructs users
about the CLI flag that will immediately solve their problem.
2024-10-23 16:27:38 -07:00
Andrew Kelley
a4cc344aa0 std.Build.Step.Compile: add a way to expect an error message
other than a compile error, specifically
2024-10-23 16:27:38 -07:00
Alex Rønne Petersen
140fb615a6
std.Target: Move isLib{C,Cxx}LibName() to std.zig.target.
These are really answering questions about the Zig compiler's capacity to
provide a libc/libc++ implementation. As such, std.zig.target seems like a more
fitting place for these.
2024-10-16 22:25:13 +02:00
Alex Rønne Petersen
c76a98f28a
std.Target: Rename is_lib{c,cxx}_lib_name() to isLib{C,Cxx}LibName(). 2024-10-16 22:24:46 +02:00
Andrew Kelley
22661f3d67 link tests: add a way to check prefix and use it 2024-10-08 21:57:08 -07:00