Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gcc12, gcc13: always mangle __FILE__ into invalid store path #255192

Merged
merged 1 commit into from
Oct 8, 2023

Conversation

trofi
Copy link
Contributor

@trofi trofi commented Sep 14, 2023

Before the change macros like assert() embedded paths to source file into an executable binary. Examples are nlohmann_json embedding into nix:

$ nix shell nixpkgs#nix nixpkgs#binutils-unwrapped nixpkgs#which
$ strings $(which nix) | fgrep nlohmann_json
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/json.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/output/serializer.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/conversions/to_chars.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/input/lexer.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/iterators/iter_impl.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/input/json_sax.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/iterators/iteration_proxy.hpp
/nix/store/5xih6daf5g3hpa0wc5vs2cgrhakn4s0j-nlohmann_json-3.11.2/include/nlohmann/detail/input/parser.hpp

Sometimes these dependencies are not too large: nlohmann_json is "just" 1MB of headers code.

But sometimes the -dev outputs contain python scripts and other build-only dependencies. The example is lttng-ust.

Description of changes

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandbox = true set in nix.conf? (See Nix manual)
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 23.11 Release Notes (or backporting 23.05 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

@trofi trofi requested a review from a user September 14, 2023 22:06
@trofi
Copy link
Contributor Author

trofi commented Sep 14, 2023

And examples like pipewire reduced their closure down for about 20% (~90MB):

Before:

$ nix path-info -rsSh $(nix-build '<nixpkgs>' -A pipewire.out) | nl | tail -n1
   219  /nix/store/ff0w34nr807in3b1swmqklxy9g9v5hg9-pipewire-0.3.79 1.4M  543.4M

After:

$ nix path-info -rsSh $(nix-build ~/n -A pipewire.out) | nl | tail -n1
   207  /nix/store/hl4dffvc73nsh3zfbji0y7h9lcnrk14b-pipewire-0.3.79 1.3M  452.0M

@Mindavi
Copy link
Contributor

Mindavi commented Sep 15, 2023

This seems like a pretty safe change to me and will reduce closure size in (presumably) all sorts of places. My bash-foo is not up to speed, so I'll leave that to others.

@trofi
Copy link
Contributor Author

trofi commented Sep 15, 2023

Even dedupe is still able to fail qemu build, but a bit later:

-----------
Command line: `gcc -m64 -mcx16 /build/qemu-8.1.0/build/meson-private/tmpbyikv8nc/testfile.c -o /build/qemu-8.1.0/build/meson-private/tmpbyikv8nc/output.exe -D_FILE_OFFSET_BITS=64 -O0 -Wl,--start-group -laio -Wl,--end-group -Wl,--allow-shlib-undefined` -> 1
stderr:
gcc: fatal error: cannot execute '/nix/store/yabgsv2ahyxk7v8n1msp4z8ybaw12ham-gcc-14.0.0/libexec/gcc/x86_64-unknown-linux-gnu/14.0.0/cc1': execv: Argument list too long
compilation terminated.
-----------

Will try a response file instead. Converting to draft.

@trofi
Copy link
Contributor Author

trofi commented Sep 15, 2023

An attempt to use response files populated in setup hooks has at least 3 problems:

  • expandResponseParams is empty in early bootstrap and that triggers a deficiency in gcc-8
  • setupHook can't create files as nix develop executes setupHooks in a separate derivation
  • something in response file file presence breaks -lstdc++ file detection in audiofile package

@trofi
Copy link
Contributor Author

trofi commented Sep 21, 2023

Response files would not help shorter term either: https://trofi.github.io/posts/299-maximum-argument-count-on-linux-and-in-gcc.html

It might be simpler to patch gcc and clang directly until response file infrastructure is ready.

@trofi trofi changed the title cc-wrapper/setup-hook.sh: mangle __FILE__ macros to not point to store gcc12, gcc13: always mangle __FILE__ into invalid store path Sep 23, 2023
@trofi trofi marked this pull request as ready for review September 23, 2023 21:56
@trofi
Copy link
Contributor Author

trofi commented Sep 23, 2023

Filed https://gcc.gnu.org/PR111527 for longer term solution in gcc. Switched to direct gcc patching to mangle NIX_STORE references out of __FILE__ macros.

The patches still are able to reduce nix and pipewire closure. Ready for review.

@ofborg ofborg bot removed the 10.rebuild-darwin-stdenv This PR causes stdenv to rebuild label Sep 23, 2023
it's not a problem, but for headers in `/nix/store` this causes `-dev`
inputs to be retained in runtime closure.

Typical examples are `nix` -> `nlonhamm_json` and `pipewire` ->
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: nlohmann

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, good catch! Fixed typo in 3 places.

Copy link
Contributor

@Mindavi Mindavi left a comment

Choose a reason for hiding this comment

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

I think this is a fine solution and it probably won't hurt any users outside. FILE is mostly an indication anyway.

@trofi
Copy link
Contributor Author

trofi commented Sep 24, 2023

As a longer-term workaround proposed limit increase in linux kernel as well: https://lkml.org/lkml/2023/9/24/381

maps = map;
}

+/* Forward declatration for a $NIX_STORE remap hack below. */
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
+/* Forward declatration for a $NIX_STORE remap hack below. */
+/* Forward declaration for a $NIX_STORE remap hack below. */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the patch. Thank you!

maps = map;
}

+/* Forward declatration for a $NIX_STORE remap hack below. */
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
+/* Forward declatration for a $NIX_STORE remap hack below. */
+/* Forward declaration for a $NIX_STORE remap hack below. */

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the patch. Thank you!

Copy link
Member

@RaitoBezarius RaitoBezarius left a comment

Choose a reason for hiding this comment

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

I do not have enough expertise in GCC to take responsibility. But the patch seems sane, the solution seems reasonable. I am in favor of this change.

@Artturin
Copy link
Member

Artturin commented Oct 4, 2023

Building pkgsCross.aarch64-multiplatform.sway

@Ericson2314
Copy link
Member

@trofi Have you tried to submit this patch upstream? I am recalling how I never got around to that with the Binutils patch, and then it became hard to maintain and that patch was puled out (by you no less :P).

I sorely miss that patch (now, because LLVM depends on libbfd for the LTO plugin, I always end up recompiling LLVM for new arches even though it is multitarget). I don't want you to lose this patch and miss it too. So I think the lesson is to submit upstream first.

To be clear I am definitely not saying we should block doing this on them accepting the patch. Rather that there should at least be an email thread we can link in Nixpkgs, and have the upstreaming process be started. Perfectly fine if it a takes a while for it to resolve itself.

Without the change `__FILE__` used in static inline functions in headers
embed paths to header files into executable images. For local headers
it's not a problem, but for headers in `/nix/store` this causes `-dev`
inputs to be retained in runtime closure.

Typical examples are `nix` -> `nlonhmann_json` and `pipewire` ->
`lttng-ust.dev`.

Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as:

  -fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver
  -fmacro-prefix-map=/nix/...

In practice it quickly exhausts argument lengtth limit due to `gcc`
deficiency: https://gcc.gnu.org/PR111527

Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
is present in the environment.

Tested as:

    $ printf "# 0 \"/nix/store/01234567890123456789012345678901-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o -
    ...
    .string "/nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-pppppp-vvvvvvv"
    ...

Mangled successfully.
@trofi trofi force-pushed the cc-wrapper-no-__FILE_-refs branch from bea823c to 5371767 Compare October 4, 2023 20:16
@trofi
Copy link
Contributor Author

trofi commented Oct 4, 2023

I am recalling how I never got around to that with the Binutils patch, and then it became hard to maintain and that patch was puled out (by you no less :P).

I sorely miss that patch (now, because LLVM depends on libbfd for the LTO plugin, I always end up recompiling LLVM for new arches even though it is multitarget). I don't want you to lose this patch and miss it too. So I think the lesson is to submit upstream first.

binutils patch context: Heh, it's still there for outdated 2.38 if you want to have a look: https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/tools/misc/binutils/2.38/build-components-separately.patch . In case of this patch it's very invasive to the build system. binutils introduced extra internal libraries (and nixpkgs attributes) which does not make it easy to port and switch back/forth with the patch.

I agree downstream changes are a problem. I hoped gcc hack would be more self-contained: it's ok to drop the patch and get larger closures (no extra changes need to be proliferated to the rest of nixpkgs).

To be clear I am definitely not saying we should block doing this on them accepting the patch. Rather that there should at least be an email thread we can link in Nixpkgs, and have the upstreaming process be started. Perfectly fine if it a takes a while for it to resolve itself.

@trofi Have you tried to submit this patch upstream?

This patch is a bit hacky as it hardcodes NIX_STORE_DIR variable and assumes rigid hash structure. More generic mangling mechanism might be more acceptable (some kind of template-based or regex-based mangling).

If you think it's fine as is I can propose to send it upstream as well. I can also do it optional upstream with a compile-time "on" flag.

Longer term I would prefer to be able to pass megabytes of options to gcc as is (and to clang as a byproduct):

@trofi
Copy link
Contributor Author

trofi commented Oct 4, 2023

Sent the problem statement with this proof-of-concept patch to gcc mailing list: https://gcc.gnu.org/pipermail/gcc/2023-October/242636.html

@Artturin
Copy link
Member

Artturin commented Oct 5, 2023

pkgsCross.aarch64-multiplatform.sway built, no runtime closure size diff.

@trofi
Copy link
Contributor Author

trofi commented Oct 5, 2023

pkgsCross.aarch64-multiplatform.sway built, no runtime closure size diff.

sway does not have a very big runtime closure. I found pipewire (and it's users) a bit different.

Copy link
Member

@Artturin Artturin left a comment

Choose a reason for hiding this comment

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

Build-wise it works

@Artturin Artturin merged commit b64b1ed into NixOS:staging Oct 8, 2023
9 checks passed
@trofi trofi deleted the cc-wrapper-no-__FILE_-refs branch October 8, 2023 06:00
@dotlambda
Copy link
Member

This broke python3.pkgs.deltachat: #267870 (comment)

-fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/eeee.eee-nlohmann-json-ver
-fmacro-prefix-map=/nix/...

In practice it quickly exhausts argument lengtth limit due to `gcc`
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
In practice it quickly exhausts argument lengtth limit due to `gcc`
In practice it quickly exhausts argument length limit due to `gcc`

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Proposed the fix as #268923

In practice it quickly exhausts argument lengtth limit due to `gcc`
deficiency: https://gcc.gnu.org/PR111527

Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Until it;s fixed let's hardcode header mangling if $NIX_STORE variable
Until it's fixed let's hardcode header mangling if $NIX_STORE variable

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! Proposed the fix as #268923

@trofi
Copy link
Contributor Author

trofi commented Nov 21, 2023

This broke python3.pkgs.deltachat: #267870 (comment)

Good find! Proposed the fix as #268920

roconnor-blockstream added a commit to BlockstreamResearch/simplicity that referenced this pull request Nov 30, 2023
The 23.11 release of NixOS has caused GCC to mangle __FILE__ names withing the
nix-store.  See <NixOS/nixpkgs#255192>.  This causes
gcov to fail with file-not-found errors:

    (DEBUG) Running gcov: 'gcov /build/source/rsort.gcda --branch-counts --branch-probabilities --demangled-names --hash-filenames --object-directory /build/source' in '/build/source'
    (ERROR) GCOV produced the following errors processing /build/source/rsort.gcda:
            Cannot open source file /nix/store/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-glibc-2.38-27-dev/include/bits/string_fortified.h

To work around this issue we add the --relative-only flag to gcov instucting it
to not consider files with absoulte paths, thus excluding header files in the nix-store.

Note: these files were already filtered out by gcovr, so the resulting
documentation hasn't really changed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants