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.
This commit is contained in:
parent
5a4168c410
commit
1a0eff0054
|
@ -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 }}
|
||||
|
|
|
@ -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.
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'])
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue