GN propagation of testonly variable problem when wrapping action() calls. |
||
Issue descriptionThis issue with GN appeared while working on Android-related changes to the Chromium build rules. It can be reproduced with the following simple CL: https://chromium-review.googlesource.com/c/chromium/src/+/1131740 Essentially, the 'testonly' variable doesn't seem to be propagated correctly through template calls that wraps an action. As an example, first consider the following: template("my_template") { forward_variables_from(invoker, ["testonly"]) ... action(first_target) { # This inherits the 'testonly' from the upper scope ... } action(second_target) { # This inherits 'testonly' from the upper scope too. ... } } Here's things occur as designed, the value of 'testonly' that was forwarded into the |my_template| scope is propagated to the actions. Now, let's write a template that wraps an action without doing anything else: template("action_wrapper") { action(target_name) { forward_variables_from(invoker, "*") } } My understanding of the GN language and rules is that calling action() or action_wrapper() should be equivalent for 'testonly'. But that's not the case: template("my_template") { forward_variables_from(invoker, ["testonly"]) ... action(first_target) { # This inherits the 'testonly' from the upper scope ... } action_wrapper(second_target) { # This DOES NOT inherit 'testonly' from the upper scope. ... } } In the code above, |second_target| will never have the testonly flag set to true, and any target that depends on it, that is testonly, will actually generate an error at GN time. This doesn't happen with a simple action() call. I've tried to look at the GN sources, the FillTestonly() method in tools/gen/target_generator.cc sets the 'testonly' flag associated with each target by calling Scope::GetValue(), which performs a recursive lookup (i.e. it is supposed to find the 'testonly' value defined in the |my_template| scope). We can work around by forwarding testonly explicitly, either with: action_wrapper(second_target) { testonly = defined(testonly) && testonly ... } Or: action_wrapper(second_target) { if (defined(testonly)) { testonly = testonly } ... } Also, note that the problem only arises when testonly is first forwarded in the outer template's scope, i.e. the following works correctly: template("my_template") { ... action(first_target) { # Inherit 'testonly' from the calling scope. forward_variables_from(invoker, ["testonly"]) ... } action_wrapper(second_target) { # This DOES inherit 'testonly' from the calling scope. forward_variables_from(invoker, ["testonly"]) ... } }
,
Jul 12
I've just stumbled upon https://bugs.chromium.org/p/chromium/issues/detail?id=594610 as well as a comment in https://cs.chromium.org/chromium/src/build/config/BUILDCONFIG.gn?q=BUILDCONFIG.gn&sq=package:chromium&g=0&l=703 It looks like the root of the issue is that forwarding all variables with "*" does not look in scopes recursively, but forwarding specific variables do. I.e. it looks like the issue can be solved by doing something like: template("action_wrapper") { action(target_name) { # Forward testonly explicitly, which performs a recursive scope lookup. forward_variables_from(invoker, [ "testonly" ]) # Forward all other variables, which does NOT! forward_variables_from(invoker, "*", [ "testonly" ]) } } I'll experiment with this and report here.
,
Jul 12
I confirm that this indeed works correctly, and is actually covered by the documentation for forward_variables_from(), which says: """ As a special case, if the variable_list is a string with the value of "*", all variables from the given scope will be copied. "*" only copies variables set directly on the from_scope, not enclosing ones. Otherwise it would duplicate all global variables. """ So I guess this is working as intended, though a little bit unintuitive, regarding the role of testonly and visibility during GN target dependency resolution. Making this as WontFix then. Sorry for the noise. I wonder if we don't want to make "*" forward 'testonly' and 'visibility' recursively by default though. I suspect there are many parts of the builds where these are not forwarded correctly :-/ |
||
►
Sign in to add a comment |
||
Comment 1 by agrieve@chromium.org
, Jul 10Labels: Build-Tools-GN