diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index 3a90eb8f6..6a271d781 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -934,6 +934,19 @@ def sdist(self, directory: Path) -> pathlib.Path: continue path = self._source_dir.joinpath(*member_parts[1:]) + if not path.exists() and member.isfile(): + # File doesn't exists on the source directory but exists on + # the Meson dist, so it is generated file, which we need to + # include. + # See https://mesonbuild.com/Reference-manual_builtin_meson.html#mesonadd_dist_script + + # MESON_DIST_ROOT could have a different base name + # than the actual sdist basename, so we need to rename here + file = meson_dist.extractfile(member.name) + member.name = str(pathlib.Path(dist_name, *member_parts[1:]).as_posix()) + tar.addfile(member, file) + continue + if not path.is_file(): continue diff --git a/tests/packages/generated-files/example-script.py b/tests/packages/generated-files/example-script.py new file mode 100755 index 000000000..6bcffbc40 --- /dev/null +++ b/tests/packages/generated-files/example-script.py @@ -0,0 +1,3 @@ +#!python + +print('hello!') diff --git a/tests/packages/generated-files/example.c b/tests/packages/generated-files/example.c new file mode 100644 index 000000000..bc24b30f9 --- /dev/null +++ b/tests/packages/generated-files/example.c @@ -0,0 +1,5 @@ +#include + +int main() { + printf("hello!"); +} diff --git a/tests/packages/generated-files/executable_module.py b/tests/packages/generated-files/executable_module.py new file mode 100755 index 000000000..894fc7e5e --- /dev/null +++ b/tests/packages/generated-files/executable_module.py @@ -0,0 +1,6 @@ +def foo(): + return 'bar' + + +if __name__ == '__main__': + print('foo?', foo()) diff --git a/tests/packages/generated-files/generate_version.py b/tests/packages/generated-files/generate_version.py new file mode 100644 index 000000000..dc056840c --- /dev/null +++ b/tests/packages/generated-files/generate_version.py @@ -0,0 +1,34 @@ +import argparse +import os + + +def write_version_info(path): + # A real project would call something to generate this + dummy_version = '1.0.0' + dummy_hash = '013j2fiejqea' + if os.environ.get('MESON_DIST_ROOT'): + path = os.path.join(os.environ.get('MESON_DIST_ROOT'), path) + with open(path, 'w') as file: + file.write(f'__version__="{dummy_version}"\n') + file.write( + f'__git_version__="{dummy_hash}"\n' + ) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '-o', '--outfile', type=str, help='Path to write version info to' + ) + args = parser.parse_args() + + if not args.outfile.endswith('.py'): + raise ValueError( + f'Output file must be a Python file. ' + f'Got: {args.outfile} as filename instead' + ) + + write_version_info(args.outfile) + + +main() diff --git a/tests/packages/generated-files/meson.build b/tests/packages/generated-files/meson.build new file mode 100644 index 000000000..f3c12777d --- /dev/null +++ b/tests/packages/generated-files/meson.build @@ -0,0 +1,39 @@ +project( + 'executable-bit', 'c', + version: '1.0.0', +) + +py_mod = import('python') +fs = import('fs') +py = py_mod.find_installation() + +executable( + 'example', 'example.c', + install: true, +) + +install_data( + 'example-script.py', + rename: 'example-script', + install_dir: get_option('bindir'), +) + +py.install_sources('executable_module.py') + +version_gen = files('generate_version.py') + +if fs.exists('_version_meson.py') + py.install_sources('_version_meson.py') +else + custom_target('write_version_file', + output: '_version_meson.py', + command: [ + py, version_gen, '-o', '@OUTPUT@' + ], + build_by_default: true, + build_always_stale: true, + install: true, + install_dir: py.get_install_dir(pure: false) + ) + meson.add_dist_script(py, version_gen, '-o', '_version_meson.py') +endif diff --git a/tests/packages/generated-files/pyproject.toml b/tests/packages/generated-files/pyproject.toml new file mode 100644 index 000000000..d6f3b6861 --- /dev/null +++ b/tests/packages/generated-files/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +build-backend = 'mesonpy' +requires = ['meson-python'] diff --git a/tests/test_sdist.py b/tests/test_sdist.py index 19dc82246..aea6e2ab7 100644 --- a/tests/test_sdist.py +++ b/tests/test_sdist.py @@ -103,3 +103,18 @@ def has_execbit(mode): # this ourselves) continue assert has_execbit(mode) == expected[name], f'Wrong mode for {name}: {mode}' + + +def test_generated_files(sdist_generated_files): + sdist = tarfile.open(sdist_generated_files, 'r:gz') + expected = { + 'executable_bit-1.0.0/PKG-INFO', + 'executable_bit-1.0.0/example-script.py', + 'executable_bit-1.0.0/example.c', + 'executable_bit-1.0.0/executable_module.py', + 'executable_bit-1.0.0/meson.build', + 'executable_bit-1.0.0/pyproject.toml', + 'executable_bit-1.0.0/_version_meson.py', + 'executable_bit-1.0.0/generate_version.py', + } + assert set(tar.name for tar in sdist.getmembers()) == expected