Skip to content

Conversation

@cocreature
Copy link

Both -Xlinker and -install_name will often receive flags starting with
@, specifically @loader_path or @rpath. Bazel 4.0 started
interpreting those as response files which broke our build.

This PR addresses this by hardcoding those flags. This is a pretty
ugly solution so I’m very open to better ideas. That said, there is
some precedence for doing that in
rules-haskell.

Both -Xlinker and -install_name will often receive flags starting with
`@`, specifically `@loader_path` or `@rpath`. Bazel 4.0 started
interpreting those as response files which broke our build.

This PR addresses this by hardcoding those flags. This is a pretty
ugly solution so I’m very open to better ideas. That said, there is
some precedence for doing that in
[rules-haskell](https://github.com/tweag/rules_haskell/blob/e8623a8c5ea502fbe6286d8ae5fb58f4915e92c5/haskell/private/cc_wrapper.py.tpl#L448).
@google-cla google-cla bot added the cla: yes label Feb 15, 2021
@keith
Copy link
Member

keith commented Feb 15, 2021

The thought at the time we made this decision was that this form of linker flag should be replaced with -Wl,-install_name,@foo

@cocreature
Copy link
Author

Those flags are not under our control. In this case, it is the Haskell compiler GHC that is passing them https://gitlab.haskell.org/ghc/ghc/-/blob/ab1b49108e2665eb9ccdccffde0099d1785315ee/compiler/main/SysTools.hs#L376 I do agree that in an ideal world, changing the flags would be preferable but I think this is a good example that this isn’t really feasible for users in a lot of cases.

@cocreature
Copy link
Author

I guess one option would be for rules_haskell’s cc wrapper to do the rewriting but I’m not sure that’s better than handling it in Bazel itself.

@keith
Copy link
Member

keith commented Feb 16, 2021

Ah interesting. I do think it would be safe to make that compiler change, but that wouldn't solve this in the short term. At least 1 problem with this change is that there are a few other places that also duplicate this logic, see the original change and conversation for details #12265

@aiuto aiuto added the team-Rules-CPP Issues for C++ rules label Feb 19, 2021
@aherrmann
Copy link
Contributor

@keith GHC's reasoning for preferring -Xlinker over -Wl,... is documented here:

Note [-Xlinker -rpath vs -Wl,-rpath]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

-Wl takes a comma-separated list of options which in the case of
-Wl,-rpath -Wl,some,path,with,commas parses the path with commas
as separate options.
Buck, the build system, produces paths with commas in them.

-Xlinker doesn't have this disadvantage and as far as I can tell
it is supported by both gcc and clang. Anecdotally nvcc supports
-Xlinker, but not -Wl.

@keith
Copy link
Member

keith commented Feb 19, 2021

ugh!! thanks for the link. I've never heard that buck could produce commas in paths, any idea where I can see more details on that? FWIW I think a change like this would be accepted as long as it covered all the cases (although I'm not a googler so I can't make that call overall), it's just we didn't have a compelling reason to do the extra work in the previous case, so we didn't want to enumerate a list of all possible flags that could have a @ after them

@aherrmann
Copy link
Contributor

@keith I'm not familiar with Buck myself. What I understand, Buck can append comma separated flavors to targets and file names, e.g. sometarget#default,static, see also this GHC related issue on Buck's issue tracker here.

FWIW I think a change like this would be accepted as long as it covered all the cases (although I'm not a googler so I can't make that call overall)

The ones I'm aware of are -install_name, e.g. -install_name @rpath/..., and -rpath, e.g. -rpath @loader_path/....

@keith
Copy link
Member

keith commented Feb 22, 2021

I actually meant which scripts not which args. There are 3 scripts which have similar logic for this unfortunately. But it depends on what rules_haskell calls through how much of an issue that will be. I believe I solved this for wrapped_clang already with this logic

// Ignore non-file args such as '@loader_path/...'
if (!original_file.good()) {
return false;
}

You should be able to implement something similar in tools/cpp/osx_cc_wrapper.sh.tpl and tools/cpp/osx_cc_wrapper.sh (both are used in different places unfortunately)

Instead of specifying the flags that can have arguments starting with @ I think you can do something like what's being done in the C++ with:

diff --git i/tools/cpp/osx_cc_wrapper.sh w/tools/cpp/osx_cc_wrapper.sh
index 8c9c111a75..23604c7c7e 100755
--- i/tools/cpp/osx_cc_wrapper.sh
+++ w/tools/cpp/osx_cc_wrapper.sh
@@ -53,7 +53,7 @@ function parse_option() {
 
 # let parse the option list
 for i in "$@"; do
-    if [[ "$i" = @* ]]; then
+    if [[ "$i" = @* && -r "$i" ]]; then
         while IFS= read -r opt
         do
             parse_option "$opt"

@aherrmann
Copy link
Contributor

I actually meant which scripts not which args.

Oh, I see, sorry, misread.

But it depends on what rules_haskell calls through how much of an issue that will be.

Just for completeness, rules_haskell doesn't call any of these scripts explicitly. It calls the C compiler provided by Bazel's cc toolchain. I.e.

cc_common.get_tool_for_action(
        feature_configuration = feature_configuration,
        action_name = ACTION_NAMES.c_compile,
)

That may be one of Bazel's cc-wrappers. So far @bazel_tools//tools/cpp:osx_cc_wrapper.sh.tpl was the only script that triggered this issue. But, it makes sense to try and cover all instances.

Instead of specifying the flags that can have arguments starting with @ I think you can do something like what's being done in the C++ with [...]

Looks good to me.

@aherrmann
Copy link
Contributor

@keith @cocreature I've opened #13148 to replace this PR with @keith's suggestions from above applied.

@cocreature cocreature closed this Mar 3, 2021
bazel-io pushed a commit that referenced this pull request Mar 21, 2022
Closes #13044
Applies the changes suggested in #13044 (comment)

Not all arguments starting with `@` represent response files, e.g. `-install_name @rpath/...` or `-Xlinker -rpath -Xlinker @loader_path/...` do not refer to response files and attempting to read them as such will fail the build.

Users don't always have control over these arguments, meaning transforming them to `-Wl,-install_name,@rpath/...` or `-Wl,-rpath,@loader_path/...` is not always an option. E.g. as described in #13044 (comment) where these flags are emitted by the Haskell compiler GHC (see #13044 (comment) for their reasoning).

With this change `osx_cc_wrapper` will only interpret arguments starting with `@` as response files if the corresponding file exists and is readable. This is analogous to the behavior defined in `wrapped_clang.cc`. See #13044 (comment) for discussion.

Closes #13148.

PiperOrigin-RevId: 436207868
@brentleyjones
Copy link
Contributor

@bazel-io fork 5.1

brentleyjones pushed a commit to brentleyjones/bazel that referenced this pull request Mar 21, 2022
Closes bazelbuild#13044
Applies the changes suggested in bazelbuild#13044 (comment)

Not all arguments starting with `@` represent response files, e.g. `-install_name @rpath/...` or `-Xlinker -rpath -Xlinker @loader_path/...` do not refer to response files and attempting to read them as such will fail the build.

Users don't always have control over these arguments, meaning transforming them to `-Wl,-install_name,@rpath/...` or `-Wl,-rpath,@loader_path/...` is not always an option. E.g. as described in bazelbuild#13044 (comment) where these flags are emitted by the Haskell compiler GHC (see bazelbuild#13044 (comment) for their reasoning).

With this change `osx_cc_wrapper` will only interpret arguments starting with `@` as response files if the corresponding file exists and is readable. This is analogous to the behavior defined in `wrapped_clang.cc`. See bazelbuild#13044 (comment) for discussion.

Closes bazelbuild#13148.

PiperOrigin-RevId: 436207868
(cherry picked from commit efb2b80)
Wyverald pushed a commit that referenced this pull request Mar 21, 2022
Closes #13044
Applies the changes suggested in #13044 (comment)

Not all arguments starting with `@` represent response files, e.g. `-install_name @rpath/...` or `-Xlinker -rpath -Xlinker @loader_path/...` do not refer to response files and attempting to read them as such will fail the build.

Users don't always have control over these arguments, meaning transforming them to `-Wl,-install_name,@rpath/...` or `-Wl,-rpath,@loader_path/...` is not always an option. E.g. as described in #13044 (comment) where these flags are emitted by the Haskell compiler GHC (see #13044 (comment) for their reasoning).

With this change `osx_cc_wrapper` will only interpret arguments starting with `@` as response files if the corresponding file exists and is readable. This is analogous to the behavior defined in `wrapped_clang.cc`. See #13044 (comment) for discussion.

Closes #13148.

PiperOrigin-RevId: 436207868
(cherry picked from commit efb2b80)

Co-authored-by: Andreas Herrmann <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla: yes team-Rules-CPP Issues for C++ rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants