Loading core/product_config.rbc +61 −47 Original line number Diff line number Diff line Loading @@ -120,25 +120,19 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): globals, globals_base = _init_globals(input_variables_init) config_postfix = [] # Configs in postfix order # Each PCM is represented by a quadruple of function, config, children names # and readyness (that is, the configurations from inherited PCMs have been # substituted). configs = {top_pcm_name: (top_pcm, None, [], False)} # All known PCMs stash = [] # Configs to push once their descendants are done # Stack containing PCMs to be processed. An item in the stack # is a pair of PCMs name and its height in the product inheritance tree. pcm_stack = [(top_pcm_name, 0)] pcm_count = 0 # Stack containing PCMs to be processed pcm_stack = [top_pcm_name] # Run it until pcm_stack is exhausted, but no more than N times for n in range(1000): if not pcm_stack: break (name, height) = pcm_stack.pop() name = pcm_stack.pop() pcm, cfg, c, _ = configs[name] # cfg is set only after PCM has been called, leverage this Loading @@ -146,9 +140,6 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): if cfg != None: continue # Push ancestors until we reach this node's height config_postfix.extend([stash.pop() for i in range(len(stash) - height)]) # Run this one, obtaining its configuration and child PCMs. if _options.trace_modules: print("#%d: %s" % (n, name)) Loading @@ -175,34 +166,75 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): # Starlark dictionaries are guaranteed to iterate through in insertion order, # so children.keys() will be ordered by the inherit() calls configs[name] = (pcm, handle.cfg, children.keys(), False) pcm_count = pcm_count + 1 if len(children) == 0: # Leaf PCM goes straight to the config_postfix config_postfix.append(name) continue # Stash this PCM, process children in the sorted order stash.append(name) for child_name in sorted(children, reverse = True): if child_name not in configs: configs[child_name] = (children[child_name], None, [], False) pcm_stack.append((child_name, len(stash))) pcm_stack.append(child_name) if pcm_stack: fail("Inheritance processing took too many iterations") # Flush the stash config_postfix.extend([stash.pop() for i in range(len(stash))]) if len(config_postfix) != pcm_count: fail("Ran %d modules but postfix tree has only %d entries" % (pcm_count, len(config_postfix))) for pcm_name in globals.get("ARTIFACT_PATH_REQUIREMENT_PRODUCTS", []): for var, val in evaluate_finalized_product_variables(configs, pcm_name[:-3]).items(): globals["PRODUCTS."+pcm_name+"."+var] = val if _options.trace_modules: # Copy product config variables from the cfg dictionary to the # PRODUCTS.<top_level_makefile_name>.<var_name> global variables. for var, val in evaluate_finalized_product_variables(configs, top_pcm_name, _options.trace_modules).items(): globals["PRODUCTS."+top_pcm_name+".mk."+var] = val # Record inheritance hierarchy in PRODUCTS.<file>.INHERITS_FROM variables. # This is required for m product-graph. for config in configs: if len(configs[config][2]) > 0: globals["PRODUCTS."+config+".mk.INHERITS_FROM"] = sorted([x + ".mk" for x in configs[config][2]]) globals["PRODUCTS"] = __words(globals.get("PRODUCTS", [])) + [top_pcm_name + ".mk"] return (globals, globals_base) def evaluate_finalized_product_variables(configs, top_level_pcm_name, trace=False): configs_postfix = [] pcm_stack = [(top_level_pcm_name, True)] for i in range(1000): if not pcm_stack: break pcm_name, before = pcm_stack.pop() if before: pcm_stack.append((pcm_name, False)) for child in sorted(configs[pcm_name][2], reverse = True): pcm_stack.append((child, True)) else: configs_postfix.append(pcm_name) if pcm_stack: fail("Inheritance processing took too many iterations") # clone the configs, because in the process of evaluating the # final cfg dictionary we will remove values from the intermediate # cfg dictionaries. We need to be able to call evaluate_finalized_product_variables() # multiple times, so we can't change the origional configs object. cloned_configs = {} for pcm_name in configs: # skip unneeded pcms if pcm_name not in configs_postfix: continue pcm, cfg, children_names, ready = configs[pcm_name] cloned_cfg = {} for var, val in cfg.items(): if type(val) == 'list': cloned_cfg[var] = list(val) else: cloned_cfg[var] = val cloned_configs[pcm_name] = (pcm, cloned_cfg, children_names, ready) configs = cloned_configs if trace: print("\n#---Postfix---") for x in config_postfix: for x in configs_postfix: print("# ", x) # Traverse the tree from the bottom, evaluating inherited values for pcm_name in config_postfix: for pcm_name in configs_postfix: pcm, cfg, children_names, ready = configs[pcm_name] # Should run Loading @@ -221,25 +253,7 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): _substitute_inherited(configs, pcm_name, cfg) _percolate_inherited(configs, pcm_name, cfg, children_names) configs[pcm_name] = pcm, cfg, children_names, True if (pcm_name + ".mk") in globals.get("ARTIFACT_PATH_REQUIREMENT_PRODUCTS", []): for var, val in cfg.items(): globals["PRODUCTS."+pcm_name+".mk."+var] = val # Copy product config variables from the cfg dictionary to the # PRODUCTS.<top_level_makefile_name>.<var_name> global variables. for var, val in configs[top_pcm_name][1].items(): globals["PRODUCTS."+top_pcm_name+".mk."+var] = val # Record inheritance hierarchy in PRODUCTS.<file>.INHERITS_FROM variables. # This is required for m product-graph. for config in configs: if len(configs[config][2]) > 0: globals["PRODUCTS."+config+".mk.INHERITS_FROM"] = sorted([x + ".mk" for x in configs[config][2]]) globals["PRODUCTS"] = __words(globals.get("PRODUCTS", [])) + [top_pcm_name + ".mk"] return (globals, globals_base) return configs[top_level_pcm_name][1] def _dictionary_difference(a, b): result = {} Loading tests/artifact_path_requirements/inherit1.rbc 0 → 100644 +21 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") load(":inherit3.rbc", _inherit3_init = "init") def init(g, handle): cfg = rblf.cfg(handle) rblf.inherit(handle, "test/inherit3", _inherit3_init) tests/artifact_path_requirements/inherit2.rbc 0 → 100644 +22 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") load(":inherit4.rbc", _inherit4_init = "init") def init(g, handle): cfg = rblf.cfg(handle) rblf.inherit(handle, "test/inherit4", _inherit4_init) rblf.require_artifacts_in_path(handle, "vendor/", "") tests/artifact_path_requirements/inherit3.rbc 0 → 100644 +22 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") load(":inherit4.rbc", _inherit4_init = "init") def init(g, handle): cfg = rblf.cfg(handle) rblf.inherit(handle, "test/inherit4", _inherit4_init) rblf.require_artifacts_in_path(handle, "vendor/", "") tests/artifact_path_requirements/inherit4.rbc 0 → 100644 +21 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") def init(g, handle): cfg = rblf.cfg(handle) rblf.setdefault(handle, "PRODUCT_COPY_FILES") cfg["PRODUCT_COPY_FILES"] += ["foo/bar/baz.txt:vendor/etc/baz.txt"] Loading
core/product_config.rbc +61 −47 Original line number Diff line number Diff line Loading @@ -120,25 +120,19 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): globals, globals_base = _init_globals(input_variables_init) config_postfix = [] # Configs in postfix order # Each PCM is represented by a quadruple of function, config, children names # and readyness (that is, the configurations from inherited PCMs have been # substituted). configs = {top_pcm_name: (top_pcm, None, [], False)} # All known PCMs stash = [] # Configs to push once their descendants are done # Stack containing PCMs to be processed. An item in the stack # is a pair of PCMs name and its height in the product inheritance tree. pcm_stack = [(top_pcm_name, 0)] pcm_count = 0 # Stack containing PCMs to be processed pcm_stack = [top_pcm_name] # Run it until pcm_stack is exhausted, but no more than N times for n in range(1000): if not pcm_stack: break (name, height) = pcm_stack.pop() name = pcm_stack.pop() pcm, cfg, c, _ = configs[name] # cfg is set only after PCM has been called, leverage this Loading @@ -146,9 +140,6 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): if cfg != None: continue # Push ancestors until we reach this node's height config_postfix.extend([stash.pop() for i in range(len(stash) - height)]) # Run this one, obtaining its configuration and child PCMs. if _options.trace_modules: print("#%d: %s" % (n, name)) Loading @@ -175,34 +166,75 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): # Starlark dictionaries are guaranteed to iterate through in insertion order, # so children.keys() will be ordered by the inherit() calls configs[name] = (pcm, handle.cfg, children.keys(), False) pcm_count = pcm_count + 1 if len(children) == 0: # Leaf PCM goes straight to the config_postfix config_postfix.append(name) continue # Stash this PCM, process children in the sorted order stash.append(name) for child_name in sorted(children, reverse = True): if child_name not in configs: configs[child_name] = (children[child_name], None, [], False) pcm_stack.append((child_name, len(stash))) pcm_stack.append(child_name) if pcm_stack: fail("Inheritance processing took too many iterations") # Flush the stash config_postfix.extend([stash.pop() for i in range(len(stash))]) if len(config_postfix) != pcm_count: fail("Ran %d modules but postfix tree has only %d entries" % (pcm_count, len(config_postfix))) for pcm_name in globals.get("ARTIFACT_PATH_REQUIREMENT_PRODUCTS", []): for var, val in evaluate_finalized_product_variables(configs, pcm_name[:-3]).items(): globals["PRODUCTS."+pcm_name+"."+var] = val if _options.trace_modules: # Copy product config variables from the cfg dictionary to the # PRODUCTS.<top_level_makefile_name>.<var_name> global variables. for var, val in evaluate_finalized_product_variables(configs, top_pcm_name, _options.trace_modules).items(): globals["PRODUCTS."+top_pcm_name+".mk."+var] = val # Record inheritance hierarchy in PRODUCTS.<file>.INHERITS_FROM variables. # This is required for m product-graph. for config in configs: if len(configs[config][2]) > 0: globals["PRODUCTS."+config+".mk.INHERITS_FROM"] = sorted([x + ".mk" for x in configs[config][2]]) globals["PRODUCTS"] = __words(globals.get("PRODUCTS", [])) + [top_pcm_name + ".mk"] return (globals, globals_base) def evaluate_finalized_product_variables(configs, top_level_pcm_name, trace=False): configs_postfix = [] pcm_stack = [(top_level_pcm_name, True)] for i in range(1000): if not pcm_stack: break pcm_name, before = pcm_stack.pop() if before: pcm_stack.append((pcm_name, False)) for child in sorted(configs[pcm_name][2], reverse = True): pcm_stack.append((child, True)) else: configs_postfix.append(pcm_name) if pcm_stack: fail("Inheritance processing took too many iterations") # clone the configs, because in the process of evaluating the # final cfg dictionary we will remove values from the intermediate # cfg dictionaries. We need to be able to call evaluate_finalized_product_variables() # multiple times, so we can't change the origional configs object. cloned_configs = {} for pcm_name in configs: # skip unneeded pcms if pcm_name not in configs_postfix: continue pcm, cfg, children_names, ready = configs[pcm_name] cloned_cfg = {} for var, val in cfg.items(): if type(val) == 'list': cloned_cfg[var] = list(val) else: cloned_cfg[var] = val cloned_configs[pcm_name] = (pcm, cloned_cfg, children_names, ready) configs = cloned_configs if trace: print("\n#---Postfix---") for x in config_postfix: for x in configs_postfix: print("# ", x) # Traverse the tree from the bottom, evaluating inherited values for pcm_name in config_postfix: for pcm_name in configs_postfix: pcm, cfg, children_names, ready = configs[pcm_name] # Should run Loading @@ -221,25 +253,7 @@ def _product_configuration(top_pcm_name, top_pcm, input_variables_init): _substitute_inherited(configs, pcm_name, cfg) _percolate_inherited(configs, pcm_name, cfg, children_names) configs[pcm_name] = pcm, cfg, children_names, True if (pcm_name + ".mk") in globals.get("ARTIFACT_PATH_REQUIREMENT_PRODUCTS", []): for var, val in cfg.items(): globals["PRODUCTS."+pcm_name+".mk."+var] = val # Copy product config variables from the cfg dictionary to the # PRODUCTS.<top_level_makefile_name>.<var_name> global variables. for var, val in configs[top_pcm_name][1].items(): globals["PRODUCTS."+top_pcm_name+".mk."+var] = val # Record inheritance hierarchy in PRODUCTS.<file>.INHERITS_FROM variables. # This is required for m product-graph. for config in configs: if len(configs[config][2]) > 0: globals["PRODUCTS."+config+".mk.INHERITS_FROM"] = sorted([x + ".mk" for x in configs[config][2]]) globals["PRODUCTS"] = __words(globals.get("PRODUCTS", [])) + [top_pcm_name + ".mk"] return (globals, globals_base) return configs[top_level_pcm_name][1] def _dictionary_difference(a, b): result = {} Loading
tests/artifact_path_requirements/inherit1.rbc 0 → 100644 +21 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") load(":inherit3.rbc", _inherit3_init = "init") def init(g, handle): cfg = rblf.cfg(handle) rblf.inherit(handle, "test/inherit3", _inherit3_init)
tests/artifact_path_requirements/inherit2.rbc 0 → 100644 +22 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") load(":inherit4.rbc", _inherit4_init = "init") def init(g, handle): cfg = rblf.cfg(handle) rblf.inherit(handle, "test/inherit4", _inherit4_init) rblf.require_artifacts_in_path(handle, "vendor/", "")
tests/artifact_path_requirements/inherit3.rbc 0 → 100644 +22 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") load(":inherit4.rbc", _inherit4_init = "init") def init(g, handle): cfg = rblf.cfg(handle) rblf.inherit(handle, "test/inherit4", _inherit4_init) rblf.require_artifacts_in_path(handle, "vendor/", "")
tests/artifact_path_requirements/inherit4.rbc 0 → 100644 +21 −0 Original line number Diff line number Diff line # Copyright 2022 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. load("//build/make/core:product_config.rbc", "rblf") def init(g, handle): cfg = rblf.cfg(handle) rblf.setdefault(handle, "PRODUCT_COPY_FILES") cfg["PRODUCT_COPY_FILES"] += ["foo/bar/baz.txt:vendor/etc/baz.txt"]