Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/markdown/Builtin-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@ or compiler being used:
| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use |
| rust_dynamic_std | false | true, false | Whether to link dynamically to the Rust standard library *(Added in 1.9.0)* |
| rust_nightly | auto | enabled, disabled, auto | Nightly Rust compiler (enabled=required, disabled=don't use nightly feature, auto=use nightly feature if available) *(Added in 1.10.0)* |
| cuda_ccbindir | | filesystem path | CUDA non-default toolchain directory to use (-ccbin) *(Added in 0.57.1)* |

The default values of `c_winlibs` and `cpp_winlibs` are in
Expand Down
52 changes: 52 additions & 0 deletions mesonbuild/cargo/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def _create_package(self, pkg: PackageState, build: builder.Builder, subdir: str
]
ast += self._create_dependencies(pkg, build)
ast += self._create_meson_subdir(build)
ast += self._create_env_args(pkg, build, subdir)

if pkg.manifest.lib:
crate_type = pkg.manifest.lib.crate_type
Expand Down Expand Up @@ -596,6 +597,56 @@ def _create_meson_subdir(self, build: builder.Builder) -> T.List[mparser.BaseNod
build.block([build.function('subdir', [build.string('meson')])]))
]

def _pkg_common_env(self, pkg: PackageState, subdir: str) -> T.Dict[str, str]:
# Common variables for build.rs and crates
# https://doc.rust-lang.org/cargo/reference/environment-variables.html
# OUT_DIR is the directory where build.rs generate files. In our case,
# it's the directory where meson/meson.build places generated files.
out_dir = os.path.join(self.environment.build_dir, subdir, 'meson')
os.makedirs(out_dir, exist_ok=True)
version_arr = pkg.manifest.package.version.split('.')
version_arr += ['' * (4 - len(version_arr))]
return {
'OUT_DIR': out_dir,
'CARGO_MANIFEST_DIR': os.path.join(self.environment.source_dir, subdir),
'CARGO_MANIFEST_PATH': os.path.join(self.environment.source_dir, subdir, 'Cargo.toml'),
'CARGO_PKG_VERSION': pkg.manifest.package.version,
'CARGO_PKG_VERSION_MAJOR': version_arr[0],
'CARGO_PKG_VERSION_MINOR': version_arr[1],
'CARGO_PKG_VERSION_PATCH': version_arr[2],
'CARGO_PKG_VERSION_PRE': version_arr[3],
'CARGO_PKG_AUTHORS': ','.join(pkg.manifest.package.authors),
'CARGO_PKG_NAME': pkg.manifest.package.name,
# FIXME: description can contain newlines which breaks ninja.
#'CARGO_PKG_DESCRIPTION': pkg.manifest.package.description or '',
'CARGO_PKG_HOMEPAGE': pkg.manifest.package.homepage or '',
'CARGO_PKG_REPOSITORY': pkg.manifest.package.repository or '',
'CARGO_PKG_LICENSE': pkg.manifest.package.license or '',
'CARGO_PKG_LICENSE_FILE': pkg.manifest.package.license_file or '',
'CARGO_PKG_RUST_VERSION': pkg.manifest.package.rust_version or '',
'CARGO_PKG_README': pkg.manifest.package.readme or '',
}

def _create_env_args(self, pkg: PackageState, build: builder.Builder, subdir: str) -> T.List[mparser.BaseNode]:
host_rustc = T.cast('RustCompiler', self.environment.coredata.compilers[MachineChoice.HOST]['rust'])
enable_env_set_args = host_rustc.enable_env_set_args()
if enable_env_set_args is None:
return [build.assign(build.array([]), 'env_args')]
# https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-crates
env_dict = self._pkg_common_env(pkg, subdir)
env_dict.update({
'CARGO_CRATE_NAME': fixup_meson_varname(pkg.manifest.package.name),
#FIXME: TODO
#CARGO_BIN_NAME
#CARGO_BIN_EXE_<name>
#CARGO_PRIMARY_PACKAGE
#CARGO_TARGET_TMPDIR
})
env_args: T.List[mparser.BaseNode] = [build.string(a) for a in enable_env_set_args]
for k, v in env_dict.items():
env_args += [build.string('--env-set'), build.string(f'{k}={v}')]
return [build.assign(build.array(env_args), 'env_args')]

def _create_lib(self, pkg: PackageState, build: builder.Builder,
lib_type: Literal['rust', 'c', 'proc-macro'],
static: bool = False, shared: bool = False) -> T.List[mparser.BaseNode]:
Expand All @@ -616,6 +667,7 @@ def _create_lib(self, pkg: PackageState, build: builder.Builder,
build.identifier('features_args'),
build.identifier(_extra_args_varname()),
build.identifier('system_deps_args'),
build.identifier('env_args'),
]

dependencies.append(build.identifier(_extra_deps_varname()))
Expand Down
24 changes: 24 additions & 0 deletions mesonbuild/compilers/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def __init__(self, exelist: T.List[str], version: str, for_machine: MachineChoic
self.native_static_libs: T.List[str] = []
self.is_beta = '-beta' in full_version
self.is_nightly = '-nightly' in full_version
self.allow_nightly = False # Will be set in sanity_check()
self.has_check_cfg = version_compare(version, '>=1.80.0')

def needs_static_linker(self) -> bool:
Expand Down Expand Up @@ -144,6 +145,14 @@ def sanity_check(self, work_dir: str, environment: Environment) -> None:
raise EnvironmentException(f'Rust compiler {self.name_string()} cannot compile programs.')
self._native_static_libs(work_dir, source_name)
self.run_sanity_check(environment, [output_name], work_dir)
# Check if we are allowed to use nightly features.
# This is done here because it's the only place we have access to
# environment object, and sanity_check() is called after the compiler
# options have been initialized.
nightly_opt = self.get_compileropt_value('nightly', environment, None)
if nightly_opt == 'enabled' and not self.is_nightly:
raise EnvironmentException(f'Rust compiler {self.name_string()} is not a nightly compiler as required by the "nightly" option.')
self.allow_nightly = nightly_opt != 'disabled' and self.is_nightly

def _native_static_libs(self, work_dir: str, source_name: str) -> None:
# Get libraries needed to link with a Rust staticlib
Expand Down Expand Up @@ -288,6 +297,12 @@ def get_options(self) -> MutableKeyedOptionDictType:
'Whether to link Rust build targets to a dynamic libstd',
False)

key = self.form_compileropt_key('nightly')
opts[key] = options.UserFeatureOption(
self.make_option_name(key),
"Nightly Rust compiler (enabled=required, disabled=don't use nightly feature, auto=use nightly feature if available)",
'auto')

return opts

def get_dependency_compile_args(self, dep: 'Dependency') -> T.List[str]:
Expand Down Expand Up @@ -384,6 +399,15 @@ def get_rustdoc(self, env: 'Environment') -> T.Optional[RustdocTestCompiler]:
self.is_cross, self.info, full_version=self.full_version,
linker=self.linker, rustc=self)

def enable_env_set_args(self) -> T.Optional[T.List[str]]:
'''Extra arguments to enable --env-set support in rustc.
Returns None if not supported.
'''
if version_compare(self.version, '>= 1.76') and self.allow_nightly:
return ['-Z', 'unstable-options']
return None


class ClippyRustCompiler(RustCompiler):

"""Clippy is a linter that wraps Rustc.
Expand Down
Loading