diff options
author | Eli Schwartz <eschwartz@archlinux.org> | 2021-10-03 14:35:30 -0400 |
---|---|---|
committer | Eli Schwartz <eschwartz@archlinux.org> | 2021-10-08 14:35:00 -0400 |
commit | 108bd996ee72b16c14f0ee0ca86959b142582394 (patch) | |
tree | 2cc138363c7139ce3fa2ae918e75ac5b81d19c77 /mesonbuild | |
parent | 54e17ad5975252242712dc3b613bdbd0a2504e23 (diff) | |
download | meson-108bd996ee72b16c14f0ee0ca86959b142582394.zip meson-108bd996ee72b16c14f0ee0ca86959b142582394.tar.gz meson-108bd996ee72b16c14f0ee0ca86959b142582394.tar.bz2 |
add install_emptydir function
This replaces the absolute hack of using
```
install_subdir('nonexisting', install_dir: 'share')
```
which requires you to make sure you don't accidentally or deliberately
have a completely different directory with the same name in your source
tree that is full of files you don't want installed. It also avoids
splitting the name in two and listing them in the wrong order.
You can also set the install mode of each directory component by listing
them one at a time in order, and in fact create nested structures at
all.
Fixes #1604
Properly fixes #2904
Diffstat (limited to 'mesonbuild')
-rw-r--r-- | mesonbuild/ast/interpreter.py | 1 | ||||
-rw-r--r-- | mesonbuild/backend/backends.py | 15 | ||||
-rw-r--r-- | mesonbuild/build.py | 14 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreter.py | 13 | ||||
-rw-r--r-- | mesonbuild/interpreter/interpreterobjects.py | 3 | ||||
-rw-r--r-- | mesonbuild/minstall.py | 18 |
6 files changed, 62 insertions, 2 deletions
diff --git a/mesonbuild/ast/interpreter.py b/mesonbuild/ast/interpreter.py index 7954b9b..ec93ff5 100644 --- a/mesonbuild/ast/interpreter.py +++ b/mesonbuild/ast/interpreter.py @@ -103,6 +103,7 @@ class AstInterpreter(InterpreterBase): 'install_man': self.func_do_nothing, 'install_data': self.func_do_nothing, 'install_subdir': self.func_do_nothing, + 'install_emptydir': self.func_do_nothing, 'configuration_data': self.func_do_nothing, 'configure_file': self.func_do_nothing, 'find_program': self.func_do_nothing, diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 6218156..3d8654e 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -120,6 +120,7 @@ class InstallData: self.targets: T.List[TargetInstallData] = [] self.headers: T.List[InstallDataBase] = [] self.man: T.List[InstallDataBase] = [] + self.emptydir: T.List[InstallEmptyDir] = [] self.data: T.List[InstallDataBase] = [] self.install_scripts: T.List[ExecutableSerialisation] = [] self.install_subdirs: T.List[SubdirInstallData] = [] @@ -147,6 +148,13 @@ class TargetInstallData: self.optional = optional self.tag = tag +class InstallEmptyDir: + def __init__(self, path: str, install_mode: 'FileMode', subproject: str, tag: T.Optional[str] = None): + self.path = path + self.install_mode = install_mode + self.subproject = subproject + self.tag = tag + class InstallDataBase: def __init__(self, path: str, install_path: str, install_path_name: str, install_mode: 'FileMode', subproject: str, tag: T.Optional[str] = None, @@ -1470,6 +1478,7 @@ class Backend: self.generate_target_install(d) self.generate_header_install(d) self.generate_man_install(d) + self.generate_emptydir_install(d) self.generate_data_install(d) self.generate_custom_install_script(d) self.generate_subdir_install(d) @@ -1665,6 +1674,12 @@ class Backend: i = InstallDataBase(srcabs, dstabs, dstname, m.get_custom_install_mode(), m.subproject, tag='man') d.man.append(i) + def generate_emptydir_install(self, d: InstallData) -> None: + emptydir: T.List[build.EmptyDir] = self.build.get_emptydir() + for e in emptydir: + i = InstallEmptyDir(e.path, e.install_mode, e.subproject, e.install_tag) + d.emptydir.append(i) + def generate_data_install(self, d: InstallData) -> None: data = self.build.get_data() srcdir = self.environment.get_source_dir() diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 311732e..ef2210e 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -187,6 +187,16 @@ class Man(HoldableObject): return self.sources +class EmptyDir(HoldableObject): + + def __init__(self, path: str, install_mode: 'FileMode', subproject: str, + install_tag: T.Optional[str] = None): + self.path = path + self.install_mode = install_mode + self.subproject = subproject + self.install_tag = install_tag + + class InstallDir(HoldableObject): def __init__(self, src_subdir: str, inst_subdir: str, install_dir: str, @@ -239,6 +249,7 @@ class Build: self.benchmarks: T.List['Test'] = [] self.headers: T.List[Headers] = [] self.man: T.List[Man] = [] + self.emptydir: T.List[EmptyDir] = [] self.data: T.List[Data] = [] self.static_linker: PerMachine[StaticLinker] = PerMachine(None, None) self.subprojects = {} @@ -316,6 +327,9 @@ class Build: def get_data(self) -> T.List['Data']: return self.data + def get_emptydir(self) -> T.List['EmptyDir']: + return self.emptydir + def get_install_subdirs(self) -> T.List['InstallDir']: return self.install_dirs diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index 9a89b0c..8ac92c8 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -349,6 +349,7 @@ class Interpreter(InterpreterBase, HoldableObject): 'install_data': self.func_install_data, 'install_headers': self.func_install_headers, 'install_man': self.func_install_man, + 'install_emptydir': self.func_install_emptydir, 'install_subdir': self.func_install_subdir, 'is_disabler': self.func_is_disabler, 'is_variable': self.func_is_variable, @@ -410,6 +411,7 @@ class Interpreter(InterpreterBase, HoldableObject): build.AliasTarget: OBJ.AliasTargetHolder, build.Headers: OBJ.HeadersHolder, build.Man: OBJ.ManHolder, + build.EmptyDir: OBJ.EmptyDirHolder, build.Data: OBJ.DataHolder, build.InstallDir: OBJ.InstallDirHolder, build.IncludeDirs: OBJ.IncludeDirsHolder, @@ -1896,6 +1898,17 @@ This will become a hard error in the future.''' % kwargs['input'], location=self return m + @FeatureNew('install_emptydir', '0.60.0') + @typed_kwargs( + 'install_emptydir', + INSTALL_MODE_KW + ) + def func_install_emptydir(self, node: mparser.BaseNode, args: T.Tuple[str], kwargs) -> None: + d = build.EmptyDir(args[0], kwargs['install_mode'], self.subproject) + self.build.emptydir.append(d) + + return d + @FeatureNewKwargs('subdir', '0.44.0', ['if_found']) @permittedKwargs({'if_found'}) @typed_pos_args('subdir', str) diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py index 072d2f0..b0447e6 100644 --- a/mesonbuild/interpreter/interpreterobjects.py +++ b/mesonbuild/interpreter/interpreterobjects.py @@ -646,6 +646,9 @@ class InstallDirHolder(ObjectHolder[build.InstallDir]): class ManHolder(ObjectHolder[build.Man]): pass +class EmptyDirHolder(ObjectHolder[build.EmptyDir]): + pass + class GeneratedObjectsHolder(ObjectHolder[build.ExtractedObjects]): pass diff --git a/mesonbuild/minstall.py b/mesonbuild/minstall.py index 6284f95..7864742 100644 --- a/mesonbuild/minstall.py +++ b/mesonbuild/minstall.py @@ -25,7 +25,7 @@ import sys import typing as T from . import environment -from .backend.backends import InstallData, InstallDataBase, TargetInstallData, ExecutableSerialisation +from .backend.backends import InstallData, InstallDataBase, InstallEmptyDir, TargetInstallData, ExecutableSerialisation from .coredata import major_versions_differ, MesonVersionMismatchException from .coredata import version as coredata_version from .mesonlib import Popen_safe, RealPathAction, is_windows @@ -370,7 +370,7 @@ class Installer: return run_exe(*args, **kwargs) return 0 - def should_install(self, d: T.Union[TargetInstallData, InstallDataBase, ExecutableSerialisation]) -> bool: + def should_install(self, d: T.Union[TargetInstallData, InstallEmptyDir, InstallDataBase, 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: @@ -531,6 +531,7 @@ class Installer: self.install_targets(d, dm, destdir, fullprefix) self.install_headers(d, dm, destdir, fullprefix) self.install_man(d, dm, destdir, fullprefix) + self.install_emptydir(d, dm, destdir, fullprefix) self.install_data(d, dm, destdir, fullprefix) self.restore_selinux_contexts(destdir) self.apply_ldconfig(destdir) @@ -581,6 +582,19 @@ class Installer: self.did_install_something = True self.set_mode(outfilename, m.install_mode, d.install_umask) + def install_emptydir(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: + for e in d.emptydir: + if not self.should_install(e): + continue + self.did_install_something = True + full_dst_dir = get_destdir_path(destdir, fullprefix, e.path) + self.log(f'Installing new directory {full_dst_dir}') + if os.path.isfile(full_dst_dir): + print(f'Tried to create directory {full_dst_dir} but a file of that name already exists.') + sys.exit(1) + dm.makedirs(full_dst_dir, exist_ok=True) + self.set_mode(full_dst_dir, e.install_mode, d.install_umask) + def install_headers(self, d: InstallData, dm: DirMaker, destdir: str, fullprefix: str) -> None: for t in d.headers: if not self.should_install(t): |