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

Use more precise compiler flags. #241

Merged
merged 4 commits into from
May 14, 2018
Merged

Use more precise compiler flags. #241

merged 4 commits into from
May 14, 2018

Conversation

judah
Copy link
Collaborator

@judah judah commented May 9, 2018

Previously, if we had a header foo/bar/baz/header.h we were passing -I
for every partial path (-Ifoo -Ifoo/bar -Ifoo/bar/baz). This is too
aggressive; in practice, it's only necessary to specify the "root" directories
like bazel-out/*/genfiles.

The previous behavior led to some problems in Hazel with headers from
different sources and the same basename confusing the preprocessor and making it
import the wrong one.

Fixed by calling individual fields of cc to get the compiler flags directly.
Then, pass them to GHC via -optP and to hsc2hs via --cflag.

For reference, this is the same approach as rules_go:
https://github.com/bazelbuild/rules_go/blob/master/go/private/rules/cgo.bzl#L187

Also add a strip_include_prefix attr to haskell_cc_import. This parameter is available for cc_library, and Bazel team has it on their roadmap to add it to cc_import as well:
bazelbuild/bazel#4748
This change does potentially break existing cc_import rules that didn't specify it previously. However, it seems worth it to fix the above issue at the cost of being more explicit.

Previously, if we had a header `foo/bar/baz/header.h` we were passing `-I`
for *every* partial path (`-Ifoo -Ifoo/bar -Ifoo/bar/baz`).  This is too
aggressive; in practice, it's only necessary to specify the "root" directories
like `bazel-out/*/genfiles`.

The previous behavior led to some problems in Hazel with headers from
different sources and the same basename confusing the preprocessor and making it
import the wrong one.

Fixed by calling `cc.compile_flags` to get the compiler flags directly.
Then, pass them to GHC via `-optP` and to hsc2hs via `--cflag`.

For reference, this is the implementation of `cc.compile_flags` which
indicates it passes preprocessor-related flags (`-D`, `-isystem`, `-iquote`
and `-I`):
https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/rules/cpp/CcSkylarkApiProvider.java#L169
@judah judah requested a review from mrkkrp May 9, 2018 23:51
@judah
Copy link
Collaborator Author

judah commented May 10, 2018

Looks like this doesn't interact as well with haskell_cc_import on Linux. I'll debug this further.

@judah judah removed the request for review from mrkkrp May 10, 2018 00:25
This parameter is available for cc_library, and Bazel team has it on
their roadmap to add it to `cc_import` as well:
bazelbuild/bazel#4748

This change does potentially break existing `cc_import` rules that didn't specify it
previously.  However, that change seems worth it for being more explicit.
@judah judah requested a review from mrkkrp May 11, 2018 20:34
haskell/cc.bzl Outdated

return hdrs.to_list(), ["-I" + dir for dir in dirs]
return hdrs.to_list(), [f for flag in flags for f in ctx.tokenize(flag)]
Copy link
Member

Choose a reason for hiding this comment

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

ctx.tokenize does shell tokenization I guess? I could not find documentation about this: https://docs.bazel.build/versions/master/skylark/lib/ctx.html.

haskell/cc.bzl Outdated
dirs = set.to_list(set.from_list([hdr.dirname for hdr in hdrs]))
flags = set.to_list(set.from_list(
[f for dep in ctx.attr.deps if hasattr(dep, "cc")
for f in dep.cc.compile_flags]))
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure, maybe forwarding all compile flags of all dependencies at once is an overkill? May be we'll get something unnecessary or conflicting this way?

Copy link
Collaborator Author

@judah judah May 14, 2018

Choose a reason for hiding this comment

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

See the link in the PR description; in practice this field only actually covers CPP-related pragmas, so I think it provides the right necessary set of flags. (For what it's worth, this is the approach the Haskell rules developed internally at Google have taken, and it looks like it's been stable over the last couple of years.) I'm not aware of a more robust approach, at least until bazelbuild/bazel#2163 is completed.

ctx.tokenize is not officially documented but is defined here: https://github.com/bazelbuild/bazel/blob/abbb9002c41bbd53588e7249756aab236f6fcb4b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/SkylarkRuleContextApi.java#L290
I could also try seeing how robust it would be to reimplement it from scratch.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also note that the cc_library "defines" and "includes" fields already have strong warnings in its docs:
https://docs.bazel.build/versions/master/be/c-cpp.html
For example:
Unlike copts, these flags are added for the target and every rule that depends on it! Be very careful, since this may have far-reaching effects. When in doubt, add "-D" (or /D on Windows) flags to copts instead.
Which indicates that we shouldn't have to worry about conflicts.

Another option is to assemble the set of compile flags manually, basically replicating the logic in compile_flags. For example, in rules_go:
https://github.com/bazelbuild/rules_go/blob/master/go/private/rules/cgo.bzl#L187
Compare:
https://github.com/bazelbuild/bazel/blob/fa135cf600a957cbcef0ca45f97d5a9009d40859/src/main/java/com/google/devtools/build/lib/rules/cpp/CcSkylarkApiProvider.java#L175

@mrkkrp
Copy link
Member

mrkkrp commented May 13, 2018

Also add a strip_include_prefix attr to haskell_cc_import.

I don't see this in the diff though.

@judah
Copy link
Collaborator Author

judah commented May 14, 2018

Updated the PR; it was missing some changes I pushed to the wrong place.

@mboes mboes self-requested a review May 14, 2018 07:37
Copy link
Member

@mboes mboes left a comment

Choose a reason for hiding this comment

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

This LGTM. I trust that the breaking change in haskell_cc_import (need to use strip_include_prefix now) makes it consistent with the include path at which the cc_library rule (and in future cc_import) make header files available?

In of itself, I'm not sure I like that change. But I do like it a lot if it's to be consistent with core rules.

Rather than calling compile_flags plus `ctx.tokenize`, call
`cc.include_directories`, `cc.defines`, etc. directly.
Follow the behavior of `cc_library` more closely; allow either
a relative path (relative to the package) or an absolute path
(relative to the workspace root).
@judah
Copy link
Collaborator Author

judah commented May 14, 2018

I updated the implementation; please take another look:

@mboes mboes merged commit 896ae55 into master May 14, 2018
@mboes
Copy link
Member

mboes commented May 14, 2018

Looks great!

@mboes mboes deleted the includes branch May 14, 2018 20:02
judah added a commit to FormationAI/rules_haskell that referenced this pull request May 15, 2018
`-include` is used by Cabal (or build systems that emulate it, like Hazel)
to specify macros like `MIN_VERSION_base(...)`.

As of tweag#241 we're passing arguments around include directories via `optP`.
Since a manual `compiler_flag` call might also specify `-optP`, and need
to reference one of those header files, we should pass `compiler_flags`
*after* passing the include directories.
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.

3 participants