Commit graph

570 commits

Author SHA1 Message Date
Alex Rønne Petersen
6b6e336e07
std.Build.Step.CheckObject: Truncate st_other before interpreting it
Tools are free to use the upper bits of this field for whatever; thus, tools
that want to interpret the visibility type should truncate to 2 bits.
2025-06-30 12:21:38 +02:00
Kevin Boulain
640a130651 std.Build.Watch: key fanotify file descriptors by mount id
Since marks are limited to a single filesystem.
Context: https://github.com/ziglang/zig/issues/20670
Original pull request: https://github.com/ziglang/zig/pull/20672

Co-authored-by: Maciej 'vesim' Kuliński <vesim809@pm.me>
2025-06-23 06:08:25 +02:00
Matthew Lugg
75d0ec9c04
Merge pull request #24227 from mlugg/misc-build-stuff
`std.Build`: more miscellaneous bits
2025-06-20 10:28:38 +01:00
mlugg
4a9e8b73aa
std.Build.Step.Run: pass correct relative cache dir to tests
Fixes an additional bug reported in the closed #24216.
2025-06-20 00:33:44 +01: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
36499c251c std.Build.Step.Run: prefix relative path arguments with './'
This is necessary in two cases:

* On POSIX, the exe path (`argv[0]`) must contain a path separator
* Some programs might treat a file named e.g. `-foo` as a flag, which
  can be avoided by passing `./-foo`

Rather than detecting these two cases, just always include the prefix;
there's no harm in it.

Also, if the cwd is specified, include it in the manifest. If the user
has set the cwd of a Run step, it is clearly because this affects the
behavior of the executable somehow, so that cwd path should be a part of
the step's manifest.

Resolves: #24216
2025-06-18 22:45:05 +01:00
mlugg
f3c0555975
std.Build: introduce ConfigHeader.getOutputDir, small refactor
`std.Build.Step.ConfigHeader` emits a *directory* containing a config
header under a given sub path, but there's no good way to actually
access that directory as a `LazyPath` in the configure phase. This is
silly; it's perfectly valid to refer to that directory, perhaps to
explicitly pass as a "-I" flag to a different toolchain invoked via a
`Step.Run`. So now, instead of the `GeneratedFile` being the actual
*file*, it should be that *directory*, i.e. `cache/o/<digest>`. We can
then easily get the *file* if needed just by using `LazyPath.path` to go
"deeper", which there is a helper function for.

The legacy `getOutput` function is now a deprecated alias for
`getOutputFile`, and `getOutputDir` is introduced.

`std.Build.Module.IncludeDir.appendZigProcessFlags` needed a fix after
this change, so I took the opportunity to refactor it a little. I was
looking at this function while working on ziglang/translate-c yesterday
and realised it could be expressed much more simply -- particularly
after the `ConfigHeader` change here.

I had to update the test `standalone/cmakedefine/` -- it turns out this
test was well and truly reaching into build system internals, and doing
horrible not-really-allowed stuff like overriding the `makeFn` of a
`TopLevelStep`. To top it all off, the test forgot to set
`b.default_step` to its "test" step, so the test never even ran. I've
refactored it to follow accepted practices and to actually, like, work.
2025-06-17 11:55:36 +01:00
mlugg
a92427bf27
Build.Cache.Path: fix resolvePosix empty sub_path
This function is sometimes used to assume a canonical representation of
a path. However, when the `Path` referred to `root_dir` itself, this
function previously resolved `sub_path` to ".", which is incorrect; per
doc comments, it should set `sub_path` to "".

This fix ultimately didn't solve what I was trying to solve, though I'm
still PRing it, because it's still *correct*. The background to this
commit is quite interesting and worth briefly discussing.

I originally worked on this to try and fix a bug in the build system,
where if the root package (i.e. the one you `zig build`) depends on
package X which itself depends back on the root package (through a
`.path` dependency), invalid dependency modules are generated. I hit
this case working on ziglang/translate-c, which wants to depend on
"examples" (similar to the Zig compiler's "standalone" test cases) which
themselves depend back on the translate-c package. However, after this
patch just turned that error into another, I realised that this case
simply cannot work, because `std.Build` needs to eagerly execute build
scripts at `dependency` calls to learn which artifacts, modules, etc,
exist.

...at least, that's how the build system is currently designed. One can
imagine a world where `dependency` sort of "queues" the call, `artifact`
and `module` etc just pretend that the thing exists, and all configure
functions are called non-recursively by the runner. The downside is that
it becomes impossible to query state set by a dependency's configure
script. For instance, if a dependency exposes an artifact, it would
become impossible to get that artifact's resolved target in the
configure phase. However, as well as allowing recursive package imports
(which are certainly kinda nifty), it would also make lazy dependencies
far more useful! Right now, lazy dependencies only really work if you
use options (`std.Build.option`) to block their usage, since any call to
`lazyDependency` causes the dependency to be fetched. However, if we
made this change, lazy dependencies could be made far more versatile by
only fetching them *if the final step plan requires them*. I'm not 100%
sure if this is a good idea or not, but I might open an issue for it
soon.
2025-06-17 11:06:39 +01:00
mlugg
14e033ed95
std.Build.Step.Run: convert relative paths to be relative to child cwd
Because any `LazyPath` might be resolved to a relative path, it's
incorrect to pass that directly to a child process whose cwd might
differ. Instead, if the child has an overriden cwd, we need to convert
such paths to be relative to the child cwd using `std.fs.path.relative`.
2025-06-13 16:30:39 +01: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
Alex Rønne Petersen
6810ffa424
Merge pull request #24031 from ypsvlq/master
Haiku fixes
2025-06-10 17:54:19 +02:00
Andrew Kelley
4d79806459 std.Build.Step.Run: add addDecoratedDirectoryArg function
For directory arguments that need both prefix and suffix strings
appended.

Needed to unbreak ffmpeg package after fe855691f6
2025-06-09 05:25:30 -04:00
Elaine Gibson
2cfa0f567d std.Build.Watch: not supported on haiku 2025-06-05 13:45:47 +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
Alex Rønne Petersen
87f8f47ba5
std.Build: Demote errors for exceeding max_rss to warnings.
We have no control over memory usage on arbitrary systems in the wild. But we
would still like to get the warnings so we can adjust the values based on
observations in the official ZSF CI.

Closes #23254.
Closes #23638.
2025-06-02 20:55:01 +02: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
mlugg
fe855691f6
std.Build.Step.Run: inherit build runner cwd
Right now, if you override the build root with `--build-root`, then
`Run` steps can fail to execute because of incorrect path handling in
the compiler: `std.process.Child` gets a cwd-relative path, but also has
its cwd set to the build root. The latter behavior is really weird; it
doesn't match my expectations, nor does it match how we spawn child
`zig` processes. So, this commit makes the child process inherit the
build runner's cwd, as `LazyPath.getPath2` *expects* it to.

After investigating, this behavior dates all the way back to 2017; it
was introduced in 4543413. So, there isn't any clear/documented reason
for this; it should be safe to revert, since under the modern `LazyPath`
system it is strictly a bug AFAICT.
2025-05-21 01:45:05 +01:00
mlugg
d32829e053
std.Build.Cache: change contract of addFilePostContents
This function was broken, because it took ownership of the buffer on
error *sometimes*, in a way which the caller could not tell. Rather than
trying to be clever, it's easier to just follow the same interface as
all other `addFilePost` methods, and not take ownership of the path.

This is a breaking change. The next commits will apply it to the
compiler, which is the only user of this function in the ziglang/zig
repository.
2025-05-18 17:10:04 +01:00
Alex Rønne Petersen
5b606d435d
Merge pull request #21882 from alexrp/compiler-fixes
compiler: Fix some real and theoretical miscompilations with `allowzero` and `volatile`
2025-05-13 10:42:05 +02:00
wooster0
a365971a33 std.meta.intToEnum -> std.enums.fromInt
Also use an optional as the return type instead of an error code.
2025-05-13 07:28:41 +02: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
Alex Rønne Petersen
35f30558ad
std.Build: Rename --glibc-runtimes to --libc-runtimes and enable it for musl. 2025-05-06 01:52:47 +02:00
mlugg
3783b1b23c std.Build.Cache: fix several bugs
Aside from adding comments to document the logic in `Cache.Manifest.hit`
better, this commit fixes two serious bugs.

The first, spotted by Andrew, is that when upgrading from a shared to an
exclusive lock on the manifest file, we do not seek it back to the
start. This is a simple fix.

The second is more subtle, and has to do with the computation of file
digests. Broadly speaking, the goal of the main loop in `hit` is to
iterate the files listed in the manifest file, and check if they've
changed, based on stat and a file hash. While doing this, the
`bin_digest` field of `std.Build.Cache.File`, which is initially
`undefined`, is populated for all files, either straight from the
manifest (if the stat matches) or recomputed from the file on-disk. This
file digest is then used to update `man.hash.hasher`, which is building
the final hash used as, for instance, the output directory name when the
compiler emits into the cache directory. When `hit` returns a cache
miss, it is expected that `man.hash.hasher` includes the digests of all
"initial files"; that is, those which have been already added with e.g.
`addFilePath`, but not those which will later be added with
`addFilePost` (even though the manifest file has told us about some such
files). Previously, `hit` was using the `unhit` function to do this in a
few cases. However, this is incorrect, because `hit` assumes that all
files already have their `bin_digest` field populated; this function is
only valid to call *after* `hit` returns. Instead, we need to actually
compute the hashes which haven't yet been populated. Even if this logic
has been working, there was still a bug here, because we called `unhit`
when upgrading from a shared to an exclusive lock, writing the
(potentially `undefined`) file digests, but the loop itself writes the
file digests *again*! All in all, the hashing logic here was actually
incredibly broken.

I've taken the opportunity to restructure this section of the code into
what I think is a more readable format. A new function,
`hitWithCurrentLock`, uses the open manifest file to try and find a
cache hit. It returns a tagged union which, in the miss case, tells the
caller (`hit`) how many files already have their hash populated. This
avoids redundant work recomputing the same hash multiple times in
situations where the lock needs upgrading. This also eliminates the
outer loop from `hit`, which was a little confusing because it iterated
no more than twice!

The bugs fixed here could manifest in several different ways depending
on how contended file locks were satisfied. Most notably, on a cache
miss, the Zig compiler might have written the compilation output to the
incorrect directory (because it incorrectly constructed a hash using
`undefined` or repeated file digests), resulting in all future hits on
this manifest causing `error.FileNotFound`. This is #23110. I have been
able to reproduce #23110 on `master`, and have not been able to after
this commit, so I am relatively sure this commit resolves that issue.

Resolves: #23110
2025-04-27 05:42:18 +01:00
Alex Rønne Petersen
b3537d0f4a compiler: Allow configuring UBSan mode at the module level.
* Accept -fsanitize-c=trap|full in addition to the existing form.
* Accept -f(no-)sanitize-trap=undefined in zig cc.
* Change type of std.Build.Module.sanitize_c to std.zig.SanitizeC.
* Add some missing Compilation.Config fields to the cache.

Closes #23216.
2025-04-26 22:54:34 +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
Alex Rønne Petersen
667035fc78 std.Build.Step: Don't capture a stack trace if !std.debug.sys_can_stack_trace. 2025-04-14 06:06:07 +02:00
Andrew Kelley
f32a5d349d std: eradicate u29 and embrace std.mem.Alignment 2025-04-13 02:20:32 -04: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
dweiller
b84db311d9 zig build: add env_map entries to hash for Step.Run
This change fixes false-positive cache hits for run steps that get run
with different sets of environment variables due the the environment map
being excluded from the cache hash.
2025-03-26 14:48:04 +01:00
rpkak
9f8d938d38 DepTokenizer: allow space between target and colon 2025-03-24 15:31:03 +01:00
Loris Cro
11b49e9002 std.Build.Watch: fix macos implementation
The code did one useless thing and two wrong things:

- ref counting was basically a noop
- last_dir_fd was chosen from the wrong index and also under the wrong
  condition

This caused regular crashes on macOS which are now gone.
2025-03-15 05:29:54 +00:00
Pat Tullmann
214750fcfe lib/std/Build/Cache.zig: remove .wasi SkipZigTest checks
The build Cache test pass on Wasi now.

Fixes #5437
2025-03-08 04:38:29 +01:00
Andrew Kelley
5765736867 fix InstallArtifact opening empty string
this appears to have been a problem since 43f73af359
2025-03-07 15:21:40 -05:00
Jan200101
013a228960 std.Build: add build-id option 2025-03-07 10:59:02 +01:00
Andrew Kelley
1e2b3b1df9 std.Build.Step: fix missing path sep in error message
I have a more robust solution to this coming up in the writer interface
branch.
2025-03-03 17:18:18 -08:00
Andrew Kelley
6b6c1b1b0e Revert "Merge pull request #22898 from kristoff-it/deprecated-proposal"
This reverts commit dea72d15da, reversing
changes made to ab381933c8.

The changeset does not work as advertised and does not have sufficient
test coverage.

Reopens #22822
2025-02-28 01:37:10 -08:00
Loris Cro
43a949ee95 fix regressed build system unit test 2025-02-26 14:41:33 -05:00
Andrew Kelley
c5aa680c88 don't inherit allowed deprecation from parent modules
Inheriting allow-deprecation from parent modules doesn't make too much
sense, so instead make them default to disallow unless otherwise
specified. This allows build system to avoid redundant
`-fno-allow-deprecated` args.

This makes the generated CLIs smaller, and makes zig1.wasm update not
needed.

Also represented `is_root` differently (moved to field of graph).
2025-02-26 14:41:33 -05:00
Loris Cro
25790e95f1 @deprecated: remove per-module flag in Build
This implementation looks at the builder of each
module in the build graph instead of storing a
boolean for each module.
2025-02-26 14:41:33 -05:00
Loris Cro
ba7cd8121d @deprecated: add build system support 2025-02-26 14:41:33 -05:00
David Rubin
9432a9b6e1 build: add bundle_ubsan_rt 2025-02-25 11:22:33 -08:00
Andrew Kelley
e47f340e23 std.Build.Step.ConfigHeader: follow deprecation policy 2025-02-23 12:45:35 -08:00
Andrew Kelley
86f35479d9
Merge pull request #22794 from cbilz/autoconf_at
std.Build.Step.ConfigHeader: Add support for Autoconf-style `@FOO@` variables
2025-02-23 15:36:49 -05:00
Constantin Bilz
75b0538688 std.Build: Allow ConfigHeader values to be added at build.zig runtime 2025-02-22 23:31:17 -05:00