custom_target: Add env kwarg
This commit is contained in:
parent
e4137ae3ec
commit
633264984b
|
@ -374,6 +374,10 @@ following.
|
||||||
- `install_mode` *(since 0.47.0)*: the file mode and optionally the
|
- `install_mode` *(since 0.47.0)*: the file mode and optionally the
|
||||||
owner/uid and group/gid
|
owner/uid and group/gid
|
||||||
- `output`: list of output files
|
- `output`: list of output files
|
||||||
|
- `env` *(since 0.57.0)*: environment variables to set, such as
|
||||||
|
`{'NAME1': 'value1', 'NAME2': 'value2'}` or `['NAME1=value1', 'NAME2=value2']`,
|
||||||
|
or an [`environment()` object](#environment-object) which allows more
|
||||||
|
sophisticated environment juggling.
|
||||||
|
|
||||||
The list of strings passed to the `command` keyword argument accept
|
The list of strings passed to the `command` keyword argument accept
|
||||||
the following special string substitutions:
|
the following special string substitutions:
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
## custom_target() now accepts `env` keyword argument
|
||||||
|
|
||||||
|
Environment variables can now be passed to `custom_target()` command.
|
||||||
|
|
||||||
|
```meson
|
||||||
|
env = environment()
|
||||||
|
env.append('PATH', '/foo')
|
||||||
|
custom_target(..., env: env)
|
||||||
|
custom_target(..., env: {'MY_ENV': 'value'})
|
||||||
|
custom_target(..., env: ['MY_ENV=value'])
|
||||||
|
```
|
|
@ -125,10 +125,10 @@ class TargetInstallData:
|
||||||
self.optional = optional
|
self.optional = optional
|
||||||
|
|
||||||
class ExecutableSerialisation:
|
class ExecutableSerialisation:
|
||||||
def __init__(self, cmd_args, env=None, exe_wrapper=None,
|
def __init__(self, cmd_args, env: T.Optional[build.EnvironmentVariables] = None, exe_wrapper=None,
|
||||||
workdir=None, extra_paths=None, capture=None) -> None:
|
workdir=None, extra_paths=None, capture=None) -> None:
|
||||||
self.cmd_args = cmd_args
|
self.cmd_args = cmd_args
|
||||||
self.env = env or {}
|
self.env = env
|
||||||
if exe_wrapper is not None:
|
if exe_wrapper is not None:
|
||||||
assert(isinstance(exe_wrapper, dependencies.ExternalProgram))
|
assert(isinstance(exe_wrapper, dependencies.ExternalProgram))
|
||||||
self.exe_runner = exe_wrapper
|
self.exe_runner = exe_wrapper
|
||||||
|
@ -378,7 +378,8 @@ class Backend:
|
||||||
return obj_list
|
return obj_list
|
||||||
|
|
||||||
def as_meson_exe_cmdline(self, tname, exe, cmd_args, workdir=None,
|
def as_meson_exe_cmdline(self, tname, exe, cmd_args, workdir=None,
|
||||||
extra_bdeps=None, capture=None, force_serialize=False):
|
extra_bdeps=None, capture=None, force_serialize=False,
|
||||||
|
env: T.Optional[build.EnvironmentVariables] = None):
|
||||||
'''
|
'''
|
||||||
Serialize an executable for running with a generator or a custom target
|
Serialize an executable for running with a generator or a custom target
|
||||||
'''
|
'''
|
||||||
|
@ -427,6 +428,9 @@ class Backend:
|
||||||
if any('\n' in c for c in cmd_args):
|
if any('\n' in c for c in cmd_args):
|
||||||
reasons.append('because command contains newlines')
|
reasons.append('because command contains newlines')
|
||||||
|
|
||||||
|
if env and env.varnames:
|
||||||
|
reasons.append('to set env')
|
||||||
|
|
||||||
force_serialize = force_serialize or bool(reasons)
|
force_serialize = force_serialize or bool(reasons)
|
||||||
|
|
||||||
if capture:
|
if capture:
|
||||||
|
@ -440,7 +444,6 @@ class Backend:
|
||||||
', '.join(reasons))
|
', '.join(reasons))
|
||||||
|
|
||||||
workdir = workdir or self.environment.get_build_dir()
|
workdir = workdir or self.environment.get_build_dir()
|
||||||
env = {}
|
|
||||||
if isinstance(exe, (dependencies.ExternalProgram,
|
if isinstance(exe, (dependencies.ExternalProgram,
|
||||||
build.BuildTarget, build.CustomTarget)):
|
build.BuildTarget, build.CustomTarget)):
|
||||||
basename = exe.name
|
basename = exe.name
|
||||||
|
@ -451,7 +454,7 @@ class Backend:
|
||||||
# Take a digest of the cmd args, env, workdir, and capture. This avoids
|
# Take a digest of the cmd args, env, workdir, and capture. This avoids
|
||||||
# collisions and also makes the name deterministic over regenerations
|
# collisions and also makes the name deterministic over regenerations
|
||||||
# which avoids a rebuild by Ninja because the cmdline stays the same.
|
# which avoids a rebuild by Ninja because the cmdline stays the same.
|
||||||
data = bytes(str(sorted(env.items())) + str(cmd_args) + str(workdir) + str(capture),
|
data = bytes(str(env) + str(cmd_args) + str(workdir) + str(capture),
|
||||||
encoding='utf-8')
|
encoding='utf-8')
|
||||||
digest = hashlib.sha1(data).hexdigest()
|
digest = hashlib.sha1(data).hexdigest()
|
||||||
scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, digest)
|
scratch_file = 'meson_exe_{0}_{1}.dat'.format(basename, digest)
|
||||||
|
|
|
@ -960,7 +960,8 @@ int dummy;
|
||||||
|
|
||||||
meson_exe_cmd, reason = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:],
|
meson_exe_cmd, reason = self.as_meson_exe_cmdline(target.name, target.command[0], cmd[1:],
|
||||||
extra_bdeps=target.get_transitive_build_target_deps(),
|
extra_bdeps=target.get_transitive_build_target_deps(),
|
||||||
capture=ofilenames[0] if target.capture else None)
|
capture=ofilenames[0] if target.capture else None,
|
||||||
|
env=target.env)
|
||||||
if meson_exe_cmd:
|
if meson_exe_cmd:
|
||||||
cmd = meson_exe_cmd
|
cmd = meson_exe_cmd
|
||||||
cmd_type = ' (wrapped by meson {})'.format(reason)
|
cmd_type = ' (wrapped by meson {})'.format(reason)
|
||||||
|
|
|
@ -576,7 +576,8 @@ class Vs2010Backend(backends.Backend):
|
||||||
workdir=tdir_abs,
|
workdir=tdir_abs,
|
||||||
extra_bdeps=extra_bdeps,
|
extra_bdeps=extra_bdeps,
|
||||||
capture=ofilenames[0] if target.capture else None,
|
capture=ofilenames[0] if target.capture else None,
|
||||||
force_serialize=True)
|
force_serialize=True,
|
||||||
|
env=target.env)
|
||||||
if target.build_always_stale:
|
if target.build_always_stale:
|
||||||
# Use a nonexistent file to always consider the target out-of-date.
|
# Use a nonexistent file to always consider the target out-of-date.
|
||||||
ofilenames += [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(),
|
ofilenames += [self.nonexistent_file(os.path.join(self.environment.get_scratch_dir(),
|
||||||
|
|
|
@ -2153,6 +2153,7 @@ class CustomTarget(Target):
|
||||||
'build_by_default',
|
'build_by_default',
|
||||||
'override_options',
|
'override_options',
|
||||||
'console',
|
'console',
|
||||||
|
'env',
|
||||||
])
|
])
|
||||||
|
|
||||||
def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False, backend=None):
|
def __init__(self, name, subdir, subproject, kwargs, absolute_paths=False, backend=None):
|
||||||
|
@ -2325,6 +2326,7 @@ class CustomTarget(Target):
|
||||||
else:
|
else:
|
||||||
mlog.debug(i)
|
mlog.debug(i)
|
||||||
raise InvalidArguments('Unknown type {!r} in depend_files.'.format(type(i).__name__))
|
raise InvalidArguments('Unknown type {!r} in depend_files.'.format(type(i).__name__))
|
||||||
|
self.env = kwargs.get('env')
|
||||||
|
|
||||||
def get_dependencies(self):
|
def get_dependencies(self):
|
||||||
return self.dependencies
|
return self.dependencies
|
||||||
|
|
|
@ -2315,7 +2315,8 @@ permitted_kwargs = {'add_global_arguments': {'language', 'native'},
|
||||||
'depfile',
|
'depfile',
|
||||||
'build_by_default',
|
'build_by_default',
|
||||||
'build_always_stale',
|
'build_always_stale',
|
||||||
'console'},
|
'console',
|
||||||
|
'env'},
|
||||||
'dependency': {'default_options',
|
'dependency': {'default_options',
|
||||||
'embed',
|
'embed',
|
||||||
'fallback',
|
'fallback',
|
||||||
|
@ -3997,6 +3998,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
||||||
raise SubdirDoneRequest()
|
raise SubdirDoneRequest()
|
||||||
|
|
||||||
@stringArgs
|
@stringArgs
|
||||||
|
@FeatureNewKwargs('custom_target', '0.57.0', ['env'])
|
||||||
@FeatureNewKwargs('custom_target', '0.48.0', ['console'])
|
@FeatureNewKwargs('custom_target', '0.48.0', ['console'])
|
||||||
@FeatureNewKwargs('custom_target', '0.47.0', ['install_mode', 'build_always_stale'])
|
@FeatureNewKwargs('custom_target', '0.47.0', ['install_mode', 'build_always_stale'])
|
||||||
@FeatureNewKwargs('custom_target', '0.40.0', ['build_by_default'])
|
@FeatureNewKwargs('custom_target', '0.40.0', ['build_by_default'])
|
||||||
|
@ -4018,6 +4020,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
||||||
except mesonlib.MesonException:
|
except mesonlib.MesonException:
|
||||||
mlog.warning('''Custom target input \'%s\' can\'t be converted to File object(s).
|
mlog.warning('''Custom target input \'%s\' can\'t be converted to File object(s).
|
||||||
This will become a hard error in the future.''' % kwargs['input'], location=self.current_node)
|
This will become a hard error in the future.''' % kwargs['input'], location=self.current_node)
|
||||||
|
kwargs['env'] = self.unpack_env_kwarg(kwargs)
|
||||||
tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, self.subproject, kwargs, backend=self.backend), self)
|
tg = CustomTargetHolder(build.CustomTarget(name, self.subdir, self.subproject, kwargs, backend=self.backend), self)
|
||||||
self.add_target(name, tg.held_object)
|
self.add_target(name, tg.held_object)
|
||||||
return tg
|
return tg
|
||||||
|
|
|
@ -39,7 +39,8 @@ def run_exe(exe: ExecutableSerialisation) -> int:
|
||||||
else:
|
else:
|
||||||
cmd_args = exe.cmd_args
|
cmd_args = exe.cmd_args
|
||||||
child_env = os.environ.copy()
|
child_env = os.environ.copy()
|
||||||
child_env.update(exe.env)
|
if exe.env:
|
||||||
|
child_env = exe.env.get_env(child_env)
|
||||||
if exe.extra_paths:
|
if exe.extra_paths:
|
||||||
child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) +
|
child_env['PATH'] = (os.pathsep.join(exe.extra_paths + ['']) +
|
||||||
child_env['PATH'])
|
child_env['PATH'])
|
||||||
|
|
|
@ -15,6 +15,7 @@ mytarget = custom_target('bindat',
|
||||||
output : 'data.dat',
|
output : 'data.dat',
|
||||||
input : 'data_source.txt',
|
input : 'data_source.txt',
|
||||||
command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless],
|
command : [python, comp, '--input=@INPUT@', '--output=@OUTPUT@', useless],
|
||||||
|
env: {'MY_COMPILER_ENV': 'value'},
|
||||||
install : true,
|
install : true,
|
||||||
install_dir : 'subdir'
|
install_dir : 'subdir'
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,6 +8,7 @@ assert(os.path.exists(sys.argv[3]))
|
||||||
args = sys.argv[:-1]
|
args = sys.argv[:-1]
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
assert os.environ['MY_COMPILER_ENV'] == 'value'
|
||||||
if len(args) != 3 or not args[1].startswith('--input') or \
|
if len(args) != 3 or not args[1].startswith('--input') or \
|
||||||
not args[2].startswith('--output'):
|
not args[2].startswith('--output'):
|
||||||
print(args[0], '--input=input_file --output=output_file')
|
print(args[0], '--input=input_file --output=output_file')
|
||||||
|
|
Loading…
Reference in New Issue