aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2023-01-13 16:42:09 -0500
committerEli Schwartz <eschwartz93@gmail.com>2023-01-18 11:06:48 -0500
commit1a0eff005483b63259e365bd4d51be7c4bd3b729 (patch)
tree7b64867bb7ac42f9a0b441e4c375b4113eeea47b
parent5a4168c410fea6fce8867ec60e0ba481d7c61866 (diff)
downloadmeson-1a0eff005483b63259e365bd4d51be7c4bd3b729.zip
meson-1a0eff005483b63259e365bd4d51be7c4bd3b729.tar.gz
meson-1a0eff005483b63259e365bd4d51be7c4bd3b729.tar.bz2
devenv: Allow dumping into file and select a format
It is often more useful to generate shell script than dumping to stdout. It is also important to be able to select the shell format. Formats currently implemented: - sh: Basic VAR=prepend_value:$VAR - export: Same as 'sh', but also export VAR - vscode: Same as 'sh', but without substitutions because they don't seems to work. To be used in launch.json's envFile.
-rw-r--r--docs/markdown/Commands.md17
-rw-r--r--docs/markdown/snippets/devenv.md11
-rw-r--r--mesonbuild/mdevenv.py32
-rw-r--r--mesonbuild/utils/core.py4
-rw-r--r--test cases/unit/90 devenv/meson.build5
-rwxr-xr-xtest cases/unit/90 devenv/test-devenv.py1
-rw-r--r--unittests/allplatformstests.py27
7 files changed, 83 insertions, 14 deletions
diff --git a/docs/markdown/Commands.md b/docs/markdown/Commands.md
index 4a00c4f..b7b72c4 100644
--- a/docs/markdown/Commands.md
+++ b/docs/markdown/Commands.md
@@ -348,20 +348,31 @@ These variables are set in environment in addition to those set using [[meson.ad
- `QEMU_LD_PREFIX` *Since 1.0.0* is set to the `sys_root` value from cross file
when cross compiling and that property is defined.
-Since *Since 0.62.0* if bash-completion scripts are being installed and the
+*Since 0.62.0* if bash-completion scripts are being installed and the
shell is bash, they will be automatically sourced.
-Since *Since 0.62.0* when GDB helper scripts (*-gdb.py, *-gdb.gdb, and *-gdb.csm)
+*Since 0.62.0* when GDB helper scripts (*-gdb.py, *-gdb.gdb, and *-gdb.csm)
are installed with a library name that matches one being built, Meson adds the
needed auto-load commands into `<builddir>/.gdbinit` file. When running gdb from
top build directory, that file is loaded by gdb automatically. In the case of
python scripts that needs to load other python modules, `PYTHONPATH` may need
to be modified using `meson.add_devenv()`.
-Since *Since 0.63.0* when cross compiling for Windows `WINEPATH` is used instead
+*Since 0.63.0* when cross compiling for Windows `WINEPATH` is used instead
of `PATH` which allows running Windows executables using wine. Note that since
`WINEPATH` size is currently limited to 1024 characters, paths relative to the
root of build directory are used. That means current workdir must be the root of
build directory when running wine.
+*Since 1.1.0* `meson devenv --dump [<filename>]` command takes an optional
+filename argument to write the environment into a file instead of printing to
+stdout.
+
+*Since 1.1.0* `--dump-format` argument has been added to select which shell
+format should be used. There are currently 3 formats supported:
+- `sh`: Lines are in the format `VAR=/prepend:$VAR:/append`.
+- `export`: Same as `sh` but with extra `export VAR` lines.
+- `vscode`: Same as `sh` but without `$VAR` substitution because they do not
+ seems to be properly supported by vscode.
+
{{ devenv_arguments.inc }}
diff --git a/docs/markdown/snippets/devenv.md b/docs/markdown/snippets/devenv.md
new file mode 100644
index 0000000..c2ce2ad
--- /dev/null
+++ b/docs/markdown/snippets/devenv.md
@@ -0,0 +1,11 @@
+## Dump devenv into file and select format
+
+`meson devenv --dump [<filename>]` command now takes an option filename argument
+to write the environment into a file instead of printing to stdout.
+
+A new `--dump-format` argument has been added to select which shell format
+should be used. There are currently 3 formats supported:
+- `sh`: Lines are in the format `VAR=/prepend:$VAR:/append`.
+- `export`: Same as `sh` but with extra `export VAR` lines.
+- `vscode`: Same as `sh` but without `$VAR` substitution because they do not
+ seems to be properly supported by vscode.
diff --git a/mesonbuild/mdevenv.py b/mesonbuild/mdevenv.py
index b25d73b..ddf53d9 100644
--- a/mesonbuild/mdevenv.py
+++ b/mesonbuild/mdevenv.py
@@ -21,8 +21,12 @@ def add_arguments(parser: argparse.ArgumentParser) -> None:
help='Path to build directory')
parser.add_argument('--workdir', '-w', type=Path, default=None,
help='Directory to cd into before running (default: builddir, Since 1.0.0)')
- parser.add_argument('--dump', action='store_true',
- help='Only print required environment (Since 0.62.0)')
+ parser.add_argument('--dump', nargs='?', const=True,
+ help='Only print required environment (Since 0.62.0) ' +
+ 'Takes an optional file path (Since 1.1.0)')
+ parser.add_argument('--dump-format', default='export',
+ choices=['sh', 'export', 'vscode'],
+ help='Format used with --dump (Since 1.1.0)')
parser.add_argument('devcmd', nargs=argparse.REMAINDER, metavar='command',
help='Command to run in developer environment (default: interactive shell)')
@@ -48,7 +52,7 @@ def reduce_winepath(env: T.Dict[str, str]) -> None:
env['WINEPATH'] = get_wine_shortpath([winecmd], winepath.split(';'))
mlog.log('Meson detected wine and has set WINEPATH accordingly')
-def get_env(b: build.Build, dump: bool) -> T.Tuple[T.Dict[str, str], T.Set[str]]:
+def get_env(b: build.Build, dump_fmt: T.Optional[str]) -> T.Tuple[T.Dict[str, str], T.Set[str]]:
extra_env = build.EnvironmentVariables()
extra_env.set('MESON_DEVENV', ['1'])
extra_env.set('MESON_PROJECT_NAME', [b.project_name])
@@ -57,10 +61,11 @@ def get_env(b: build.Build, dump: bool) -> T.Tuple[T.Dict[str, str], T.Set[str]]
if sysroot:
extra_env.set('QEMU_LD_PREFIX', [sysroot])
- env = {} if dump else os.environ.copy()
+ env = {} if dump_fmt else os.environ.copy()
+ default_fmt = '${0}' if dump_fmt in {'sh', 'export'} else None
varnames = set()
for i in itertools.chain(b.devenv, {extra_env}):
- env = i.get_env(env, dump)
+ env = i.get_env(env, default_fmt)
varnames |= i.get_names()
reduce_winepath(env)
@@ -138,6 +143,12 @@ def write_gdb_script(privatedir: Path, install_data: 'InstallData', workdir: Pat
mlog.log(' - Change current workdir to', mlog.bold(str(rel_path.parent)),
'or use', mlog.bold(f'--init-command {rel_path}'))
+def dump(devenv: T.Dict[str, str], varnames: T.Set[str], dump_format: T.Optional[str], output: T.Optional[T.TextIO] = None) -> None:
+ for name in varnames:
+ print(f'{name}="{devenv[name]}"', file=output)
+ if dump_format == 'export':
+ print(f'export {name}', file=output)
+
def run(options: argparse.Namespace) -> int:
privatedir = Path(options.builddir) / 'meson-private'
buildfile = privatedir / 'build.dat'
@@ -146,13 +157,16 @@ def run(options: argparse.Namespace) -> int:
b = build.load(options.builddir)
workdir = options.workdir or options.builddir
- devenv, varnames = get_env(b, options.dump)
+ dump_fmt = options.dump_format if options.dump else None
+ devenv, varnames = get_env(b, dump_fmt)
if options.dump:
if options.devcmd:
raise MesonException('--dump option does not allow running other command.')
- for name in varnames:
- print(f'{name}="{devenv[name]}"')
- print(f'export {name}')
+ if options.dump is True:
+ dump(devenv, varnames, dump_fmt)
+ else:
+ with open(options.dump, "w", encoding='utf-8') as output:
+ dump(devenv, varnames, dump_fmt, output)
return 0
if b.environment.need_exe_wrapper():
diff --git a/mesonbuild/utils/core.py b/mesonbuild/utils/core.py
index 310061a..b0c2b31 100644
--- a/mesonbuild/utils/core.py
+++ b/mesonbuild/utils/core.py
@@ -135,10 +135,10 @@ class EnvironmentVariables(HoldableObject):
curr = env.get(name, default_value)
return separator.join(values if curr is None else values + [curr])
- def get_env(self, full_env: EnvironOrDict, dump: bool = False) -> T.Dict[str, str]:
+ def get_env(self, full_env: EnvironOrDict, default_fmt: T.Optional[str] = None) -> T.Dict[str, str]:
env = full_env.copy()
for method, name, values, separator in self.envvars:
- default_value = f'${name}' if dump else None
+ default_value = default_fmt.format(name) if default_fmt else None
env[name] = method(env, name, values, separator, default_value)
return env
diff --git a/test cases/unit/90 devenv/meson.build b/test cases/unit/90 devenv/meson.build
index 3b0bb6a..72d8fdc 100644
--- a/test cases/unit/90 devenv/meson.build
+++ b/test cases/unit/90 devenv/meson.build
@@ -15,3 +15,8 @@ meson.add_devenv(env)
# This exe links on a library built in another directory. On Windows this means
# PATH must contain builddir/subprojects/sub to be able to run it.
executable('app', 'main.c', dependencies: foo_dep, install: true)
+
+env = environment({'TEST_C': ['/prefix']}, method: 'prepend')
+meson.add_devenv(env)
+env = environment({'TEST_C': ['/suffix']}, method: 'append')
+meson.add_devenv(env)
diff --git a/test cases/unit/90 devenv/test-devenv.py b/test cases/unit/90 devenv/test-devenv.py
index 75497ff..07bcf61 100755
--- a/test cases/unit/90 devenv/test-devenv.py
+++ b/test cases/unit/90 devenv/test-devenv.py
@@ -6,3 +6,4 @@ assert os.environ['MESON_DEVENV'] == '1'
assert os.environ['MESON_PROJECT_NAME'] == 'devenv'
assert os.environ['TEST_A'] == '1'
assert os.environ['TEST_B'] == '0+1+2+3+4'
+assert os.environ['TEST_C'] == os.pathsep.join(['/prefix', '/suffix'])
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 351f79d..a98cd94 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -3973,6 +3973,33 @@ class AllPlatformTests(BasePlatformTests):
self._run(cmd + python_command + [script])
self.assertEqual('This is text.', self._run(cmd + [app]).strip())
+ cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump']
+ o = self._run(cmd)
+ expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix'])
+ self.assertIn(f'TEST_C="{expected}"', o)
+ self.assertIn('export TEST_C', o)
+
+ cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', '--dump-format', 'sh']
+ o = self._run(cmd)
+ expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix'])
+ self.assertIn(f'TEST_C="{expected}"', o)
+ self.assertNotIn('export', o)
+
+ cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', '--dump-format', 'vscode']
+ o = self._run(cmd)
+ expected = os.pathsep.join(['/prefix', '/suffix'])
+ self.assertIn(f'TEST_C="{expected}"', o)
+ self.assertNotIn('export', o)
+
+ fname = os.path.join(self.builddir, 'dump.env')
+ cmd = self.meson_command + ['devenv', '-C', self.builddir, '--dump', fname]
+ o = self._run(cmd)
+ self.assertEqual(o, '')
+ o = Path(fname).read_text()
+ expected = os.pathsep.join(['/prefix', '$TEST_C', '/suffix'])
+ self.assertIn(f'TEST_C="{expected}"', o)
+ self.assertIn('export TEST_C', o)
+
def test_clang_format_check(self):
if self.backend is not Backend.ninja:
raise SkipTest(f'Skipping clang-format tests with {self.backend.name} backend')