Skip to content

Commit

Permalink
cargo: Add support for target specific dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
xclaesse committed Oct 11, 2024
1 parent e46f036 commit 3a794cd
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 13 deletions.
42 changes: 31 additions & 11 deletions mesonbuild/cargo/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
import urllib.parse
import typing as T

from . import builder
from . import version
from . import builder, version, cfg
from ..mesonlib import MesonException, Popen_safe, File, MachineChoice
from .. import coredata, mlog
from ..wrap.wrap import PackageDefinition
Expand Down Expand Up @@ -418,10 +417,14 @@ class PackageKey:
class Interpreter:
def __init__(self, env: Environment) -> None:
self.environment = env
self.build_rustc = T.cast('RustCompiler', self.environment.coredata.compilers[MachineChoice.BUILD]['rust'])
self.host_rustc = T.cast('RustCompiler', self.environment.coredata.compilers[MachineChoice.HOST]['rust'])
# Map Cargo.toml's subdir to loaded manifest.
self.manifests: T.Dict[str, Manifest] = {}
# Map of cargo package (name + api) to its state
self.packages: T.Dict[PackageKey, PackageState] = {}
# Rustc's config
self.cfgs = self._get_cfgs()

def interpret(self, subdir: str) -> T.Tuple[mparser.CodeBlockNode, T.List[str]]:
manifest = self._load_manifest(subdir)
Expand Down Expand Up @@ -473,6 +476,10 @@ def _fetch_package(self, package_name: str, api: str) -> T.Tuple[PackageState, b
manifest = self._load_manifest(subdir)
pkg = PackageState(manifest)
self.packages[key] = pkg
# Merge target specific dependencies that are enabled
for condition, dependencies in manifest.target.items():
if cfg.eval_cfg(condition, self.cfgs):
manifest.dependencies.update(dependencies)
# Fetch required dependencies recursively.
for depname, dep in manifest.dependencies.items():
if not dep.optional:
Expand Down Expand Up @@ -556,20 +563,17 @@ def _run_build_rs(self, pkg: PackageState, subdir: str) -> T.Tuple[T.List[str],
mlog.warning('Cannot use build.rs with build-dependencies. It should be ported manually in meson/meson.build.')
return [], []

build_rustc = T.cast('RustCompiler', self.environment.coredata.compilers[MachineChoice.BUILD]['rust'])
host_rustc = T.cast('RustCompiler', self.environment.coredata.compilers[MachineChoice.HOST]['rust'])

# Prepare build.rs run environment
# https://doc.rust-lang.org/cargo/reference/environment-variables.html
host_rustc_cmd = host_rustc.get_exelist(ccache=False)
host_rustc_cmd = self.host_rustc.get_exelist(ccache=False)
out_dir = os.path.join(self.environment.build_dir, subdir, 'build.rs.p')
version_arr = pkg.manifest.package.version.split('.')
version_arr += ['' * (4 - len(version_arr))]
env = os.environ.copy()
env.update({
'OUT_DIR': out_dir,
'RUSTC': host_rustc_cmd[0],
'TARGET': host_rustc.get_target_triplet(),
'TARGET': self.host_rustc.get_target_triplet(),
'CARGO_MANIFEST_DIR': os.path.join(self.environment.source_dir, subdir),
'CARGO_PKG_VERSION': pkg.manifest.package.version,
'CARGO_PKG_VERSION_MAJOR': version_arr[0],
Expand All @@ -589,16 +593,15 @@ def _run_build_rs(self, pkg: PackageState, subdir: str) -> T.Tuple[T.List[str],

def conv(k: str) -> str:
return k.upper().replace('-', '_')
# TODO: Add cfgs
#for k, v in self.cfgs.items():
# env[f'CARGO_CFG_{conv(k)}'] = v
for k, v in self.cfgs.items():
env[f'CARGO_CFG_{conv(k)}'] = v
for f in pkg.features:
env[f'CARGO_FEATURE_{conv(f)}'] = ''

# Compile and run build.rs
build_rs_file = File.from_absolute_file(build_rs)
cwd = os.path.join(self.environment.source_dir, subdir)
res = build_rustc.run(build_rs_file, self.environment, run_env=env, run_cwd=cwd)
res = self.build_rustc.run(build_rs_file, self.environment, run_env=env, run_cwd=cwd)
if res.returncode != 0:
raise MesonException('Could not run build.rs')
mlog.log('Run ', mlog.bold('build.rs'), ': ', mlog.green('YES'), sep='')
Expand All @@ -617,6 +620,23 @@ def conv(k: str) -> str:

return compiler_args, build_def_files

def _get_cfgs(self) -> T.Dict[str, str]:
cfgs = self.host_rustc.get_cfgs().copy()
rustflags = self.environment.coredata.get_external_args(MachineChoice.HOST, 'rust')
rustflags_i = iter(rustflags)
for i in rustflags_i:
if i == '--cfg':
cfgs.append(next(rustflags_i))
return dict(self._split_cfg(i) for i in cfgs)

@staticmethod
def _split_cfg(cfg: str) -> T.Tuple[str, str]:
pair = cfg.split('=', maxsplit=1)
value = pair[1] if len(pair) > 1 else ''
if value and value[0] == '"':
value = value[1:-1]
return pair[0], value

def _create_project(self, pkg: PackageState, build: builder.Builder) -> T.List[mparser.BaseNode]:
"""Create the project() function call
Expand Down
8 changes: 6 additions & 2 deletions mesonbuild/compilers/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,20 @@ def _native_static_libs(self, work_dir: str, source_name: str) -> None:
def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]:
return ['--dep-info', outfile]

@functools.lru_cache(maxsize=None)
def get_sysroot(self) -> str:
cmd = self.get_exelist(ccache=False) + ['--print', 'sysroot']
p, stdo, stde = Popen_safe_logged(cmd)
return stdo.split('\n', maxsplit=1)[0]

@functools.lru_cache(maxsize=None)
def get_crt_static(self) -> bool:
def get_cfgs(self) -> T.List[str]:
cmd = self.get_exelist(ccache=False) + ['--print', 'cfg']
p, stdo, stde = Popen_safe_logged(cmd)
return bool(re.search('^target_feature="crt-static"$', stdo, re.MULTILINE))
return stdo.splitlines()

def get_crt_static(self) -> bool:
return 'target_feature="crt-static"' in self.get_cfgs()

@functools.lru_cache(maxsize=None)
def get_target_triplet(self) -> str:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ features = ["f1"]
[dependencies.libname]
version = "1"

[target."cfg(unix)".dependencies.unixdep]
version = "0.1"

[features]
default = ["f1"]
f1 = ["f2", "f3"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ extern "C" {
#[cfg(feature = "foo")]
#[no_mangle]
pub extern "C" fn rust_func() -> i32 {
if cfg!(unix) {
extern crate unixdep;
assert!(unixdep::only_on_unix() == 0);
}
assert!(common::common_func() == 0);
assert!(libothername::stuff() == 42);
let v: i32;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[wrap-file]
method = cargo
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "unixdep"
version = "0.1"
edition = "2021"

[lib]
path = "lib.rs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub fn only_on_unix() -> i32 {
0
}

#[cfg(not(unix))]
pub fn broken() -> i32 {
plop
}

0 comments on commit 3a794cd

Please sign in to comment.