rust: Accept generated sources for main.rs
There are still caveats here. Rust/cargo handles generated sources by writing out all targets of a single repo into a single output directory, setting a path to that via a build-time environment variable, and then include those files via a set of functions and macros. Meson's build layout is naturally different, and ninja makes working with environment variables at compile time difficult. Fixes #8157
This commit is contained in:
parent
3ae115b57a
commit
bff0b41525
|
@ -45,7 +45,7 @@ from ..mesonlib import (
|
|||
)
|
||||
from ..mesonlib import get_compiler_for_source, has_path_sep, OptionKey
|
||||
from .backends import CleanTrees
|
||||
from ..build import InvalidArguments
|
||||
from ..build import GeneratedList, InvalidArguments
|
||||
from ..interpreter import Interpreter
|
||||
|
||||
if T.TYPE_CHECKING:
|
||||
|
@ -1581,12 +1581,23 @@ int dummy;
|
|||
args = rustc.compiler_args()
|
||||
# Compiler args for compiling this target
|
||||
args += compilers.get_base_compile_args(base_proxy, rustc)
|
||||
self.generate_generator_list_rules(target)
|
||||
main_rust_file = None
|
||||
for i in target.get_sources():
|
||||
if not rustc.can_compile(i):
|
||||
raise InvalidArguments('Rust target {} contains a non-rust source file.'.format(target.get_basename()))
|
||||
if main_rust_file is None:
|
||||
main_rust_file = i.rel_to_builddir(self.build_to_src)
|
||||
for g in target.get_generated_sources():
|
||||
for i in g.get_outputs():
|
||||
if not rustc.can_compile(i):
|
||||
raise InvalidArguments('Rust target {} contains a non-rust source file.'.format(target.get_basename()))
|
||||
if isinstance(g, GeneratedList):
|
||||
fname = os.path.join(self.get_target_private_dir(target), i)
|
||||
else:
|
||||
fname = i
|
||||
if main_rust_file is None:
|
||||
main_rust_file = fname
|
||||
if main_rust_file is None:
|
||||
raise RuntimeError('A Rust target has no Rust sources. This is weird. Also a bug. Please report')
|
||||
target_name = os.path.join(target.subdir, target.get_filename())
|
||||
|
|
|
@ -569,7 +569,7 @@ class BuildTarget(Target):
|
|||
unity_opt = environment.coredata.get_option(OptionKey('unity'))
|
||||
self.is_unity = unity_opt == 'on' or (unity_opt == 'subprojects' and subproject != '')
|
||||
self.environment = environment
|
||||
self.sources = []
|
||||
self.sources: T.List[File] = []
|
||||
self.compilers = OrderedDict() # type: OrderedDict[str, Compiler]
|
||||
self.objects = []
|
||||
self.external_deps = []
|
||||
|
@ -588,7 +588,7 @@ class BuildTarget(Target):
|
|||
self.need_install = False
|
||||
self.pch = {}
|
||||
self.extra_args: T.Dict[str, T.List['FileOrString']] = {}
|
||||
self.generated = []
|
||||
self.generated: T.Sequence[T.Union[GeneratedList, CustomTarget, CustomTargetIndex]] = []
|
||||
self.d_features = {}
|
||||
self.pic = False
|
||||
self.pie = False
|
||||
|
@ -1414,7 +1414,14 @@ You probably should put it in link_with instead.''')
|
|||
|
||||
def uses_rust(self) -> bool:
|
||||
"""Is this target a rust target."""
|
||||
return self.sources and self.sources[0].fname.endswith('.rs')
|
||||
if self.sources:
|
||||
first_file = self.sources[0]
|
||||
if first_file.fname.endswith('.rs'):
|
||||
return True
|
||||
elif self.generated:
|
||||
if self.generated[0].get_outputs()[0].endswith('.rs'):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_using_msvc(self):
|
||||
'''
|
||||
|
@ -1434,11 +1441,13 @@ You probably should put it in link_with instead.''')
|
|||
2. If the target contains only objects, process_compilers guesses and
|
||||
picks the first compiler that smells right.
|
||||
'''
|
||||
compiler, _ = self.get_clink_dynamic_linker_and_stdlibs()
|
||||
# Rustc can use msvc style linkers
|
||||
if self.uses_rust():
|
||||
compiler = self.environment.coredata.compilers[self.for_machine]['rust']
|
||||
else:
|
||||
compiler, _ = self.get_clink_dynamic_linker_and_stdlibs()
|
||||
# Mixing many languages with MSVC is not supported yet so ignore stdlibs.
|
||||
if compiler and compiler.get_linker_id() in {'link', 'lld-link', 'xilink', 'optlink'}:
|
||||
return True
|
||||
return False
|
||||
return compiler and compiler.get_linker_id() in {'link', 'lld-link', 'xilink', 'optlink'}
|
||||
|
||||
def check_module_linking(self):
|
||||
'''
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('out')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.out, 'w') as f:
|
||||
f.write('fn main() { println!("I prefer tarnish, actually.") }')
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,16 @@
|
|||
project('generated rust main', 'rust')
|
||||
|
||||
gen = find_program('gen.py')
|
||||
|
||||
c = custom_target(
|
||||
'custom_target',
|
||||
command : [gen, '@OUTPUT@'],
|
||||
output : ['main.rs'],
|
||||
)
|
||||
|
||||
executable('custom_target_main', c)
|
||||
executable('custom_target_index_main', c[0])
|
||||
|
||||
gen = generator(gen, arguments : ['@OUTPUT@'], output : '@BASENAME@.rs')
|
||||
# Doesn't actually use gen.py as input, just a limitation of generators
|
||||
executable('generator_main', gen.process(['gen.py']))
|
Loading…
Reference in New Issue