Skip to content
Open
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
17 changes: 17 additions & 0 deletions docs/markdown/Rust-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,23 @@ were never turned on by Meson.
bindgen_clang_arguments = ['--target', 'x86_64-linux-gnu']
```

### compiler_target()

*Since 1.11.0*

```meson
rustmod.compiler_target()
rustmod.compiler_target(native: true)
```

Returns the Rust target triple (e.g. `x86_64-unknown-linux-gnu`) for the
Rust compiler. By default, or with `native: false`, this returns the
target for the host machine. If `native: true` is passed, it returns
the target for the build machine instead.

This is useful when converting build scripts to Meson, because it
matches the value of Cargo's `TARGET` and `HOST` environment variables.

### proc_macro()

```meson
Expand Down
5 changes: 5 additions & 0 deletions docs/markdown/snippets/rust_compiler_target.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## `compiler_target()` method in the Rust module

The Rust module has a `compiler_target()` method that can be useful
when converting build scripts to Meson, because its return value
matches the value of Cargo's `TARGET` and `HOST` environment variables.
16 changes: 15 additions & 1 deletion mesonbuild/compilers/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import typing as T

from .. import options
from ..mesonlib import EnvironmentException, MesonException, Popen_safe_logged, version_compare
from ..mesonlib import EnvironmentException, MesonException, Popen_safe, Popen_safe_logged, version_compare
from ..linkers.linkers import VisualStudioLikeLinkerMixin
from ..options import OptionKey
from .compilers import Compiler, CompileCheckMode, clike_debug_args, is_library
Expand Down Expand Up @@ -239,6 +239,20 @@ def get_cfgs(self) -> T.List[str]:
p, stdo, stde = Popen_safe_logged(cmd)
return stdo.splitlines()

@functools.lru_cache(maxsize=None)
def get_target_triple(self) -> str:
# First check if --target is explicitly set in the compiler command
target = parse_target(self.get_exe_args())
if target:
return target
# Fall back to parsing the host triple from `rustc -vV`
cmd = self.get_exelist(ccache=False) + ['-vV']
p, stdo, stde = Popen_safe(cmd)
for line in stdo.splitlines():
if line.startswith('host:'):
return line.split(':', 1)[1].strip()
raise EnvironmentException('Could not determine Rust target triple')

@functools.lru_cache(maxsize=None)
def get_crt_static(self) -> bool:
return 'target_feature="crt-static"' in self.get_cfgs()
Expand Down
5 changes: 5 additions & 0 deletions mesonbuild/interpreter/kwargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
TestArgs = T.Union[str, File, build.Target, ExternalProgram]
RustAbi = Literal['rust', 'c']

class NativeKW(TypedDict):

native: MachineChoice


class FuncAddProjectArgs(TypedDict):

"""Keyword Arguments for the add_*_arguments family of arguments.
Expand Down
5 changes: 1 addition & 4 deletions mesonbuild/interpreter/mesonmain.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from ..interpreterbase import TYPE_kwargs, TYPE_var
from ..mesonlib import ExecutableSerialisation
from .interpreter import Interpreter
from .kwargs import NativeKW

class FuncOverrideDependency(TypedDict):

Expand All @@ -42,10 +43,6 @@ class AddInstallScriptKW(TypedDict):
install_tag: str
dry_run: bool

class NativeKW(TypedDict):

native: mesonlib.MachineChoice

class AddDevenvKW(TypedDict):
method: Literal['set', 'prepend', 'append']
separator: str
Expand Down
16 changes: 15 additions & 1 deletion mesonbuild/modules/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from ..dependencies import Dependency
from ..interpreter.type_checking import (
DEPENDENCIES_KW, LINK_WITH_KW, LINK_WHOLE_KW, SHARED_LIB_KWS, TEST_KWS, TEST_KWS_NO_ARGS,
OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS, NoneType, in_set_validator
OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS, NATIVE_KW, NoneType, in_set_validator,
)
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noKwargs, noPosargs, permittedKwargs
from ..interpreter.interpreterobjects import Doctest
Expand Down Expand Up @@ -217,6 +217,7 @@ def __init__(self, interpreter: Interpreter) -> None:
'test': self.test,
'doctest': self.doctest,
'bindgen': self.bindgen,
'compiler_target': self.compiler_target,
'proc_macro': self.proc_macro,
'workspace': self.workspace,
})
Expand Down Expand Up @@ -612,6 +613,19 @@ def bindgen(self, state: ModuleState, args: T.List, kwargs: FuncBindgen) -> Modu

return ModuleReturnValue(target, [target])

@FeatureNew('rust.compiler_target', '1.11.0')
@noPosargs
@typed_kwargs('rust.compiler_target', NATIVE_KW)
def compiler_target(self, state: ModuleState, args: T.List, kwargs: '_kwargs.NativeKW') -> str:
"""Returns the Rust target triple for the specified machine's Rust compiler."""
for_machine = kwargs['native']
compilers = state._interpreter.coredata.compilers[for_machine]
if 'rust' in compilers:
rustc = T.cast('RustCompiler', compilers['rust'])
return rustc.get_target_triple()
else:
raise MesonException(f'No Rust compiler was requested for the {for_machine} machine')

# Allow a limited set of kwargs, but still use the full set of typed_kwargs()
# because it could be setting required default values.
@FeatureNew('rust.proc_macro', '1.3.0')
Expand Down
13 changes: 0 additions & 13 deletions test cases/rust/36 compiles/meson.build

This file was deleted.

27 changes: 27 additions & 0 deletions test cases/rust/36 probes/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
project('rust compiles', 'rust')

rustc = meson.get_compiler('rust')

# Test that compiles() works without and with a main function
assert(rustc.compiles('pub fn foo() {}'), 'compiles() without main should work')
assert(rustc.compiles('pub fn main() {}'), 'compiles() with main should work')

# Test with a simple expression
assert(rustc.compiles('pub fn bar() { let _x: i32 = 1; }'), 'compiles() with simple code should work')

# Test that invalid code fails
assert(not rustc.compiles('pub fn baz() { invalid_syntax }'), 'compiles() should fail on invalid code')


rustmod = import('rust')

cargo_target = rustmod.compiler_target()
message('Host Rust target triple: ' + cargo_target)
assert(cargo_target != '', 'compiler_target() should return a non-empty string')
assert(cargo_target == rustmod.compiler_target(native: false), 'compiler_target(native: false) should match the default')
assert(cargo_target.contains('-'), 'compiler_target() should return a triple containing dashes')

cargo_host = rustmod.compiler_target(native: true)
message('Build Rust target triple: ' + cargo_host)
assert(cargo_host != '', 'compiler_target(native: true) should return a non-empty string')
assert(cargo_host.contains('-'), 'compiler_target(native: true) should return a triple containing dashes')
Loading