structured_sources: fix subdir handling

We currently don't handle subdirectories correctly in
structured_sources, which is problematic. To make this easier to handle
correctly, I've simply changed `structured_sources` to only use Files
and not strings as an implementation detail.
pull/10147/head
Dylan Baker 3 years ago
parent 7c20890a05
commit f9445300b3
  1. 8
      mesonbuild/backend/ninjabackend.py
  2. 14
      mesonbuild/build.py
  3. 6
      mesonbuild/interpreter/interpreter.py

@ -1669,9 +1669,7 @@ class NinjaBackend(backends.Backend):
root = Path(self.get_target_private_dir(target)) / 'structured'
for path, files in target.structured_sources.sources.items():
for file in files:
if isinstance(file, (str, File)):
if isinstance(file, str):
file = File.from_absolute_file(file)
if isinstance(file, File):
out = root / path / Path(file.fname).name
orderdeps.append(str(out))
self._generate_copy_target(file, out)
@ -1707,13 +1705,11 @@ class NinjaBackend(backends.Backend):
main_rust_file = None
if target.structured_sources:
if target.structured_sources.needs_copy(target):
if target.structured_sources.needs_copy():
_ods, main_rust_file = self.__generate_compile_structure(target)
orderdeps.extend(_ods)
else:
g = target.structured_sources.first_file()
if isinstance(g, str):
g = File.from_source_file(self.environment.source_dir, target.subdir, g)
if isinstance(g, File):
main_rust_file = g.rel_to_builddir(self.build_to_src)

@ -463,7 +463,7 @@ class StructuredSources(HoldableObject):
represent the required filesystem layout.
"""
sources: T.DefaultDict[str, T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList]]] = field(
sources: T.DefaultDict[str, T.List[T.Union[File, CustomTarget, CustomTargetIndex, GeneratedList]]] = field(
default_factory=lambda: defaultdict(list))
def __add__(self, other: StructuredSources) -> StructuredSources:
@ -475,30 +475,26 @@ class StructuredSources(HoldableObject):
def __bool__(self) -> bool:
return bool(self.sources)
def first_file(self) -> T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList]:
def first_file(self) -> T.Union[File, CustomTarget, CustomTargetIndex, GeneratedList]:
"""Get the first source in the root
:return: The first source in the root
"""
return self.sources[''][0]
def as_list(self) -> T.List[T.Union[str, File, CustomTarget, CustomTargetIndex, GeneratedList]]:
def as_list(self) -> T.List[T.Union[File, CustomTarget, CustomTargetIndex, GeneratedList]]:
return list(itertools.chain.from_iterable(self.sources.values()))
def needs_copy(self, target: BuildTarget) -> bool:
def needs_copy(self) -> bool:
"""Do we need to create a structure in the build directory.
This allows us to avoid making copies if the structures exists in the
source dir. Which could happen in situations where a generated source
only exists in some configurations
"""
p = pathlib.Path(target.subdir)
for files in self.sources.values():
for f in files:
if isinstance(f, str):
if not (target.environment.source_dir / p / f).exists():
return True
elif isinstance(f, File):
if isinstance(f, File):
if f.is_built:
return True
else:

@ -2122,11 +2122,13 @@ external dependencies (including libraries) must go to "dependencies".''')
args: T.Tuple[object, T.Optional[T.Dict[str, object]]],
kwargs: 'TYPE_kwargs') -> build.StructuredSources:
valid_types = (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)
sources: T.Dict[str, T.List[T.Union['mesonlib.FileOrString', 'build.GeneratedTypes']]] = collections.defaultdict(list)
sources: T.Dict[str, T.List[T.Union[mesonlib.File, 'build.GeneratedTypes']]] = collections.defaultdict(list)
for arg in mesonlib.listify(args[0]):
if not isinstance(arg, valid_types):
raise InvalidArguments(f'structured_sources: type "{type(arg)}" is not valid')
if isinstance(arg, str):
arg = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, arg)
sources[''].append(arg)
if args[1]:
if '' in args[1]:
@ -2135,6 +2137,8 @@ external dependencies (including libraries) must go to "dependencies".''')
for arg in mesonlib.listify(v):
if not isinstance(arg, valid_types):
raise InvalidArguments(f'structured_sources: type "{type(arg)}" is not valid')
if isinstance(arg, str):
arg = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, arg)
sources[k].append(arg)
return build.StructuredSources(sources)

Loading…
Cancel
Save