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
|
- `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.
|
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.
|
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
|
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
|
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
|
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
|
python scripts that needs to load other python modules, `PYTHONPATH` may need
|
||||||
to be modified using `meson.add_devenv()`.
|
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
|
of `PATH` which allows running Windows executables using wine. Note that since
|
||||||
`WINEPATH` size is currently limited to 1024 characters, paths relative to the
|
`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
|
root of build directory are used. That means current workdir must be the root of
|
||||||
build directory when running wine.
|
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 }}
|
{{ 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')
|
help='Path to build directory')
|
||||||
parser.add_argument('--workdir', '-w', type=Path, default=None,
|
parser.add_argument('--workdir', '-w', type=Path, default=None,
|
||||||
help='Directory to cd into before running (default: builddir, Since 1.0.0)')
|
help='Directory to cd into before running (default: builddir, Since 1.0.0)')
|
||||||
parser.add_argument('--dump', action='store_true',
|
parser.add_argument('--dump', nargs='?', const=True,
|
||||||
help='Only print required environment (Since 0.62.0)')
|
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',
|
parser.add_argument('devcmd', nargs=argparse.REMAINDER, metavar='command',
|
||||||
help='Command to run in developer environment (default: interactive shell)')
|
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(';'))
|
env['WINEPATH'] = get_wine_shortpath([winecmd], winepath.split(';'))
|
||||||
mlog.log('Meson detected wine and has set WINEPATH accordingly')
|
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 = build.EnvironmentVariables()
|
||||||
extra_env.set('MESON_DEVENV', ['1'])
|
extra_env.set('MESON_DEVENV', ['1'])
|
||||||
extra_env.set('MESON_PROJECT_NAME', [b.project_name])
|
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:
|
if sysroot:
|
||||||
extra_env.set('QEMU_LD_PREFIX', [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()
|
varnames = set()
|
||||||
for i in itertools.chain(b.devenv, {extra_env}):
|
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()
|
varnames |= i.get_names()
|
||||||
|
|
||||||
reduce_winepath(env)
|
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)),
|
mlog.log(' - Change current workdir to', mlog.bold(str(rel_path.parent)),
|
||||||
'or use', mlog.bold(f'--init-command {rel_path}'))
|
'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:
|
def run(options: argparse.Namespace) -> int:
|
||||||
privatedir = Path(options.builddir) / 'meson-private'
|
privatedir = Path(options.builddir) / 'meson-private'
|
||||||
buildfile = privatedir / 'build.dat'
|
buildfile = privatedir / 'build.dat'
|
||||||
|
@ -146,13 +157,16 @@ def run(options: argparse.Namespace) -> int:
|
||||||
b = build.load(options.builddir)
|
b = build.load(options.builddir)
|
||||||
workdir = options.workdir or 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.dump:
|
||||||
if options.devcmd:
|
if options.devcmd:
|
||||||
raise MesonException('--dump option does not allow running other command.')
|
raise MesonException('--dump option does not allow running other command.')
|
||||||
for name in varnames:
|
if options.dump is True:
|
||||||
print(f'{name}="{devenv[name]}"')
|
dump(devenv, varnames, dump_fmt)
|
||||||
print(f'export {name}')
|
else:
|
||||||
|
with open(options.dump, "w", encoding='utf-8') as output:
|
||||||
|
dump(devenv, varnames, dump_fmt, output)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
if b.environment.need_exe_wrapper():
|
if b.environment.need_exe_wrapper():
|
||||||
|
|
|
@ -135,10 +135,10 @@ class EnvironmentVariables(HoldableObject):
|
||||||
curr = env.get(name, default_value)
|
curr = env.get(name, default_value)
|
||||||
return separator.join(values if curr is None else values + [curr])
|
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()
|
env = full_env.copy()
|
||||||
for method, name, values, separator in self.envvars:
|
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)
|
env[name] = method(env, name, values, separator, default_value)
|
||||||
return env
|
return env
|
||||||
|
|
||||||
|
|
|
@ -15,3 +15,8 @@ meson.add_devenv(env)
|
||||||
# This exe links on a library built in another directory. On Windows this means
|
# 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.
|
# PATH must contain builddir/subprojects/sub to be able to run it.
|
||||||
executable('app', 'main.c', dependencies: foo_dep, install: true)
|
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['MESON_PROJECT_NAME'] == 'devenv'
|
||||||
assert os.environ['TEST_A'] == '1'
|
assert os.environ['TEST_A'] == '1'
|
||||||
assert os.environ['TEST_B'] == '0+1+2+3+4'
|
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._run(cmd + python_command + [script])
|
||||||
self.assertEqual('This is text.', self._run(cmd + [app]).strip())
|
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):
|
def test_clang_format_check(self):
|
||||||
if self.backend is not Backend.ninja:
|
if self.backend is not Backend.ninja:
|
||||||
raise SkipTest(f'Skipping clang-format tests with {self.backend.name} backend')
|
raise SkipTest(f'Skipping clang-format tests with {self.backend.name} backend')
|
||||||
|
|
Loading…
Reference in New Issue