diff options
Diffstat (limited to 'mesonbuild/minstall.py')
-rw-r--r-- | mesonbuild/minstall.py | 62 |
1 files changed, 45 insertions, 17 deletions
diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 7979fe6..60d533c 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -26,7 +26,10 @@ import sys import typing as T from . import environment -from .backend.backends import InstallData, InstallDataBase, InstallEmptyDir, TargetInstallData, ExecutableSerialisation +from .backend.backends import ( + InstallData, InstallDataBase, InstallEmptyDir, InstallSymlinkData, + TargetInstallData, ExecutableSerialisation +) from .coredata import major_versions_differ, MesonVersionMismatchException from .coredata import version as coredata_version from .mesonlib import Popen_safe, RealPathAction, is_windows @@ -317,6 +320,7 @@ class Installer: def __init__(self, options: 'ArgumentType', lf: T.TextIO): self.did_install_something = False + self.printed_symlink_error = False self.options = options self.lf = lf self.preserved_file_count = 0 @@ -394,7 +398,9 @@ class Installer: return run_exe(*args, **kwargs) return 0 - def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir, InstallDataBase, ExecutableSerialisation]) -> bool: + def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir, + InstallDataBase, InstallSymlinkData, + ExecutableSerialisation]) -> bool: if d.subproject and (d.subproject in self.skip_subprojects or '*' in self.skip_subprojects): return False if self.tags and d.tag not in self.tags: @@ -452,6 +458,29 @@ class Installer: append_to_log(self.lf, to_file) return True + def do_symlink(self, target: str, link: str, full_dst_dir: str) -> bool: + abs_target = target + if not os.path.isabs(target): + abs_target = os.path.join(full_dst_dir, target) + if not os.path.exists(abs_target): + raise RuntimeError(f'Tried to install symlink to missing file {abs_target}') + if os.path.exists(link): + if not os.path.islink(link): + raise RuntimeError(f'Destination {link!r} already exists and is not a symlink') + self.remove(link) + if not self.printed_symlink_error: + self.log(f'Installing symlink pointing to {target} to {link}') + try: + self.symlink(target, link, target_is_directory=os.path.isdir(abs_target)) + except (NotImplementedError, OSError): + if not self.printed_symlink_error: + print("Symlink creation does not work on this platform. " + "Skipping all symlinking.") + self.printed_symlink_error = True + return False + append_to_log(self.lf, link) + return True + def do_copydir(self, data: InstallData, src_dir: str, dst_dir: str, exclude: T.Optional[T.Tuple[T.Set[str], T.Set[str]]], install_mode: 'FileMode', dm: DirMaker) -> None: @@ -558,6 +587,7 @@ class Installer: self.install_man(d, dm, destdir, fullprefix) self.install_emptydir(d, dm, destdir, fullprefix) self.install_data(d, dm, destdir, fullprefix) + self.install_symlinks(d, dm, destdir, fullprefix) self.restore_selinux_contexts(destdir) self.apply_ldconfig(dm, destdir, libdir) self.run_install_script(d, destdir, fullprefix) @@ -596,6 +626,16 @@ class Installer: self.did_install_something = True self.set_mode(outfilename, i.install_mode, d.install_umask) + def install_symlinks(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for s in d.symlinks: + if not self.should_install(s): + continue + full_dst_dir = get_destdir_path(destdir, fullprefix, s.install_path) + full_link_name = get_destdir_path(destdir, fullprefix, s.name) + dm.makedirs(full_dst_dir, exist_ok=True) + if self.do_symlink(s.target, full_link_name, full_dst_dir): + self.did_install_something = True + def install_man(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: for m in d.man: if not self.should_install(m): @@ -712,21 +752,9 @@ class Installer: self.do_copydir(d, fname, outname, None, install_mode, dm) else: raise RuntimeError(f'Unknown file type for {fname!r}') - printed_symlink_error = False - for alias, to in aliases.items(): - try: - symlinkfilename = os.path.join(outdir, alias) - try: - self.remove(symlinkfilename) - except FileNotFoundError: - pass - self.symlink(to, symlinkfilename) - append_to_log(self.lf, symlinkfilename) - except (NotImplementedError, OSError): - if not printed_symlink_error: - print("Symlink creation does not work on this platform. " - "Skipping all symlinking.") - printed_symlink_error = True + for alias, target in aliases.items(): + symlinkfilename = os.path.join(outdir, alias) + self.do_symlink(target, symlinkfilename, outdir) if file_copied: self.did_install_something = True try: |