Skip to content

Commit

Permalink
[WIP] SQUASHME
Browse files Browse the repository at this point in the history
  • Loading branch information
oleavr committed Feb 7, 2024
1 parent 831234b commit 6e466e5
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 22 deletions.
27 changes: 19 additions & 8 deletions mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,22 @@ def get_custom_targets(self):

def copy(self) -> Build:
other = Build(self.environment)
self._copy_to(other)
return other

def copy_to_native(self) -> Build:
other = Build(self.environment.copy_to_native())
self._copy_to(other)
return other

def _copy_to(self, other: Build) -> None:
for k, v in self.__dict__.items():
if k == 'environment':
continue
if isinstance(v, (list, dict, set, OrderedDict)):
other.__dict__[k] = v.copy()
else:
other.__dict__[k] = v
return other

def merge(self, other: Build) -> None:
for k, v in other.__dict__.items():
Expand All @@ -307,7 +317,7 @@ def ensure_static_linker(self, compiler: Compiler) -> None:
self.static_linker[compiler.for_machine] = detect_static_linker(self.environment, compiler)

def get_project(self):
return self.projects['']
return self.projects[('', MachineChoice.HOST)]

def get_subproject_dir(self):
return self.subproject_dir
Expand Down Expand Up @@ -596,7 +606,7 @@ def get_basename(self) -> str:
return self.name

def get_subdir(self) -> str:
return self.subdir
return self.environment.build_output_rpath(self.subdir)

def get_typename(self) -> str:
return self.typename
Expand All @@ -612,7 +622,7 @@ def _get_id_hash(target_id: str) -> str:
return h.hexdigest()[:7]

@staticmethod
def construct_id_from_path(subdir: str, name: str, type_suffix: str) -> str:
def construct_id_from_path(subdir: str, name: str, type_suffix: str, extra_suffix: str = '') -> str:
"""Construct target ID from subdir, name and type suffix.
This helper function is made public mostly for tests."""
Expand All @@ -623,7 +633,7 @@ def construct_id_from_path(subdir: str, name: str, type_suffix: str) -> str:
# FIXME replace with assert when slash in names is prohibited
name_part = name.replace('/', '@').replace('\\', '@')
assert not has_path_sep(type_suffix)
my_id = name_part + type_suffix
my_id = name_part + type_suffix + extra_suffix
if subdir:
subdir_part = Target._get_id_hash(subdir)
# preserve myid for better debuggability
Expand All @@ -635,7 +645,7 @@ def get_id(self) -> str:
if getattr(self, 'name_suffix_set', False):
name += '.' + self.suffix
return self.construct_id_from_path(
self.subdir, name, self.type_suffix())
self.subdir, name, self.type_suffix(), '@native' if self.environment.is_native_clone else '')

def process_kwargs_base(self, kwargs: T.Dict[str, T.Any]) -> None:
if 'build_by_default' in kwargs:
Expand Down Expand Up @@ -1481,8 +1491,9 @@ def check_can_link_together(self, t: BuildTargetTypes) -> None:
links_with_rust_abi = isinstance(t, BuildTarget) and t.uses_rust_abi()
if not self.uses_rust() and links_with_rust_abi:
raise InvalidArguments(f'Try to link Rust ABI library {t.name!r} with a non-Rust target {self.name!r}')
if t.subproject and not self.environment.is_cross_build():
return
# XXX: Do we still need this?
#if t.subproject and not self.environment.is_cross_build():
# return
if self.for_machine is not t.for_machine and (not links_with_rust_abi or t.rust_crate_type != 'proc-macro'):
msg = f'Tried to mix libraries for machines {self.for_machine} and {t.for_machine} in target {self.name!r}'
if self.environment.is_cross_build():
Expand Down
22 changes: 22 additions & 0 deletions mesonbuild/coredata.py
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,28 @@ def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command:
self.builtin_options_libdir_cross_fixup()
self.init_builtins('')

def copy_to_native(self) -> CoreData:
other = CoreData.__new__(CoreData)
for k, v in self.__dict__.items():
other.__dict__[k] = v

# TODO: Copy options

other.cross_files = []

other.compilers = PerMachine(OrderedDict(), OrderedDict())
other.compilers.build = self.compilers.build

other.deps = PerMachineDefaultable.default(
is_cross=False,
build=self.deps.build,
host=self.deps.host)

self.compiler_check_cache.clear()
self.run_check_cache.clear()

return other

@staticmethod
def __load_config_files(options: argparse.Namespace, scratch_dir: str, ftype: str) -> T.List[str]:
# Need to try and make the passed filenames absolute because when the
Expand Down
39 changes: 39 additions & 0 deletions mesonbuild/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,39 @@ def __init__(self, source_dir: str, build_dir: str, options: 'argparse.Namespace
self.default_pkgconfig = ['pkg-config']
self.wrap_resolver: T.Optional['Resolver'] = None

self.is_native_clone = False

def copy_to_native(self) -> Build:
other = Environment.__new__(Environment)
for k, v in self.__dict__.items():
other.__dict__[k] = v

other.coredata = self.coredata.copy_to_native()

machines: PerThreeMachineDefaultable[MachineInfo] = PerThreeMachineDefaultable()
machines.build = self.machines.build
other.machines = machines.default_missing()

binaries: PerMachineDefaultable[BinaryTable] = PerMachineDefaultable()
binaries.build = self.binaries.build
other.binaries = binaries.default_missing()

properties: PerMachineDefaultable[Properties] = PerMachineDefaultable()
properties.build = self.properties.build
other.properties = properties.default_missing()

cmakevars: PerMachineDefaultable[CMakeVariables] = PerMachineDefaultable()
cmakevars.build = self.cmakevars.build
other.cmakevars = cmakevars.default_missing()

# TODO: Copy options

other.exe_wrapper = None

other.is_native_clone = True

return other

def _load_machine_file_options(self, config: 'ConfigParser', properties: Properties, machine: MachineChoice) -> None:
"""Read the contents of a Machine file and put it in the options store."""

Expand Down Expand Up @@ -841,6 +874,12 @@ def get_source_dir(self) -> str:
def get_build_dir(self) -> str:
return self.build_dir

def build_output_rpath(self, subdir: str, *parts: T.Sequence[str]) -> str:
result = subdir
if self.is_native_clone:
result += '-native'
return os.path.join(result, *parts)

def get_import_lib_dir(self) -> str:
"Install dir for the import library (library used for linking)"
return self.get_libdir()
Expand Down
1 change: 1 addition & 0 deletions mesonbuild/interpreter/dependencyfallbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def _do_subproject(self, kwargs: TYPE_nkwargs, func_args: TYPE_nvar, func_kwargs
func_kwargs.setdefault('version', [])
if 'default_options' in kwargs and isinstance(kwargs['default_options'], str):
func_kwargs['default_options'] = listify(kwargs['default_options'])
func_kwargs.setdefault('native', kwargs.get('native', False))
self.interpreter.do_subproject(subp_name, func_kwargs)
return self._get_subproject_dep(subp_name, varname, kwargs)

Expand Down
33 changes: 21 additions & 12 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from .. import mesonlib
from ..mesonlib import (EnvironmentVariables, ExecutableSerialisation, MesonBugException, MesonException, HoldableObject,
FileMode, MachineChoice, OptionKey, listify,
extract_as_list, has_path_sep, path_is_in_root, PerMachine)
extract_as_list, has_path_sep, path_is_in_root, PerMachine, PerThreeMachineDefaultable)
from ..programs import ExternalProgram, NonExistingExternalProgram
from ..dependencies import Dependency
from ..depfile import DepFile
Expand Down Expand Up @@ -271,7 +271,7 @@ def __init__(
_build: build.Build,
backend: T.Optional[Backend] = None,
subp_name: str = '',
subp_id: str = '',
subp_id: T.Tuple[str, MachineChoice] = ('', MachineChoice.HOST),
subdir: str = '',
subproject_dir: str = 'subprojects',
default_project_options: T.Optional[T.Dict[OptionKey, str]] = None,
Expand Down Expand Up @@ -966,7 +966,8 @@ def _do_subproject_meson(self, subp_name: str, subp_id: str, subdir: str,
ast: T.Optional[mparser.CodeBlockNode] = None,
build_def_files: T.Optional[T.List[str]] = None,
relaxations: T.Optional[T.Set[InterpreterRuleRelaxation]] = None) -> SubprojectHolder:
subp_id = self._make_subproject_id(subp_name, kwargs.get('native', False))
native = kwargs.get('native', False)
subp_id = self._make_subproject_id(subp_name, native)

with mlog.nested(subp_name):
if ast:
Expand All @@ -982,7 +983,10 @@ def _do_subproject_meson(self, subp_name: str, subp_id: str, subdir: str,
mlog.log('Generated Meson AST:', meson_filename)
mlog.cmd_ci_include(meson_filename)

new_build = self.build.copy()
if native and self.coredata.is_cross_build():
new_build = self.build.copy_to_native()
else:
new_build = self.build.copy()
subi = Interpreter(new_build, self.backend, subp_name, subp_id, subdir, self.subproject_dir,
default_options, ast=ast, is_translated=(ast is not None),
relaxations=relaxations,
Expand Down Expand Up @@ -1274,7 +1278,7 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str
proj_license_files.append((ifname, i))
self.build.dep_manifest[proj_name] = build.DepManifest(self.project_version, proj_license,
proj_license_files, self.subproject)
if self.subproject in self.build.projects:
if self.subp_id in self.build.projects:
raise InvalidCode('Second call to project().')

# spdirname is the subproject_dir for this project, relative to self.subdir.
Expand Down Expand Up @@ -1302,7 +1306,7 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str
else:
self.environment.wrap_resolver = r

self.build.projects[self.subproject] = proj_name
self.build.projects[self.subp_id] = proj_name
mlog.log('Project name:', mlog.bold(proj_name))
mlog.log('Project version:', mlog.bold(self.project_version))

Expand Down Expand Up @@ -1424,7 +1428,7 @@ def _print_summary(self) -> None:
self.summary_impl('User defined options', values, {'bool_yn': False, 'list_sep': None})
# Print all summaries, main project last.
mlog.log('') # newline
main_summary = self.summary.pop('', None)
main_summary = self.summary.pop(('', MachineChoice.HOST), None)
is_cross_build = self.coredata.is_cross_build()
for subp_id, summary in sorted(self.summary.items()):
if self.subprojects[subp_id].found():
Expand Down Expand Up @@ -2644,17 +2648,19 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
output = outputs[0]
if depfile:
depfile = mesonlib.substitute_values([depfile], values)[0]
ofile_rpath = os.path.join(self.subdir, output)
ofile_rpath = self.environment.build_output_rpath(self.subdir, output)
if ofile_rpath in self.configure_file_outputs:
mesonbuildfile = os.path.join(self.subdir, 'meson.build')
current_call = f"{mesonbuildfile}:{self.current_lineno}"
first_call = "{}:{}".format(mesonbuildfile, self.configure_file_outputs[ofile_rpath])
mlog.warning('Output file', mlog.bold(ofile_rpath, True), 'for configure_file() at', current_call, 'overwrites configure_file() output at', first_call)
else:
self.configure_file_outputs[ofile_rpath] = self.current_lineno
(ofile_path, ofile_fname) = os.path.split(os.path.join(self.subdir, output))
(ofile_path, ofile_fname) = os.path.split(ofile_rpath)
ofile_abs = os.path.join(self.environment.build_dir, ofile_path, ofile_fname)

output_subdir = self.environment.build_output_rpath(self.subdir)

# Perform the appropriate action
if kwargs['configuration'] is not None:
conf = kwargs['configuration']
Expand All @@ -2668,8 +2674,8 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
mlog.log('Configuring', mlog.bold(output), 'using configuration')
if len(inputs) > 1:
raise InterpreterException('At most one input file can given in configuration mode')
os.makedirs(os.path.join(self.environment.build_dir, output_subdir), exist_ok=True)
if inputs:
os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
file_encoding = kwargs['encoding']
missing_variables, confdata_useless = \
mesonlib.do_conf_file(inputs_abs[0], ofile_abs, conf,
Expand Down Expand Up @@ -2727,7 +2733,7 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
elif kwargs['copy']:
if len(inputs_abs) != 1:
raise InterpreterException('Exactly one input file must be given in copy mode')
os.makedirs(os.path.join(self.environment.build_dir, self.subdir), exist_ok=True)
os.makedirs(os.path.join(self.environment.build_dir, output_subdir), exist_ok=True)
shutil.copy2(inputs_abs[0], ofile_abs)

# Install file if requested, we check for the empty string
Expand All @@ -2750,7 +2756,7 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
install_tag = kwargs['install_tag']
self.build.data.append(build.Data([cfile], idir, idir_name, install_mode, self.subproject,
install_tag=install_tag, data_type='configure'))
return mesonlib.File.from_built_file(self.subdir, output)
return mesonlib.File.from_built_file(output_subdir, output)

def extract_incdirs(self, kwargs, key: str = 'include_directories') -> T.List[build.IncludeDirs]:
prospectives = extract_as_list(kwargs, key)
Expand Down Expand Up @@ -3186,6 +3192,9 @@ def add_target(self, name: str, tobj: build.Target) -> None:
FeatureNew.single_use(f'multiple executables with the same name, "{tobj.name}", but different suffixes in the same directory',
'1.3.0', self.subproject, location=self.current_node)

if self.environment.is_native_clone and hasattr(tobj, 'for_machine'):
tobj.for_machine = MachineChoice.BUILD

if isinstance(tobj, build.BuildTarget):
self.add_languages(tobj.missing_languages, True, tobj.for_machine)
tobj.process_compilers_late()
Expand Down
7 changes: 5 additions & 2 deletions mesonbuild/interpreter/mesonmain.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def current_build_dir_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwarg
sub = self.interpreter.subdir
if sub == '':
return src
return os.path.join(src, sub)
return os.path.join(src, self.interpreter.environment.build_output_rpath(sub))

@noPosargs
@noKwargs
Expand Down Expand Up @@ -384,7 +384,10 @@ def _override_dependency_impl(self, name: str, dep: dependencies.Dependency, kwa
else:
nkwargs['static'] = static
identifier = dependencies.get_dep_identifier(name, nkwargs)
for_machine = kwargs['native']
if self.interpreter.environment.is_native_clone:
for_machine = MachineChoice.BUILD
else:
for_machine = kwargs['native']
override = self.build.dependency_overrides[for_machine].get(identifier)
if override:
if permissive:
Expand Down

0 comments on commit 6e466e5

Please sign in to comment.