Skip to content

Conversation

@andrewrk
Copy link
Member

Before, cache manifest files would have absolute file paths. This is problematic for two reasons:

  • Absolute file paths are not portable. Some operating systems such as WASI have trouble with them. The files themselves are less portable; they cannot be migrated from one user's home directory to another's. And finally they can break due to file paths exceeding maximum path component size.
  • They would prevent some advanced use cases of Zig, where the lib dir has a different path in a different invocation but is ultimately the same Zig version and lib directory as before.

This commit adds a new column that specifies the prefix directory for each file. 0 is an escape hatch and has the previous behavior. The other two prefixes introduced are zig lib directory, and the cache directory. This means files in zig-cache manifests can reference files local to these directories.

In practice, this means it is possible to use a different file path for the zig lib directory in a subsequent run of zig and have it still take advantage of the global cache, provided that the files inside remain unchanged.

closes #13050

@andrewrk andrewrk force-pushed the cache-path-prefixes branch from 532b0c8 to 3da0ab5 Compare November 19, 2022 21:18
@andrewrk andrewrk force-pushed the cache-path-prefixes branch 2 times, most recently from cabd955 to fb511e3 Compare November 19, 2022 23:55
@andrewrk
Copy link
Member Author

andrewrk commented Nov 20, 2022

The code looks good to me and it's passing all the tests, however, I was not able to confirm that this solves the use case from #13050 yet. I want to investigate that before merging this.

Update: I've identified the issue:

debug(cache): '/home/andy/Downloads/zig/build-release/lib2/c.zig' does not start with 'lib2'
debug(cache): '/home/andy/Downloads/zig/build-release/lib2/c.zig' does not start with '/home/andy/.cache/zig'
debug(cache): Manifest.addFile lib2/c.zig -> 0 /home/andy/Downloads/zig/build-release/lib2/c.zig

Problem is when the prefix is relative but the added file path is absolute, the prefix detection goes wrong. I'm working on a fix.

@andrewrk
Copy link
Member Author

After these two commits, we're looking good:

[nix-shell:~/Downloads/zig/build-release]$ stage4/bin/zig build-exe ~/tmp/hello.cpp -target x86_64-linux-gnu.2.34  -lc++ 

andy@ark ~/.c/zig> find o -name "*c++*"
o/d53b13118461268103716ad01cf80001/libc++.a
o/debb0065fe49f0b7d35dcebf4ae11215/libc++abi.a

[nix-shell:~/Downloads/zig/build-release]$ stage4/bin/zig build-exe ~/tmp/hello.cpp -target x86_64-linux-gnu.2.34 --zig-lib-dir lib2 -lc++ 

andy@ark ~/.c/zig> find o -name "*c++*"
o/d53b13118461268103716ad01cf80001/libc++.a
o/debb0065fe49f0b7d35dcebf4ae11215/libc++abi.a

This is ready to merge once it is passing the CI tests. I did implement a breaking change so it may take a few rounds until it is green.

@andrewrk andrewrk force-pushed the cache-path-prefixes branch 2 times, most recently from 23cc3e2 to a8c06b2 Compare November 21, 2022 01:23
@motiejus
Copy link
Contributor

First pass, just tying it to bazel-zig-cc:

$ bazel build --experimental_use_sandboxfs  --platforms=@zig_sdk//libc_aware/platform:linux_amd64_gnu.2.28 ...
INFO: Analyzed 16 targets (0 packages loaded, 0 targets configured).
INFO: Found 16 targets...
ERROR: /code/test-zigcc/BUILD:4:14: Linking zigzag-10 failed: (Exit 1): c++ failed: error executing command external/zig_sdk/tools/x86_64-linux-gnu.2.28/c++ -o bazel-out/k8-fastbuild/bin/zigzag-10 bazel-out/k8-fastbuild/bin/_objs/zigzag-10/main.o -Wl,-S -fno-lto -Wl,-S

Use --sandbox_debug to see verbose messages from the sandbox and retain the sandbox build root for debugging
warning: FileNotFound: external/zig_sdk/lib/ibc/glibc/sysdeps/x86_64/crti.S
warning: FileNotFound: external/zig_sdk/lib/ibc/glibc/sysdeps/x86_64/crtn.S
warning: FileNotFound: external/zig_sdk/lib/ibc/glibc/sysdeps/x86_64/start-2.33.S
warning: FileNotFound: external/zig_sdk/lib/ibc/glibc/stdlib/atexit.c
warning: FileNotFound: external/zig_sdk/lib/ibunwind/src/libunwind.cpp
warning: FileNotFound: external/zig_sdk/lib/ibcxx/src/algorithm.cpp
warning: FileNotFound: external/zig_sdk/lib/ibcxxabi/src/abort_message.cpp
warning: FileNotFound: external/zig_sdk/lib/ompiler_rt.zig
error: unable to build glibc CRT file: FileNotFound
error: unable to build glibc shared objects: FileNotFound
error: unable to build libunwind: FileNotFound
error: unable to build libcxx: FileNotFound
error: unable to build libcxxabi: FileNotFound
error: unable to build compiler_rt: FileNotFound

Note the missing first letter of each file/dir after the lib/.

I will dig in and try to reproduce this outside of Bazel.

@motiejus
Copy link
Contributor

I will dig in and try to reproduce this outside of Bazel.

Looks like bazel-zig-cc was adding a trailing slash to ZIG_LIB_DIR. Once I remove it, this error goes away.

@motiejus
Copy link
Contributor

I have tested this change with https://git.sr.ht/~motiejus/test-zigcc. Results:

  1. the libc stubs are reused (which means this fixes support cache hits with differently named zig lib directories which have the same contents #13050).
  2. the performance issues are still there: https://git.sr.ht/~motiejus/test-zigcc#steps-to-reproduce

@andrewrk andrewrk force-pushed the cache-path-prefixes branch 2 times, most recently from 2e51020 to a2e9dd2 Compare November 21, 2022 18:46
Before, cache manifest files would have absolute file paths. This is
problematic for two reasons:

 * Absolute file paths are not portable. Some operating systems such as
   WASI have trouble with them. The files themselves are less portable;
   they cannot be migrated from one user's home directory to another's.
   And finally they can break due to file paths exceeding maximum path
   component size.
 * They would prevent some advanced use cases of Zig, where the lib dir
   has a different path in a different invocation but is ultimately the
   same Zig version and lib directory as before.

This commit adds a new column that specifies the prefix directory for
each file. 0 is an escape hatch and has the previous behavior. The other
two prefixes introduced are zig lib directory, and the cache directory.
This means files in zig-cache manifests can reference files local to
these directories.

In practice, this means it is possible to use a different file path for
the zig lib directory in a subsequent run of zig and have it still take
advantage of the global cache, provided that the files inside remain
unchanged.

closes #13050
This is a breaking change to the API. Instead of the first path
implicitly being the current working directory, it now asserts that the
number of paths passed is greater than zero.

Importantly, it never calls getcwd(); instead, it can possibly return
".", or a series of "../". This changes the error set to only be
`error{OutOfMemory}`.

closes #13613
 * Update for the breaking changes to std.fs.path.resolve. This had a
   happy side effect of deleting some error handling code which is no
   longer needed.
 * Introduce cache_exempt_flags field to CSourceFile. This is used only
   for include directories when building libc++ and libc++abi which
   depend only on the zig lib path.
 * libc_include_dir_list is only added to the cache hash when it
   contains directories which have been obtained from system probing. It
   is exempt when the directories depend only on the zig lib path.
Fixes issues with trailing slashes and things like this.
Standard library tests require the root source file to be the
corresponding file inside the Zig lib directory. In other words, there
may not be two copies of the standard library. After the changes in this
branch, Zig no longer notices that `../lib/std.zig` and
`$(pwd)/../lib/std.zig` are the same file because one is relative and
one is absolute.
@andrewrk andrewrk force-pushed the cache-path-prefixes branch from 62ddd6c to 984acae Compare November 23, 2022 04:11
Comment on lines -3249 to -3255
error.CurrentWorkingDirectoryUnlinked,
error.Unexpected,
=> comp.lockAndSetMiscFailure(
.analyze_pkg,
"unexpected problem analyzing package '{s}'",
.{pkg.root_src_path},
),
Copy link
Contributor

@motiejus motiejus Nov 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am getting this error when compiling the PR:

            module.semaPkg(pkg) catch |err| switch (err) {
                                            ^~~~~~
/home/user/zig/src/Compilation.zig:3255:45: note: unhandled error value: 'error.CurrentWorkingDirectoryUnlinked'
/home/user/zig/src/Compilation.zig:3255:45: note: unhandled error value: 'error.Unexpected'
referenced by:
    performAllTheWork: /home/user/zig/src/Compilation.zig:3087:17
    update: /home/user/zig/src/Compilation.zig:2396:13
    remaining reference traces hidden; use '-freference-trace' to see all reference traces

I am quite puzzled how the CI passes this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect you have mixed the new binary with the old standard library. It would explain this error as well as the regression noted below regarding absolute ZIG_LIB_DIR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, not sure how this happened. I built zig like I always do. Hmm. Indeed this was a false alarm (and the reported issue below), re-checked with master.

Copy link
Contributor

@motiejus motiejus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR regresses relative paths returned by -M.

If ZIG_LIB_DIR is relative, it is desired to return relative paths in -M flags.

setup

lrwxrwxrwx 1 motiejus engineering 33 Nov 23 12:42 zig_lib_dir_0.10 -> /code/zig-linux-x86_64-0.10.0/lib
lrwxrwxrwx 1 motiejus engineering 24 Nov 23 12:42 zig_lib_dir_13596 -> /code/zig/stage3/lib/zig

/code/zig/stage3/ is zig with this PR with the Compilation.zig change reverted for zig to compile.

zig 0.10 (also current master)

$ ZIG_LIB_DIR=zig_lib_dir_0.10 /code/zig-linux-x86_64-0.10.0/zig cc -target x86_64-linux-gnu.2.28 -M main.c 
main.o: main.c zig_lib_dir_0.10/libc/include/generic-glibc/stdio.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/libc-header-start.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/features.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/features-time64.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/bits/wordsize.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/bits/timesize.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/stdc-predef.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/sys/cdefs.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/bits/long-double.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/gnu/stubs.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/gnu/stubs-64.h \
  zig_lib_dir_0.10/include/stddef.h zig_lib_dir_0.10/include/stdarg.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/bits/typesizes.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/time64.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types/__fpos_t.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types/__mbstate_t.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types/__fpos64_t.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types/__FILE.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types/FILE.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/types/struct_FILE.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/stdio_lim.h \
  zig_lib_dir_0.10/libc/include/x86_64-linux-gnu/bits/floatn.h \
  zig_lib_dir_0.10/libc/include/generic-glibc/bits/floatn-common.h

This PR

$ ZIG_LIB_DIR=zig_lib_dir_13596 /code/zig/stage3/bin/zig cc -target x86_64-linux-gnu.2.28 -M main.c 
main.o: main.c \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/stdio.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/libc-header-start.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/features.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/features-time64.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/bits/wordsize.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/bits/timesize.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/stdc-predef.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/sys/cdefs.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/bits/long-double.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/gnu/stubs.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/gnu/stubs-64.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/include/stddef.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/include/stdarg.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/bits/typesizes.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/time64.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types/__fpos_t.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types/__mbstate_t.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types/__fpos64_t.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types/__FILE.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types/FILE.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/types/struct_FILE.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/stdio_lim.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/x86_64-linux-gnu/bits/floatn.h \
  /code/bazel-zig-cc/test/c/zig_lib_dir_13596/libc/include/generic-glibc/bits/floatn-common.h

I'd expect the paths to ZIG_LIB_DIR as returned by -M to be relative.

@andrewrk andrewrk merged commit 81d2135 into master Nov 23, 2022
@andrewrk andrewrk deleted the cache-path-prefixes branch November 23, 2022 19:51
FabianHahn pushed a commit to FabianHahn/bazel-zig-cc that referenced this pull request Dec 11, 2022
- do not pass where it's unnecessary
- remove trailing slash. That conflicts with ziglang/zig/pull/13596
Jarred-Sumner added a commit to oven-sh/bun that referenced this pull request Jan 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support cache hits with differently named zig lib directories which have the same contents

2 participants