Skip to content

Commit

Permalink
cargo: Set CARGO_PKG_* in env when building and running build.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
xclaesse committed Nov 24, 2023
1 parent 08272e4 commit 7900636
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 13 deletions.
28 changes: 25 additions & 3 deletions mesonbuild/cargo/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -522,16 +522,37 @@ def _create_features(cargo: Manifest, build: builder.Builder) -> T.List[mparser.
def _create_cfg(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseNode]:
# Allow Cargo subprojects to add extra Rust args in meson/meson.build file.
# This is used to replace build.rs logic.

# cargo_info = {'CARGO_...': 'value', ...}
# extra_args = []
# extra_deps = []
# fs = import('fs')
# has_meson_build = fs.is_dir('meson')
# if has_meson_build
# subdir('meson')
# endif
# cfg = rust.cargo_cfg(features, skip_build_rs: has_meson_build)
# cfg = rust.cargo_cfg(features, skip_build_rs: has_meson_build, info: cargo_info)
version_arr = cargo.package.version.split('.')
version_arr += ['' * (4 - len(version_arr))]
return [
build.assign(build.dict({
# https://doc.rust-lang.org/cargo/reference/environment-variables.html
build.string('CARGO_MANIFEST_DIR'): build.string(os.path.join(cargo.subdir, cargo.path)),
build.string('CARGO_PKG_VERSION'): build.string(cargo.package.version),
build.string('CARGO_PKG_VERSION_MAJOR'): build.string(version_arr[0]),
build.string('CARGO_PKG_VERSION_MINOR'): build.string(version_arr[1]),
build.string('CARGO_PKG_VERSION_PATCH'): build.string(version_arr[2]),
build.string('CARGO_PKG_VERSION_PRE'): build.string(version_arr[3]),
build.string('CARGO_PKG_AUTHORS'): build.string(','.join(cargo.package.authors)),
build.string('CARGO_PKG_NAME'): build.string(cargo.package.name),
build.string('CARGO_PKG_DESCRIPTION'): build.string(cargo.package.description or ''),
build.string('CARGO_PKG_HOMEPAGE'): build.string(cargo.package.homepage or ''),
build.string('CARGO_PKG_REPOSITORY'): build.string(cargo.package.repository or ''),
build.string('CARGO_PKG_LICENSE'): build.string(cargo.package.license or ''),
build.string('CARGO_PKG_LICENSE_FILE'): build.string(cargo.package.license_file or ''),
build.string('CARGO_PKG_RUST_VERSION'): build.string(cargo.package.rust_version or ''),
build.string('CARGO_PKG_README'): build.string(cargo.package.readme or ''),
}),
'cargo_info'),
build.assign(build.array([]), _extra_args_varname()),
build.assign(build.array([]), _extra_deps_varname()),
build.assign(build.function('import', [build.string('fs')]), 'fs'),
Expand All @@ -543,7 +564,8 @@ def _create_cfg(cargo: Manifest, build: builder.Builder) -> T.List[mparser.BaseN
'cargo_cfg',
build.identifier('rust'),
[build.method('keys', build.identifier('features'))],
{'skip_build_rs': build.identifier('has_meson_build')},
{'skip_build_rs': build.identifier('has_meson_build'),
'info': build.identifier('cargo_info')},
),
'cfg'),
]
Expand Down
16 changes: 9 additions & 7 deletions mesonbuild/compilers/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -718,12 +718,12 @@ def has_header_symbol(self, hname: str, symbol: str, prefix: str,
def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *,
extra_args: T.Union[T.List[str], T.Callable[[CompileCheckMode], T.List[str]], None] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
run_env: T.Optional[T.Dict[str, str]] = None,
environ: T.Optional[T.Dict[str, str]] = None,
run_cwd: T.Optional[str] = None) -> RunResult:
need_exe_wrapper = env.need_exe_wrapper(self.for_machine)
if need_exe_wrapper and self.exe_wrapper is None:
raise CrossNoRunException('Can not run test applications in this cross environment.')
with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True) as p:
with self._build_wrapper(code, env, extra_args, dependencies, mode=CompileCheckMode.LINK, want_output=True, environ=environ) as p:
if p.returncode != 0:
mlog.debug(f'Could not compile test file {p.input_name}: {p.returncode}\n')
return RunResult(False)
Expand All @@ -732,7 +732,7 @@ def run(self, code: 'mesonlib.FileOrString', env: 'Environment', *,
else:
cmdlist = [p.output_name]
try:
pe, so, se = mesonlib.Popen_safe(cmdlist, env=run_env, cwd=run_cwd)
pe, so, se = mesonlib.Popen_safe(cmdlist, env=environ, cwd=run_cwd)
except Exception as e:
mlog.debug(f'Could not run: {cmdlist} (error: {e})\n')
return RunResult(False)
Expand Down Expand Up @@ -853,7 +853,8 @@ def compiler_args(self, args: T.Optional[T.Iterable[str]] = None) -> CompilerArg
def compile(self, code: 'mesonlib.FileOrString',
extra_args: T.Union[None, CompilerArgs, T.List[str]] = None,
*, mode: CompileCheckMode = CompileCheckMode.LINK, want_output: bool = False,
temp_dir: T.Optional[str] = None) -> T.Iterator[T.Optional[CompileResult]]:
temp_dir: T.Optional[str] = None,
environ: T.Optional[T.Dict[str, str]] = None) -> T.Iterator[T.Optional[CompileResult]]:
# TODO: there isn't really any reason for this to be a contextmanager

if mode == CompileCheckMode.PREPROCESS:
Expand Down Expand Up @@ -895,7 +896,7 @@ def compile(self, code: 'mesonlib.FileOrString',
mlog.debug('Running compile:')
mlog.debug('Working directory: ', tmpdirname)
mlog.debug('Code:\n', contents)
os_env = os.environ.copy()
os_env = environ.copy() if environ else os.environ.copy()
os_env['LC_ALL'] = 'C'
if no_ccache:
os_env['CCACHE_DISABLE'] = '1'
Expand Down Expand Up @@ -1339,15 +1340,16 @@ def _build_wrapper(self, code: 'mesonlib.FileOrString', env: 'Environment',
extra_args: T.Union[None, CompilerArgs, T.List[str], T.Callable[[CompileCheckMode], T.List[str]]] = None,
dependencies: T.Optional[T.List['Dependency']] = None,
mode: CompileCheckMode = CompileCheckMode.COMPILE, want_output: bool = False,
disable_cache: bool = False) -> T.Iterator[T.Optional[CompileResult]]:
disable_cache: bool = False,
environ: T.Optional[T.Dict[str, str]] = None) -> T.Iterator[T.Optional[CompileResult]]:
"""Helper for getting a cached value when possible.
This method isn't meant to be called externally, it's mean to be
wrapped by other methods like compiles() and links().
"""
args = self.build_wrapper_args(env, extra_args, dependencies, mode)
if disable_cache or want_output:
with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir) as r:
with self.compile(code, extra_args=args, mode=mode, want_output=want_output, temp_dir=env.scratch_dir, environ=environ) as r:
yield r
else:
with self.cached_compile(code, env.coredata, extra_args=args, mode=mode, temp_dir=env.scratch_dir) as r:
Expand Down
9 changes: 6 additions & 3 deletions mesonbuild/modules/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class FuncBindgen(TypedDict):

class FuncCargoCfg(TypedDict):
skip_build_rs: bool
info: T.Dict[str, str]


class RustModule(ExtensionModule):
Expand Down Expand Up @@ -326,7 +327,7 @@ def _split_cfg(cfg: str) -> T.Tuple[str, str]:
return pair[0], value

@staticmethod
def _get_build_rs_env(state: ModuleState, cfgs: T.Dict[str, str], features: T.List[str]) -> T.Dict[str, str]:
def _get_build_rs_env(state: ModuleState, cfgs: T.Dict[str, str], features: T.List[str], info: T.Dict[str, str]) -> T.Dict[str, str]:
# https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
env = os.environ.copy()
def conv(k: str) -> str:
Expand All @@ -341,6 +342,7 @@ def conv(k: str) -> str:
rustc_cmd = rustc.get_exelist(ccache=False)
env['RUSTC'] = rustc_cmd[0]
env['TARGET'] = rustc.get_target_triplet()
env.update(info)
return env

CARGO_CFG_PREFIX = 'cargo:rustc-cfg='
Expand All @@ -350,6 +352,7 @@ def conv(k: str) -> str:
@typed_kwargs(
'rust.cargo_cfg',
KwargInfo('skip_build_rs', bool, default=False),
KwargInfo('info', ContainerTypeInfo(dict, str), default={}),
)
def cargo_cfg(self, state: ModuleState, args: T.Tuple[T.List[str]], kwargs: FuncCargoCfg) -> T.Dict[str, str]:
cfgs = dict(self._split_cfg(i) for i in self._get_cfgs(state, MachineChoice.HOST))
Expand All @@ -360,9 +363,9 @@ def cargo_cfg(self, state: ModuleState, args: T.Tuple[T.List[str]], kwargs: Func
rustc = state.get_compiler('rust', MachineChoice.BUILD)
if not rustc:
raise InterpreterException(f'build.rs file requires rust language for build machine')
env = self._get_build_rs_env(state, cfgs, args[0])
env = self._get_build_rs_env(state, cfgs, args[0], kwargs['info'])
cwd = os.path.join(state.environment.source_dir, state.subdir)
res = rustc.run(build_rs_file, state.environment, run_env=env, run_cwd=cwd)
res = rustc.run(build_rs_file, state.environment, environ=env, run_cwd=cwd)
if res.returncode == 0:
compiler_args: T.List[str] = []
for line in res.stdout.splitlines():
Expand Down

0 comments on commit 7900636

Please sign in to comment.