Add support for C dependencies with alwayslink=1#1879
Conversation
This is done via an aspect that walks the C deps graph and builds a dict between files and alwayslink properties, which is then used when building the link command line. Also, the command line is OS dependant, so add support for that too. Signed-off-by: Steeve Morin <steeve@zen.ly>
| _CgoInfo = provider() | ||
| _CcAlwaysLinkInfo = provider() | ||
|
|
||
| _WHOLE_ARCHIVE_FLAGS_BY_GOOS = { |
There was a problem hiding this comment.
I don't think the {} + {} operator is supported anymore in Starlark. If it is, it's deprecated.
I think it would be simpler to just define a function that returns the args though.
There was a problem hiding this comment.
I just tested on Bazel 0.21 and it worked without warning. Where did you see that?
There was a problem hiding this comment.
I don't think it will work with --all_incompatible_changes.
| } + { | ||
| "darwin": ("-Wl,-all_load", ""), | ||
| "js": ("", ""), | ||
| "windows": ("", ""), |
There was a problem hiding this comment.
Out of curiosity, why aren't the flags needed on Windows? Might be good to have a comment explaining it.
There was a problem hiding this comment.
They are needed, but I'm not sure what they are
There was a problem hiding this comment.
I meant depending on MSVC or MSYS
There was a problem hiding this comment.
cgo doesn't support MSVC, so don't worry about that. I think MSYS should accept gcc flags, but I don't know if there's a slightly different variant on Windows. Maybe just take out the case for Windows, and I can fix it later if it's a problem.
There was a problem hiding this comment.
alright i'll add windows to the list, then
| "windows": ("", ""), | ||
| } | ||
|
|
||
| def _always_link_aspect_impl(target, ctx): |
There was a problem hiding this comment.
An aspect will be too expensive for this. It gets applied not only to the cc_library we depend on through cdeps, but to everything it depends on, which could be a lot of things. Aspects consume a lot of time and memory, and I'd love to get rid of the ones we already have.
It's unfortunate that CcSkylarkApiProvider doesn't expose this information. Do you know if there's an open issue to add it? If not, maybe we can file one. It seems like a reasonable thing to add.
Until then, I think it would be reasonable to make -Wl,--whole-archive the default for all libraries. This would probably fix #1486 (looks like you've already seen that one).
There was a problem hiding this comment.
Is there a way to measure this? We build a pretty complex codebase and we didn't feel it was slow?
There was a problem hiding this comment.
You can build with --profile=file and then bazel analyze-profile file. It will tell you how much time Bazel spends in loading, analysis, execution, etc, but it won't say which lines of code cost the most. I don't think there's a way to do that yet.
cgo currently adds a huge amount of loading / analysis overhead because it declares cc_library rules for each configuration that could affect build files. That's separate from the cdeps libraries, but in any case, it's quite a bit slower than go build. An aspect would slow it further.
There was a problem hiding this comment.
I'm not sure using -Wl,--whole-archive would be the best way really, it may bloat the binaries significantly.
That said, if we could find a way to get the go.o file (generated prior to external linking), and use a normal cc_binary to link it against the rest (bypassing go link), we might get all the niceties for free.
There was a problem hiding this comment.
That may be possible, but it would interfere with tooling. bazel query would show your target as a cc_binary with a go_binary dependency. We have some hacks like this already (cgo), but Bazel API changes have made this less necessary.
Thanks for filing bazelbuild/bazel#7033. I think that's the right path forward. I'll comment there.
There was a problem hiding this comment.
Thanks for being so reactive.
For now we'll keep using this patch until a better solution arises.
Also, it provides at least a solution for people who are stuck.
|
Just to recap, Bazel 0.23.0 will introduce a new Starlark provider that will contain an I'll leave this PR open for now, but I may close it after there's a more concrete plan. |
|
Going back to this. Would you be open to bump the minimum bazel version to 0.23 ? |
|
It would remove this whole hack too: https://github.com/bazelbuild/rules_go/blob/master/go/private/rules/cgo.bzl#L239-L252 |
|
I'd rather not drop support for old Bazel versions, but I hope we won't have to anymore. rules_go now has a compatibility layer that can provide a consistent interface across Bazel API breaks. It's in go/private/compat. Maybe we can add something in there to retrieve this field on versions that support it. At the moment, I'm working on moving a lot of logic into the execution layer. Which means almost a complete rewrite of cgo. So let's not change anything here just yet. I'll likely ask you to take a look at that branch when it's passing CI here. You have a more complicated use case than most folks, and I want to make sure you're not broken by that change. |
|
So I take it you'll emit c artefacts from starlark and not via macro? That's great to hear! |
|
I'll try to rebase that PR and make use of the new field so that we can remove the aspect. That said, it won't work on earlier versions of bazel. |
That's right, we'll build an entire package in one action, including cgo code generation, C compilation, assembly, packing, coverage, and Go compilation. Big caveat though: it won't work for Objective C because Bazel doesn't expose the Objective C toolchain to Starlark rules. So we'll still follow the old path when |
|
That's amazing. For objc I think we can get pretty far with using -x objc to a cc_binary and aggregating deps as their are both compatible with each other. |
|
@jayconrod i just remembered there is https://docs.bazel.build/versions/master/skylark/lib/apple_common.html#new_objc_provider which could perhaps do the trick? |
|
I think |
|
I'm not sure, it sure looks to me it could be used to emit an |
|
(going back to this real quick) |
|
Also, obviously this PR will change massively related to the changes in |
|
Closing this, will reopen when the need arises. |
This is done via an aspect that walks the C deps graph and builds a
dict between files and alwayslink properties, which is then used when
building the link command line.
Also, the command line is OS dependant, so add support for that too.