From 3253e7bd254b97af35ba66379cd181de973e61f9 Mon Sep 17 00:00:00 2001 From: Joey Vagedes Date: Mon, 21 Aug 2023 14:40:23 -0700 Subject: [PATCH] instanced_inf_table: Account for non-existing library instance Due to platforms performing complex includes in their DSCs, There is a scenario in which a library instance references a library class that does not exist. This is not an error as the library class instance may not be consumed by a component in the platform, so the missing dependency is acceptable. This commit adds the ability to handle this scenario, and will not raise an error for a missing library instance. --- edk2toollib/database/tables/instanced_inf_table.py | 9 +++++++-- tests.unit/database/test_instanced_inf_table.py | 8 ++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/edk2toollib/database/tables/instanced_inf_table.py b/edk2toollib/database/tables/instanced_inf_table.py index 14f8fe3a..1e759969 100644 --- a/edk2toollib/database/tables/instanced_inf_table.py +++ b/edk2toollib/database/tables/instanced_inf_table.py @@ -119,6 +119,9 @@ def _parse_inf_recursively( Will immediately return if the INF has already been visited. """ + if inf is None: + return [] + logging.debug(f" Parsing Library: [{inf}]") visited.append(inf) library_instances = [] @@ -140,6 +143,8 @@ def _parse_inf_recursively( for null_lib in override_dict["NULL"]: library_instances.append(null_lib) + library_instances = list(filter(lambda lib: lib is not None, library_instances)) + # Time to visit in libraries that we have not visited yet. to_return = [] for library in filter(lambda lib: lib not in visited, library_instances): @@ -216,8 +221,8 @@ def _lib_to_instance(self, library_class_name, scope, library_dict, override_dic logging.debug(f'scoped library contents: {library_dict}') logging.debug(f'override dictionary: {override_dict}') e = f'Cannot find library class [{library_class_name}] for scope [{scope}] when evaluating {self.dsc}' - logging.error(e) - raise RuntimeError(e) + logging.warn(e) + return None def _reduce_lib_instances(self, module: str, library_instance_list: list[str]) -> str: """For a DSC, multiple library instances for the same library class can exist. diff --git a/tests.unit/database/test_instanced_inf_table.py b/tests.unit/database/test_instanced_inf_table.py index 4f91b0e5..4f486bc9 100644 --- a/tests.unit/database/test_instanced_inf_table.py +++ b/tests.unit/database/test_instanced_inf_table.py @@ -209,7 +209,7 @@ def test_scoped_libraries2(empty_tree: Tree): if "COMPONENT" not in row: assert row["NAME"].replace("Driver", "Lib") in row["LIBRARIES_USED"][0] -def test_missing_library(empty_tree: Tree): +def test_missing_library(empty_tree: Tree, caplog): """Test when a library is missing.""" edk2path = Edk2Path(str(empty_tree.ws), []) db = Edk2DB(Edk2DB.MEM_RW, pathobj=edk2path) @@ -227,9 +227,13 @@ def test_missing_library(empty_tree: Tree): "TARGET_ARCH": "IA32 X64", "TARGET": "DEBUG", }) - with pytest.raises(RuntimeError): + + with caplog.at_level(logging.WARNING): inf_table.parse(db) + assert len(caplog.records) == 1 + assert 'testcls' in caplog.records[0].message + def test_skip_library_with_unsupported_module_type(empty_tree: Tree): """Library class INFs can specify what module types they support.