refactor: Compute compile flags once per target - #303
Conversation
furtib
left a comment
There was a problem hiding this comment.
If I understand correctly, you also outsourced the flag collection to a single function and call implementations on that too, fixing the flag mismatches.
But you also streamlined the very start of the collection so we only compute the flags once per target.
This means #272 will be superseded by this one.
I have one minor nit about looping over all SOURCE_ATTR labels; otherwise LGTM!
| compilation_deps = [] | ||
| for attr in SOURCE_ATTR: | ||
| if hasattr(ctx.rule.attr, attr): | ||
| deps = getattr(ctx.rule.attr, attr) | ||
| if type(deps) == "list": | ||
| for dep in deps: | ||
| if CcInfo in dep: | ||
| compilation_deps.append(dep) | ||
| deps_flags = [] | ||
| for dep in compilation_deps: | ||
| for flag in get_compile_flags(dep): | ||
| if flag not in deps_flags: | ||
| deps_flags.append(flag) | ||
| return deps_flags |
There was a problem hiding this comment.
Bazel already propagates flags for every SOURCE_ATTR type except implementation_deps (that's the point of implementation_deps). We don't need to loop over every attribute, only implementation_deps.
See my changes: https://github.com/Ericsson/rules_codechecker/pull/272/changes#diff-057ef75766b6e979efc7e1e8a4fc41ce228ae8465ee228e8d45c6d66983dcb94R147.
Something like this suggestion should work correctly:
| compilation_deps = [] | |
| for attr in SOURCE_ATTR: | |
| if hasattr(ctx.rule.attr, attr): | |
| deps = getattr(ctx.rule.attr, attr) | |
| if type(deps) == "list": | |
| for dep in deps: | |
| if CcInfo in dep: | |
| compilation_deps.append(dep) | |
| deps_flags = [] | |
| for dep in compilation_deps: | |
| for flag in get_compile_flags(dep): | |
| if flag not in deps_flags: | |
| deps_flags.append(flag) | |
| return deps_flags | |
| # implementation_deps intentionally does not propagate its includes | |
| # into the target's CcInfo.compilation_context, so we must extract | |
| # them explicitly. This may produce duplication. | |
| if not hasattr(ctx.rule.attr, "implementation_deps"): | |
| return [] | |
| impl_deps = getattr(ctx.rule.attr, "implementation_deps") | |
| if type(impl_deps) != "list": | |
| return [] | |
| deps_flags = [] | |
| for dep in impl_deps: | |
| if CcInfo not in dep: | |
| continue | |
| for flag in get_compile_flags(dep): | |
| if flag not in deps_flags: | |
| deps_flags.append(flag) | |
| return deps_flags |
There was a problem hiding this comment.
I think you are right, this "implementation_deps" is a strange thing.
To be honest I still dont understand how it works and what is the difference in dependencies.
I will take deeper look.
40405e5 to
e92ad81
Compare
6f0c04c to
c38e466
Compare
Why:
Dependency flags, copts and built-in include directories
were recomputed for every source file of a target,
and get_compile_flags mixed two concerns:
flags of the given CcInfo target and walking deps of ctx.rule.attr.
That made the handling of implementation_deps hard to follow.
What:
local_defines and deduplication
Addresses:
#304, #305, #306, #307