diff --git a/edk2toollib/database/tables/instanced_inf_table.py b/edk2toollib/database/tables/instanced_inf_table.py index 2752a9d6e..d7cfca714 100644 --- a/edk2toollib/database/tables/instanced_inf_table.py +++ b/edk2toollib/database/tables/instanced_inf_table.py @@ -228,6 +228,10 @@ def _parse_inf_recursively( library_instance_list.append(null_lib) library_class_list.append("NULL") + for null_lib in self._get_null_lib_instances(inf, scope, library_dict): + library_instance_list.append(null_lib) + library_class_list.append("NULL") + # # 3. Recursively parse used libraries # @@ -355,3 +359,39 @@ def _reduce_lib_instances(self, module: str, library_instance_list: list[str]) - library_instance = self.pathobj.GetEdk2RelativePathFromAbsolutePath(library_instance) return library_instance return None + + def _get_null_lib_instances( + self, + inf: str, + scope: str, + library_dict: dict, + ) -> list: + """Returns all null libraries for a given scope. + + Args: + inf (str): The INF file to ignore null libraries for. + scope (str): The scope to search for null libraries. + library_dict (dict): The dictionary of libraries to search through. + + Returns: + list: A list of null libraries for the given scope. + """ + arch, module = tuple(scope.split(".")) + null_libs = [] + + lookup = f'{arch}.{module}.null' + null_libs.extend(library_dict.get(lookup, [])) + + lookup = f'common.{module}.null' + null_libs.extend(library_dict.get(lookup, [])) + + lookup = f'{arch}.null' + null_libs.extend(library_dict.get(lookup, [])) + + lookup = 'common.null' + null_libs.extend(library_dict.get(lookup, [])) + + if inf in null_libs: + null_libs.remove(inf) + + return null_libs diff --git a/tests.unit/database/test_instanced_inf_table.py b/tests.unit/database/test_instanced_inf_table.py index 3dd334104..4a5b460b7 100644 --- a/tests.unit/database/test_instanced_inf_table.py +++ b/tests.unit/database/test_instanced_inf_table.py @@ -410,3 +410,61 @@ def test_dsc_with_component_section_moduletype_definition(empty_tree: Tree, capl # Should not error db.parse(env) + +def test_dsc_with_null_lib_in_libraryclasses_section(empty_tree: Tree): + edk2path = Edk2Path(str(empty_tree.ws), []) + db = Edk2DB(empty_tree.ws / "db.db", pathobj=edk2path) + db.register(InstancedInfTable()) + + lib1 = empty_tree.create_library("TestLib", "TestCls") + nulllib1 = empty_tree.create_library("NullLib1", "NULL") + nulllib2 = empty_tree.create_library("NullLib2", "NULL") + nulllib3 = empty_tree.create_library("NullLib3", "NULL") + + comp1 = empty_tree.create_component("TestDriver", "PEIM", libraryclasses=["TestCls"]) + + dsc = empty_tree.create_dsc( + libraryclasses = [ + f'TestCls| {Path(lib1).as_posix()}', + f'NULL| {Path(nulllib1).as_posix()}', + ], + libraryclasses_x64 = [ + f'NULL| {Path(nulllib2).as_posix()}', + ], + libraryclasses_x64_DXE_DRIVER = [ + f'NULL| {Path(nulllib3).as_posix()}', + ], + components = [], + components_ia32_PEIM = [ + Path(comp1).as_posix(), + ], + components_x64 = [ + Path(comp1).as_posix(), + ] + ) + + env = { + "ACTIVE_PLATFORM": dsc, + "TARGET_ARCH": "IA32", + "TARGET": "DEBUG", + } + + db.parse(env) + + with db.session() as session: + component = session.query(InstancedInf).filter_by(cls = None).one() + assert len(component.libraries) == 2 + + db = Edk2DB(":memory:", pathobj=edk2path) + db.register(InstancedInfTable()) + env = { + "ACTIVE_PLATFORM": dsc, + "TARGET_ARCH": "X64", + "TARGET": "DEBUG", + } + + db.parse(env) + + with db.session() as session: + component = session.query(InstancedInf).filter_by(cls = None).one() + assert len(component.libraries) == 3