Commit graph

64 commits

Author SHA1 Message Date
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
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
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
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
Meghan Denny
a8af36ab10 std.ArrayHashMap: popOrNul() -> pop() 2025-02-07 17:52:19 -08:00
Andrew Kelley
7ff42eff91 std.Build.Cache.hit: work around macOS kernel bug
The previous commit cast doubt upon the initial report about macOS
kernel behavior, identifying another reason that ENOENT could be
returned from file creation.

However, it is demonstrable that ENOENT can be returned for both cases:
1. create file race
2. handle refers to deleted directory

This commit re-introduces the workaround for the file creation race on
macOS however it does not unconditionally retry - it first tries again
with O_EXCL to disambiguate the error condition that has occurred.
2024-12-11 11:56:44 -08:00
Andrew Kelley
d37ee79535 std.Build.Cache.hit: more discipline in error handling
Previous commits

2b0929929d
4ea2f441df

had this text:

> There are no dir components, so you would think that this was
> unreachable, however we have observed on macOS two processes racing to
> do openat() with O_CREAT manifest in ENOENT.

This appears to have been a misunderstanding based on the issue
report #12138 and corresponding PR #12139 in which the steps to
reproduce removed the cache directory in a loop which also executed
detached Zig compiler processes.

There is no evidence for the macOS kernel bug however the ENOENT is
easily explained by the removal of the cache directory.

This commit reverts those commits, ultimately reporting the ENOENT as an
error rather than repeating the create file operation. However this
commit also adds an explicit error set to `std.Build.Cache.hit` as well
as changing the `failed_file_index` to a proper diagnostic field that
fully communicates what failed, leading to more informative error
messages on failure to check the cache.

The equivalent failure when occuring for AstGen performs a fatal process
kill, reasoning being that the compiler has an invariant of the cache
directory not being yanked out from underneath it while executing. This
could be made a more granular error in the future but I suspect such
thing is not valuable to pursue.

Related to #18340 but does not solve it.
2024-12-10 18:11:12 -08:00
Alex Rønne Petersen
24ecf45569
std.Target: Add Os.HurdVersionRange for Os.Tag.hurd.
This is necessary since isGnuLibC() is true for hurd, so we need to be able to
represent a glibc version for it.

Also add an Os.TaggedVersionRange.gnuLibCVersion() convenience function.
2024-11-24 22:11:16 +01:00
Alex Rønne Petersen
3c1ccbdf39
std.Target: Add support for specifying Android API level. 2024-11-01 06:23:59 +01:00
Andrew Kelley
e567abb339 rework linker inputs
* Compilation.objects changes to Compilation.link_inputs which stores
  objects, archives, windows resources, shared objects, and strings
  intended to be put directly into the dynamic section. Order is now
  preserved between all of these kinds of linker inputs. If it is
  determined the order does not matter for a particular kind of linker
  input, that item should be moved to a different array.
* rename system_libs to windows_libs
* untangle library lookup from CLI types
* when doing library lookup, instead of using access syscalls, go ahead
  and open the files and keep the handles around for passing to the
  cache system and the linker.
* during library lookup and cache file hashing, use positioned reads to
  avoid affecting the file seek position.
* library directories are opened in the CLI and converted to Directory
  objects, warnings emitted for those that cannot be opened.
2024-10-23 16:27:38 -07:00
Andrew Kelley
1ba3fc90be link.Elf: eliminate an O(N^2) algorithm in flush()
Make shared_objects a StringArrayHashMap so that deduping does not
need to happen in flush. That deduping code also was using an O(N^2)
algorithm, which is not allowed in this codebase. There is another
violation of this rule in resolveSymbols but this commit does not
address it.

This required reworking shared object parsing, breaking it into
independent components so that we could access soname earlier.

Shared object parsing had a few problems that I noticed and fixed in
this commit:
* Many instances of incorrect use of align(1).
* `shnum * @sizeOf(elf.Elf64_Shdr)` can overflow based on user data.
* `@divExact` can cause illegal behavior based on user data.
* Strange versyms logic that wasn't present in mold nor lld. The logic
  was not commented and there is no git blame information in ziglang/zig
  nor kubkon/zld. I changed it to match mold and lld instead.
* Use of ArrayList for slices of memory that are never resized.
* finding DT_VERDEFNUM in a different loop than finding DT_SONAME.
  Ultimately I think we should follow mold's lead and ignore this
  integer, relying on null termination instead.
* Doing logic based on VER_FLG_BASE rather than ignoring it like mold
  and LLD do. No comment explaining why the behavior is different.
* Mutating the original ELF symbols rather than only storing the mangled
  name on the new Symbol struct.

I noticed something that I didn't try to address in this commit: Symbol
stores a lot of redundant information that is already present in the ELF
symbols. I suspect that the codebase could benefit from reworking Symbol
to not store redundant information.

Additionally:
* Add some type safety to std.elf.
* Eliminate 1-3 file system reads for determining the kind of input
  files, by taking advantage of file name extension and handling error
  codes properly.
* Move more error handling methods to link.Diags and make them
  infallible and thread-safe
* Make the data dependencies obvious in the parameters of
  parseSharedObject. It's now clear that the first two steps (Header and
  Parsed) can be done during the main Compilation pipeline, rather than
  waiting for flush().
2024-10-12 10:44:17 -07:00
Andrew Kelley
14c8e270bb link: fix false positive crtbegin/crtend detection
Embrace the Path abstraction, doing more operations based on directory
handles rather than absolute file paths. Most of the diff noise here
comes from this one.

Fix sorting of crtbegin/crtend atoms. Previously it would look at all
path components for those strings.

Make the C runtime path detection partially a pure function, and move
some logic to glibc.zig where it belongs.
2024-10-10 14:21:52 -07:00
mlugg
0fe3fd01dd
std: update std.builtin.Type fields to follow naming conventions
The compiler actually doesn't need any functional changes for this: Sema
does reification based on the tag indices of `std.builtin.Type` already!
So, no zig1.wasm update is necessary.

This change is necessary to disallow name clashes between fields and
decls on a type, which is a prerequisite of #9938.
2024-08-28 08:39:59 +01:00
Robin Voetter
43f73af359
fix various issues related to Path handling in the compiler and std
A compilation build step for which the binary is not required could not
be compiled previously. There were 2 issues that caused this:

- The compiler communicated only the results of the emitted binary and
  did not properly communicate the result if the binary was not emitted.

  This is fixed by communicating the final hash of the artifact path (the
  hash of the corresponding /o/<hash> directory) and communicating this
  instead of the entire path. This changes the zig build --listen protocol
  to communicate hashes instead of paths, and emit_bin_path is accordingly
  renamed to emit_digest.

- There was an error related to the default llvm object path when
  CacheUse.Whole was selected. I'm not really sure why this didn't manifest
  when the binary is also emitted.

  This was fixed by improving the path handling related to flush() and
  emitLlvmObject().

In general, this commit also improves some of the path handling throughout
the compiler and standard library.
2024-08-19 19:09:11 +02:00
Andrew Kelley
94f4f9c4ef add sub-compilation cache inputs to parents in whole mode
closes #20782
2024-07-24 19:40:54 -07:00
Andrew Kelley
5a34e6c3e6 frontend: add file system inputs for incremental cache mode
These are also used for whole cache mode in the case that any compile
errors are emitted.
2024-07-12 00:15:11 -07:00
Andrew Kelley
a3c20dffae integrate Compile steps with file watching
Updates the build runner to unconditionally require a zig lib directory
parameter. This parameter is needed in order to correctly understand
file system inputs from zig compiler subprocesses, since they will refer
to "the zig lib directory", and the build runner needs to place file
system watches on directories in there.

The build runner's fanotify file watching implementation now accounts
for when two or more Cache.Path instances compare unequal but ultimately
refer to the same directory in the file system.

Breaking change: std.Build no longer has a zig_lib_dir field. Instead,
there is the Graph zig_lib_directory field, and individual Compile steps
can still have their zig lib directories overridden. I think this is
unlikely to break anyone's build in practice.

The compiler now sends a "file_system_inputs" message to the build
runner which shares the full set of files that were added to the cache
system with the build system, so that the build runner can watch
properly and redo the Compile step. This is implemented for whole cache
mode but not yet for incremental cache mode.
2024-07-12 00:14:08 -07:00
Andrew Kelley
f2856403c6 introduce std.Build.Cache.Manifest.addFilePath
and deprecate `addFile`. Part of an effort to move towards using
`std.Build.Cache.Path` abstraction in more places, which makes it easier
to avoid absolute paths and path resolution.
2024-07-12 00:14:08 -07:00
Andrew Kelley
7ed2fbd755 std.Build.Cache: add binToHex function
reduces need for API users to rely on formatted printing, even though
that's how it is currently implemented.
2024-07-04 17:12:45 -07:00
Ben Crist
a9e9c9965d
Build system: Support Windows depfiles with unquoted, backslash escaped spaces (#20100) 2024-06-06 18:40:10 +00:00
Jacob Young
ad72172293 Build.Step.Run: fix cache management when there are side effects
Closes #19947
2024-05-20 07:45:31 -04:00
Ryan Liptak
b86c4bde64 Rename Dir.writeFile2 -> Dir.writeFile and update all callsites
writeFile was deprecated in favor of writeFile2 in f645022d16. This commit renames writeFile2 to writeFile and makes writeFile2 a compile error.
2024-05-03 13:29:22 -07:00
Jacob Young
af0668d6c2 Build.Cache: fix UAF during unhit 2024-03-24 18:28:16 +00:00
Andrew Kelley
950359071b std.Build.Cache: bump manifest_file_size_max to 100M
Some users are hitting this limit. I think it's primarily due to not
deduplicating (solved in the previous commit) but this seems like a
better limit regardless.
2024-03-21 19:56:47 -07:00
Andrew Kelley
2f4bbd6c63 std.Build.Cache: use an array hash map for files
Rather than an ArrayList. Provides deduplication.
2024-03-21 19:56:30 -07:00
Andrew Kelley
7bc0b74b6d move Package.Path to std.Build.Cache.Path 2024-03-21 16:16:47 -07:00
Andrew Kelley
8778dc4bb2 extract std.Build.Cache.Directory into separate file 2024-03-21 16:11:59 -07:00
binarycraft007
a7a5f4cf4d objcopy: support multiple only sections 2024-03-01 09:23:54 -08:00
Ryan Liptak
68b87918df Fix handling of Windows (WTF-16) and WASI (UTF-8) paths
Windows paths now use WTF-16 <-> WTF-8 conversion everywhere, which is lossless. Previously, conversion of ill-formed UTF-16 paths would either fail or invoke illegal behavior.

WASI paths must be valid UTF-8, and the relevant function calls have been updated to handle the possibility of failure due to paths not being encoded/encodable as valid UTF-8.

Closes #18694
Closes #1774
Closes #2565
2024-02-24 14:05:24 -08:00
Jacob Young
26cb72086a Cache: fix logic for retrying cache hits
Fixes potentially #16149
2024-02-04 03:48:29 +01:00
Andrew Kelley
f64205b445
Merge pull request #18262 from ziglang/fix-18259
std.Build.Step.Run: fix depfile support
2024-01-03 13:23:40 -08:00
Andrew Kelley
12de7e3472 WIP: move many global settings to become per-Module
Much of the logic from Compilation.create() is extracted into
Compilation.Config.resolve() which accepts many optional settings and
produces concrete settings. This separate step is needed by API users of
Compilation so that they can pass the resolved global settings to the
Module creation function, which itself needs to resolve per-Module
settings.

Since the target and other things are no longer global settings, I did
not want them stored in link.File (in the `options` field). That options
field was already a kludge; those options should be resolved into
concrete settings. This commit also starts to work on that, deleting
link.Options, moving the fields into Compilation and
ObjectFormat-specific structs instead. Some fields were ephemeral and
should not have been stored at all, such as symbol_size_hint.

The link.File object of Compilation is now a `?*link.File` and `null`
when -fno-emit-bin is passed. It is now arena-allocated along with
Compilation itself, avoiding some messy cleanup code that was there
before.

On the command line, it is now possible to configure the standard
library itself by using `--mod std` just like any other module. This
meant that the CLI needed to create the standard library module rather
than having Compilation create it.

There are a lot of changes in this commit and it's still not done. I
didn't realize how quickly this changeset was going to balloon out of
control, and there are still many lines that need to be changed before
it even compiles successfully.

* introduce std.Build.Cache.HashHelper.oneShot
* add error_tracing to std.Build.Module
* extract build.zig file generation into src/Builtin.zig
* each CSourceFile and RcSourceFile now has a Module owner, which
  determines some of the C compiler flags.
2024-01-01 17:51:18 -07:00
Andrew Kelley
142471fcc4 zig build system: change target, compilation, and module APIs
Introduce the concept of "target query" and "resolved target". A target
query is what the user specifies, with some things left to default. A
resolved target has the default things discovered and populated.
In the future, std.zig.CrossTarget will be rename to std.Target.Query.
Introduces `std.Build.resolveTargetQuery` to get from one to the other.

The concept of `main_mod_path` is gone, no longer supported. You have to
put the root source file at the module root now.

* remove deprecated API
* update build.zig for the breaking API changes in this branch
* move std.Build.Step.Compile.BuildId to std.zig.BuildId
* add more options to std.Build.ExecutableOptions, std.Build.ObjectOptions,
  std.Build.SharedLibraryOptions, std.Build.StaticLibraryOptions, and
  std.Build.TestOptions.
* remove `std.Build.constructCMacro`. There is no use for this API.
* deprecate `std.Build.Step.Compile.defineCMacro`. Instead,
  `std.Build.Module.addCMacro` is provided.
  - remove `std.Build.Step.Compile.defineCMacroRaw`.
* deprecate `std.Build.Step.Compile.linkFrameworkNeeded`
  - use `std.Build.Module.linkFramework`
* deprecate `std.Build.Step.Compile.linkFrameworkWeak`
  - use `std.Build.Module.linkFramework`
* move more logic into `std.Build.Module`
* allow `target` and `optimize` to be `null` when creating a Module.
  Along with other fields, those unspecified options will be inherited
  from parent `Module` when inserted into an import table.
* the `target` field of `addExecutable` is now required. pass `b.host`
  to get the host target.
2024-01-01 17:51:18 -07:00
Loris Cro
26e27f5f64 std.Build.Cache: add HexDigest type 2023-12-11 23:08:03 +01:00
mlugg
51595d6b75
lib: correct unnecessary uses of 'var' 2023-11-19 09:55:07 +00:00
Jacob Young
8f69e977f1 x86_64: implement 128-bit builtins
* `@clz`
 * `@ctz`
 * `@popCount`
 * `@byteSwap`
 * `@bitReverse`
 * various encodings used by std
2023-10-23 22:42:18 -04:00
Jacob Young
27fe945a00 Revert "Revert "Merge pull request #17637 from jacobly0/x86_64-test-std""
This reverts commit 6f0198cadb.
2023-10-22 15:46:43 -04:00
Andrew Kelley
6f0198cadb Revert "Merge pull request #17637 from jacobly0/x86_64-test-std"
This reverts commit 0c99ba1eab, reversing
changes made to 5f92b070bf.

This caused a CI failure when it landed in master branch due to a
128-bit `@byteSwap` in std.mem.
2023-10-22 12:16:35 -07:00
Jacob Young
2e6e39a700 x86_64: fix bugs and disable erroring tests 2023-10-21 10:55:41 -04:00
Andrew Kelley
47a413361d Package.Fetch: fix handling of relative paths 2023-10-08 16:54:31 -07:00
Andrew Kelley
e5c2a7dbca finish hooking up new dependency tree logic
* add Module instances for each package's build.zig and attach it to the
  dependencies.zig module with the hash digest hex string as the name.
* fix incorrectly skipping the wrong packages for creating
  dependencies.zig
* a couple more renaming of "package" to "module"
2023-10-08 16:54:31 -07:00
Andrew Kelley
d0bcc390e8 get zig fetch working with the new system
* start renaming "package" to "module" (see #14307)
  - build system gains `main_mod_path` and `main_pkg_path` is still
    there but it is deprecated.
* eliminate the object-oriented memory management style of what was
  previously `*Package`. Now it is `*Package.Module` and all pointers
  point to externally managed memory.
* fixes to get the new Fetch.zig code working. The previous commit was
  work-in-progress. There are still two commented out code paths, the
  one that leads to `Compilation.create` and the one for `zig build`
  that fetches the entire dependency tree and creates the required
  modules for the build runner.
2023-10-08 16:54:31 -07:00
Ryan Liptak
020105d0dd Cache: Fix findPrefix when paths are slightly out of the ordinary
This makes Cache.findPrefix/findPrefixResolved use `std.fs.path.relative` instead of `std.mem.startsWith` when checking if a file is within a prefix. This fixes multiple edge cases around prefix detection:

- If a prefix path ended with a path separator, then the first character of the 'sub_path' would get cut off because the previous implementation assumed it was a path separator. Example: prefix: `/foo/`, file_path: `/foo/abc.txt` would see that they both start with `/foo/` and then slice starting from one byte past the common prefix, ending up with `bc.txt` instead of the expected `abc.txt`
- If a prefix contained double path separators after any component, then the `startsWith` check would erroneously fail. Example: prefix: `/foo//bar`, file_path: `/foo/bar/abc.txt` would not see that abc.txt is a sub path of the prefix `/foo//bar`
- On Windows, case insensitivity was not respected at all, instead the UTF-8 bytes were compared directly

This fixes all of the things in the above list (and possibly more).
2023-08-19 22:32:24 -07:00
Sahnvour
2ceeade99a std.Build: add support for deps .d file in Step.Run 2023-08-13 12:15:47 -07:00
mlugg
f26dda2117 all: migrate code to new cast builtin syntax
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:

* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
2023-06-24 16:56:39 -07:00
r00ster91
6e84f46990 std: replace builtin.Version with SemanticVersion 2023-06-17 13:17:34 -07:00
Andrew Kelley
629f0d23b5
Merge pull request #15579 from squeek502/mem-delimiters
Split `std.mem.split` and `tokenize` into `sequence`, `any`, and `scalar` versions
2023-06-03 13:51:02 -07:00
kcbanner
9244e4fe2d cache: handle 0-length prefix paths in findPrefixResolved 2023-05-30 01:21:01 -07:00
Linus Groh
ba35eeb417 std.fs.file: Rename File.Lock enum values to snake case 2023-05-25 20:17:07 +01:00
Andrew Kelley
728ce2d7c1 tweaks to --build-id
* build.zig: the result of b.option() can be assigned directly in many
   cases thanks to the return type being an optional
 * std.Build: make the build system aware of the
   std.Build.Step.Compile.BuildId type when used as an option.
   - remove extraneous newlines in error logs
 * simplify caching logic
 * simplify hexstring parsing tests and use a doc test
 * simplify hashing logic. don't use an optional when the `none` tag
   already provides this meaning.
 * CLI: fix incorrect linker arg parsing
2023-05-16 20:39:01 -07:00