diff options
36 files changed, 123 insertions, 11 deletions
diff --git a/docs/markdown/snippets/install_sources_preserve_path_arg.md b/docs/markdown/snippets/install_sources_preserve_path_arg.md new file mode 100644 index 0000000..0bc37f2 --- /dev/null +++ b/docs/markdown/snippets/install_sources_preserve_path_arg.md @@ -0,0 +1,8 @@ +## Added preserve_path arg to install_data + +The [[install_data]] function now has an optional argument `preserve_path` +that allows installing multi-directory data file structures that live +alongside source code with a single command. + +This is also available in the specialized `py_installation.install_sources` +method. diff --git a/docs/yaml/functions/install_data.yaml b/docs/yaml/functions/install_data.yaml index 3bb9802..191c612 100644 --- a/docs/yaml/functions/install_data.yaml +++ b/docs/yaml/functions/install_data.yaml @@ -43,6 +43,15 @@ kwargs: to install only a subset of the files. By default these files have no install tag which means they are not being installed when `--tags` argument is specified. + preserve_path: + type: bool + since: 0.64.0 + default: false + description: | + Disable stripping child-directories from data files when installing. + + This is equivalent to GNU Automake's `nobase` option. + rename: type: list[str] since: 0.46.0 diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index c2f0813..2f31815 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -79,6 +79,7 @@ from .type_checking import ( INSTALL_TAG_KW, LANGUAGE_KW, NATIVE_KW, + PRESERVE_PATH_KW, REQUIRED_KW, SOURCES_KW, VARIABLES_KW, @@ -2094,7 +2095,7 @@ class Interpreter(InterpreterBase, HoldableObject): @typed_pos_args('install_headers', varargs=(str, mesonlib.File)) @typed_kwargs( 'install_headers', - KwargInfo('preserve_path', bool, default=False, since='0.63.0'), + PRESERVE_PATH_KW, KwargInfo('subdir', (str, NoneType)), INSTALL_MODE_KW.evolve(since='0.47.0'), INSTALL_DIR_KW, @@ -2302,6 +2303,7 @@ class Interpreter(InterpreterBase, HoldableObject): INSTALL_MODE_KW.evolve(since='0.38.0'), INSTALL_TAG_KW.evolve(since='0.60.0'), INSTALL_DIR_KW, + PRESERVE_PATH_KW.evolve(since='0.64.0'), ) def func_install_data(self, node: mparser.BaseNode, args: T.Tuple[T.List['mesonlib.FileOrString']], @@ -2321,19 +2323,35 @@ class Interpreter(InterpreterBase, HoldableObject): else: install_dir_name = '{datadir}' return self.install_data_impl(sources, kwargs['install_dir'], kwargs['install_mode'], - rename, kwargs['install_tag'], install_dir_name) + rename, kwargs['install_tag'], install_dir_name, + preserve_path=kwargs['preserve_path']) def install_data_impl(self, sources: T.List[mesonlib.File], install_dir: T.Optional[str], install_mode: FileMode, rename: T.Optional[str], tag: T.Optional[str], install_dir_name: T.Optional[str] = None, - install_data_type: T.Optional[str] = None) -> build.Data: + install_data_type: T.Optional[str] = None, + preserve_path: bool = False) -> build.Data: """Just the implementation with no validation.""" - data = build.Data(sources, install_dir, install_dir_name or install_dir, install_mode, - self.subproject, rename, tag, install_data_type) - self.build.data.append(data) - return data + idir = install_dir or '' + idir_name = install_dir_name or idir + dirs = collections.defaultdict(list) + ret_data = [] + if preserve_path: + for file in sources: + dirname = os.path.dirname(file.fname) + dirs[dirname].append(file) + else: + dirs[''].extend(sources) + + for childdir, files in dirs.items(): + d = build.Data(files, os.path.join(idir, childdir), os.path.join(idir_name, childdir), + install_mode, self.subproject, rename, tag, install_data_type) + ret_data.append(d) + + self.build.data.extend(ret_data) + return ret_data @typed_pos_args('install_subdir', str) @typed_kwargs( diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py index e0ddb1b..09f734b 100644 --- a/mesonbuild/interpreter/type_checking.py +++ b/mesonbuild/interpreter/type_checking.py @@ -438,3 +438,5 @@ VARIABLES_KW: KwargInfo[T.Dict[str, str]] = KwargInfo( convertor=variables_convertor, default={}, ) + +PRESERVE_PATH_KW: KwargInfo[bool] = KwargInfo('preserve_path', bool, default=False, since='0.63.0') diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index 47dc674..5a6daa0 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -30,7 +30,7 @@ from ..dependencies.base import process_method_kw from ..dependencies.detect import get_dep_identifier from ..environment import detect_cpu_family from ..interpreter import ExternalProgramHolder, extract_required_kwarg, permitted_dependency_kwargs -from ..interpreter.type_checking import NoneType +from ..interpreter.type_checking import NoneType, PRESERVE_PATH_KW from ..interpreterbase import ( noPosargs, noKwargs, permittedKwargs, ContainerTypeInfo, InvalidArguments, typed_pos_args, typed_kwargs, KwargInfo, @@ -588,8 +588,13 @@ class PythonInstallation(ExternalProgramHolder): return dep @typed_pos_args('install_data', varargs=(str, mesonlib.File)) - @typed_kwargs('python_installation.install_sources', _PURE_KW, _SUBDIR_KW, - KwargInfo('install_tag', (str, NoneType), since='0.60.0')) + @typed_kwargs( + 'python_installation.install_sources', + _PURE_KW, + _SUBDIR_KW, + PRESERVE_PATH_KW, + KwargInfo('install_tag', (str, NoneType), since='0.60.0') + ) def install_sources_method(self, args: T.Tuple[T.List[T.Union[str, mesonlib.File]]], kwargs: 'PyInstallKw') -> 'Data': tag = kwargs['install_tag'] or 'runtime' @@ -597,7 +602,8 @@ class PythonInstallation(ExternalProgramHolder): self.interpreter.source_strings_to_files(args[0]), self._get_install_dir_impl(kwargs['pure'], kwargs['subdir']), mesonlib.FileMode(), rename=None, tag=tag, install_data_type='python', - install_dir_name=self._get_install_dir_name_impl(kwargs['pure'], kwargs['subdir'])) + install_dir_name=self._get_install_dir_name_impl(kwargs['pure'], kwargs['subdir']), + preserve_path=kwargs['preserve_path']) @noPosargs @typed_kwargs('python_installation.install_dir', _PURE_KW, _SUBDIR_KW) diff --git a/test cases/common/252 install data structured/dir1/bad b/test cases/common/252 install data structured/dir1/bad new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir1/bad diff --git a/test cases/common/252 install data structured/dir1/file1 b/test cases/common/252 install data structured/dir1/file1 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir1/file1 diff --git a/test cases/common/252 install data structured/dir1/file2 b/test cases/common/252 install data structured/dir1/file2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir1/file2 diff --git a/test cases/common/252 install data structured/dir1/file3 b/test cases/common/252 install data structured/dir1/file3 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir1/file3 diff --git a/test cases/common/252 install data structured/dir2/bad b/test cases/common/252 install data structured/dir2/bad new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir2/bad diff --git a/test cases/common/252 install data structured/dir2/file1 b/test cases/common/252 install data structured/dir2/file1 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir2/file1 diff --git a/test cases/common/252 install data structured/dir2/file2 b/test cases/common/252 install data structured/dir2/file2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir2/file2 diff --git a/test cases/common/252 install data structured/dir2/file3 b/test cases/common/252 install data structured/dir2/file3 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir2/file3 diff --git a/test cases/common/252 install data structured/dir3/bad b/test cases/common/252 install data structured/dir3/bad new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir3/bad diff --git a/test cases/common/252 install data structured/dir3/file1 b/test cases/common/252 install data structured/dir3/file1 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir3/file1 diff --git a/test cases/common/252 install data structured/dir3/file2 b/test cases/common/252 install data structured/dir3/file2 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir3/file2 diff --git a/test cases/common/252 install data structured/dir3/file3 b/test cases/common/252 install data structured/dir3/file3 new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/252 install data structured/dir3/file3 diff --git a/test cases/common/252 install data structured/meson.build b/test cases/common/252 install data structured/meson.build new file mode 100644 index 0000000..9d29794 --- /dev/null +++ b/test cases/common/252 install data structured/meson.build @@ -0,0 +1,16 @@ +project('install structured data') + +install_data( + 'dir1/file1', + 'dir1/file2', + 'dir1/file3', + 'dir2/file1', + 'dir2/file2', + 'dir2/file3', + 'dir3/file1', + 'dir3/file2', + 'dir3/file3', + install_dir: get_option('datadir'), + preserve_path: true, +) +subdir('pysrc') diff --git a/test cases/common/252 install data structured/pysrc/__init__.py b/test cases/common/252 install data structured/pysrc/__init__.py new file mode 100644 index 0000000..cb831ca --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/__init__.py @@ -0,0 +1 @@ +'''init for mod''' diff --git a/test cases/common/252 install data structured/pysrc/bad.py b/test cases/common/252 install data structured/pysrc/bad.py new file mode 100644 index 0000000..d2f862e --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/bad.py @@ -0,0 +1 @@ +'''mod.bad should not be installed''' diff --git a/test cases/common/252 install data structured/pysrc/bar.py b/test cases/common/252 install data structured/pysrc/bar.py new file mode 100644 index 0000000..1ac5d08 --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/bar.py @@ -0,0 +1 @@ +'''mod.bar module''' diff --git a/test cases/common/252 install data structured/pysrc/foo.py b/test cases/common/252 install data structured/pysrc/foo.py new file mode 100644 index 0000000..eff906b --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/foo.py @@ -0,0 +1 @@ +'''mod.foo module''' diff --git a/test cases/common/252 install data structured/pysrc/meson.build b/test cases/common/252 install data structured/pysrc/meson.build new file mode 100644 index 0000000..64c0f4d --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/meson.build @@ -0,0 +1,11 @@ +py_inst = import('python').find_installation() + +py_inst.install_sources( + '__init__.py', + 'foo.py', + 'bar.py', + 'submod/__init__.py', + 'submod/baz.py', + subdir: 'mod', + preserve_path: true, +) diff --git a/test cases/common/252 install data structured/pysrc/submod/__init__.py b/test cases/common/252 install data structured/pysrc/submod/__init__.py new file mode 100644 index 0000000..65a3500 --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/submod/__init__.py @@ -0,0 +1 @@ +'''init for submod''' diff --git a/test cases/common/252 install data structured/pysrc/submod/bad.py b/test cases/common/252 install data structured/pysrc/submod/bad.py new file mode 100644 index 0000000..6661a6d --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/submod/bad.py @@ -0,0 +1 @@ +'''mod.submod.bad should not be installed''' diff --git a/test cases/common/252 install data structured/pysrc/submod/baz.py b/test cases/common/252 install data structured/pysrc/submod/baz.py new file mode 100644 index 0000000..d0b2904 --- /dev/null +++ b/test cases/common/252 install data structured/pysrc/submod/baz.py @@ -0,0 +1 @@ +'''mod.submod.baz module''' diff --git a/test cases/common/252 install data structured/test.json b/test cases/common/252 install data structured/test.json new file mode 100644 index 0000000..f4dc2df --- /dev/null +++ b/test cases/common/252 install data structured/test.json @@ -0,0 +1,18 @@ +{ + "installed": [ + {"type": "python_file", "file": "usr/@PYTHON_PURELIB@/mod/__init__.py"}, + {"type": "python_file", "file": "usr/@PYTHON_PURELIB@/mod/foo.py"}, + {"type": "python_file", "file": "usr/@PYTHON_PURELIB@/mod/bar.py"}, + {"type": "python_file", "file": "usr/@PYTHON_PURELIB@/mod/submod/__init__.py"}, + {"type": "python_file", "file": "usr/@PYTHON_PURELIB@/mod/submod/baz.py"}, + {"type": "file", "file": "usr/share/dir1/file1"}, + {"type": "file", "file": "usr/share/dir1/file2"}, + {"type": "file", "file": "usr/share/dir1/file3"}, + {"type": "file", "file": "usr/share/dir2/file1"}, + {"type": "file", "file": "usr/share/dir2/file2"}, + {"type": "file", "file": "usr/share/dir2/file3"}, + {"type": "file", "file": "usr/share/dir3/file1"}, + {"type": "file", "file": "usr/share/dir3/file2"}, + {"type": "file", "file": "usr/share/dir3/file3"} + ] +} diff --git a/test cases/python/7 install path/meson.build b/test cases/python/7 install path/meson.build index 4a7df7e..5f0f7df 100644 --- a/test cases/python/7 install path/meson.build +++ b/test cases/python/7 install path/meson.build @@ -8,3 +8,5 @@ project('install path', py = import('python').find_installation() py.install_sources('test.py') py.install_sources('test.py', pure: false) + +subdir('structured') diff --git a/test cases/python/7 install path/structured/alpha/one.py b/test cases/python/7 install path/structured/alpha/one.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/python/7 install path/structured/alpha/one.py diff --git a/test cases/python/7 install path/structured/alpha/three.py b/test cases/python/7 install path/structured/alpha/three.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/python/7 install path/structured/alpha/three.py diff --git a/test cases/python/7 install path/structured/alpha/two.py b/test cases/python/7 install path/structured/alpha/two.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/python/7 install path/structured/alpha/two.py diff --git a/test cases/python/7 install path/structured/beta/one.py b/test cases/python/7 install path/structured/beta/one.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/python/7 install path/structured/beta/one.py diff --git a/test cases/python/7 install path/structured/meson.build b/test cases/python/7 install path/structured/meson.build new file mode 100644 index 0000000..6c85587 --- /dev/null +++ b/test cases/python/7 install path/structured/meson.build @@ -0,0 +1,9 @@ +py.install_sources( + 'one.py', + 'two.py', + 'alpha/one.py', + 'alpha/two.py', + 'alpha/three.py', + 'beta/one.py', + preserve_path: true, +) diff --git a/test cases/python/7 install path/structured/one.py b/test cases/python/7 install path/structured/one.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/python/7 install path/structured/one.py diff --git a/test cases/python/7 install path/structured/two.py b/test cases/python/7 install path/structured/two.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/python/7 install path/structured/two.py diff --git a/test cases/python/7 install path/test.json b/test cases/python/7 install path/test.json index f03ada8..9b05b66 100644 --- a/test cases/python/7 install path/test.json +++ b/test cases/python/7 install path/test.json @@ -1,5 +1,11 @@ { "installed": [ + {"type": "file", "file": "pure/one.py"}, + {"type": "file", "file": "pure/two.py"}, + {"type": "file", "file": "pure/alpha/one.py"}, + {"type": "file", "file": "pure/alpha/two.py"}, + {"type": "file", "file": "pure/alpha/three.py"}, + {"type": "file", "file": "pure/beta/one.py"}, {"type": "file", "file": "plat/test.py"}, {"type": "file", "file": "pure/test.py"} ] |