Skip to content

Commit

Permalink
ninja: Bundle target support
Browse files Browse the repository at this point in the history
  • Loading branch information
2xsaiko committed Jan 23, 2025
1 parent 8f27b2e commit 9b28e42
Showing 1 changed file with 111 additions and 3 deletions.
114 changes: 111 additions & 3 deletions mesonbuild/backend/ninjabackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .. import environment, mesonlib
from .. import build
from .. import mlog
from .. import nsbundle
from .. import compilers
from ..arglist import CompilerArgs
from ..compilers import Compiler
Expand Down Expand Up @@ -954,7 +955,11 @@ def generate_target(self, target) -> None:
self.generate_generator_list_rules(target)

# Generate rules for building the remaining source files in this target
outname = self.get_target_filename(target)
if isinstance(target, nsbundle.TargetBundle):
outname = os.path.join(self.get_target_private_dir(target), target.get_executable_name())
else:
outname = self.get_target_filename(target)

obj_list = []
is_unity = target.is_unity
header_deps = []
Expand Down Expand Up @@ -1103,6 +1108,9 @@ def generate_target(self, target) -> None:
elem = NinjaBuildElement(self.all_outputs, linker.get_archive_name(outname), 'AIX_LINKER', [outname])
self.add_build(elem)

if isinstance(target, nsbundle.TargetBundle):
self.generate_bundle_target(target, elem)

def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool:
if not self.ninja_has_dyndeps:
return False
Expand Down Expand Up @@ -1489,6 +1497,97 @@ def generate_jar_target(self, target: build.Jar) -> None:
# Create introspection information
self.create_target_source_introspection(target, compiler, compile_args, src_list, gen_src_list)

def generate_bundle_target(self, target: nsbundle.AnyBundleTarget, bin_elem: NinjaBuildElement) -> None:
bi: nsbundle.BundleInfo = target.get_bundle_info()

main_binary = bin_elem.outfilenames[0]
main_binary_dir, main_binary_fname = os.path.split(main_binary)
bundle_rel = self.get_target_filename(target)

presets_path = os.path.join(self.get_target_private_dir(target), 'Presets', 'Info.plist')
presets_fullpath = os.path.join(self.environment.get_build_dir(), presets_path)
os.makedirs(os.path.dirname(presets_fullpath), exist_ok=True)

with open(presets_fullpath, 'wb') as fp:
import plistlib

d = bi.get_configured_info_dict()
plistlib.dump(d, fp)

presets_file = File(True, *os.path.split(presets_path))

if bi.info_dict_file:
info_plist = self.generate_merge_plist(target, 'Info.plist', [presets_file, bi.info_dict_file])
else:
info_plist = presets_file

layout = build.StructuredSources()
layout.sources[str(bi.get_executable_folder_path())] += [File(True, main_binary_dir, main_binary_fname)]
layout.sources[str(bi.get_infoplist_path())] += [info_plist]

if bi.resources is not None:
for k, v in bi.resources.sources.items():
layout.sources[str(bi.get_unlocalized_resources_folder_path() / k)] += v

if bi.contents is not None:
for k, v in bi.contents.sources.items():
layout.sources[str(bi.get_contents_folder_path() / k)] += v

if bi.extra_binaries is not None:
for k, v in bi.extra_binaries.sources.items():
layout.sources[str(bi.get_executables_folder_path() / k)] += v

for file in layout.as_list():
if isinstance(file, GeneratedList):
self.generate_genlist_for_target(file, target)

elem = NinjaBuildElement(self.all_outputs, bundle_rel, 'phony', [])
elem.add_orderdep(self.__generate_sources_structure(Path(bundle_rel), layout, target=target)[0])

# Create links for versioned bundles (frameworks only)
def make_relative_link(src: PurePath, dst: PurePath):
src_rel = src.relative_to(dst.parent, walk_up=True)
dst_path = Path(bundle_rel) / dst
elem.add_orderdep(str(dst_path))
self._generate_symlink_target(str(src_rel), dst_path)

contents_dir = bi.get_contents_folder_path()

for path in bi.get_paths_to_link_contents():
can_link_whole_dir = True

for d in layout.sources.keys():
if PurePath(d).is_relative_to(path):
can_link_whole_dir = False
break

if can_link_whole_dir:
make_relative_link(contents_dir, path)
else:
names = set()

for d in layout.sources.keys():
d = PurePath(d)

if not d.parent.is_relative_to(contents_dir):
continue

d = d.relative_to(contents_dir).parts[0]
names.add(d)

for file in layout.sources[str(contents_dir)]:
if isinstance(file, File):
names.add(PurePath(file.fname).parts[0])
else:
names.update(file.get_outputs())

for n in names:
assert n != '.'

make_relative_link(contents_dir / n, path / n)

self.add_build(elem)

def generate_cs_resource_tasks(self, target) -> T.Tuple[T.List[str], T.List[str]]:
args = []
deps = []
Expand Down Expand Up @@ -1880,7 +1979,7 @@ def _generate_symlink_target(self, src: str, output: Path) -> None:
elem.add_item('TARGET', src)
self.add_build(elem)

def __generate_sources_structure(self, root: Path, structured_sources: build.StructuredSources) -> T.Tuple[T.List[str], T.Optional[str]]:
def __generate_sources_structure(self, root: Path, structured_sources: build.StructuredSources, target: T.Optional[build.Target] = None) -> T.Tuple[T.List[str], T.Optional[str]]:
first_file: T.Optional[str] = None
orderdeps: T.List[str] = []
for path, files in structured_sources.sources.items():
Expand All @@ -1892,10 +1991,18 @@ def __generate_sources_structure(self, root: Path, structured_sources: build.Str
if first_file is None:
first_file = str(out)
else:
if isinstance(file, GeneratedList):
if target is None:
raise MesonBugException('Encountered GeneratedList in StructuredSources with None target')

srcdir = Path(self.get_target_private_dir(target))
else:
srcdir = Path(file.subdir)

for f in file.get_outputs():
out = root / path / f
orderdeps.append(str(out))
self._generate_copy_target(str(Path(file.subdir) / f), out)
self._generate_copy_target(str(srcdir / f), out)
if first_file is None:
first_file = str(out)
return orderdeps, first_file
Expand Down Expand Up @@ -3830,6 +3937,7 @@ def generate_ending(self) -> None:
if self.environment.machines[t.for_machine].is_aix():
linker, stdlib_args = t.get_clink_dynamic_linker_and_stdlibs()
t.get_outputs()[0] = linker.get_archive_name(t.get_outputs()[0])

targetlist.append(os.path.join(self.get_target_dir(t), t.get_outputs()[0]))

elem = NinjaBuildElement(self.all_outputs, targ, 'phony', targetlist)
Expand Down

0 comments on commit 9b28e42

Please sign in to comment.