Skip to content

Commit

Permalink
Allow overriding programs from the command line
Browse files Browse the repository at this point in the history
People coming from autotools are used to having easy access for
overriding programs. This should ease that transition.
  • Loading branch information
tristan957 committed Dec 12, 2023
1 parent cc5a95a commit 54a475d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 1 deletion.
24 changes: 24 additions & 0 deletions mesonbuild/coredata.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,9 @@ def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command:
self.options: 'MutableKeyedOptionDictType' = {}
self.cross_files = self.__load_config_files(options, scratch_dir, 'cross')
self.compilers: PerMachine[T.Dict[str, Compiler]] = PerMachine(OrderedDict(), OrderedDict())
self.program_aliases: PerMachine[T.Dict[str, str]] = PerMachine(
self.__parse_program_aliases(options, MachineChoice.BUILD),
self.__parse_program_aliases(options, MachineChoice.HOST))

# Set of subprojects that have already been initialized once, this is
# required to be stored and reloaded with the coredata, as we don't
Expand All @@ -595,6 +598,24 @@ def __init__(self, options: argparse.Namespace, scratch_dir: str, meson_command:
self.builtin_options_libdir_cross_fixup()
self.init_builtins('')

@staticmethod
def __parse_program_aliases(options: argparse.Namespace, for_machine: MachineChoice) -> OrderedDict[str, str]:
alias_map: OrderedDict[str, str] = OrderedDict()
aliases: T.List[str]
if for_machine == MachineChoice.HOST:
aliases = options.native_program
elif for_machine == MachineChoice.BUILD:
aliases = options.cross_program

for a in aliases:
parts = a.split('=', 1)
if len(parts) == 1:
pass

alias_map[parts[0]] = parts[1]

return alias_map

@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 Expand Up @@ -1040,6 +1061,9 @@ def emit_base_options_warnings(self, enabled_opts: T.List[OptionKey]) -> None:
mlog.warning('Base option \'b_bitcode\' is enabled, which is incompatible with many linker options. Incompatible options such as \'b_asneeded\' have been disabled.', fatal=False)
mlog.warning('Please see https://mesonbuild.com/Builtin-options.html#Notes_about_Apple_Bitcode_support for more details.', fatal=False)

def get_program_aliases(self, for_machine: MachineChoice) -> T.Dict[str, str]:
return self.program_aliases[for_machine]

class CmdLineFileParser(configparser.ConfigParser):
def __init__(self) -> None:
# We don't want ':' as key delimiter, otherwise it would break when
Expand Down
26 changes: 26 additions & 0 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,28 @@ def add_languages_for(self, args: T.List[str], required: bool, for_machine: Mach

return success

def program_from_alias(self, for_machine: MachineChoice, prognames: T.List[mesonlib.FileOrString],
extra_info: T.List[mlog.TV_Loggable]) -> T.Optional[ExternalProgram]:
program_aliases = self.coredata.get_program_aliases(for_machine)
if not program_aliases:
return None

for p in prognames:
if isinstance(p, mesonlib.File):
continue # Always points to a local (i.e. self generated) file.
if not isinstance(p, str):
raise InterpreterException('Executable name must be a string')

alias = program_aliases.get(p, None)
if not alias:
return None

prog = ExternalProgram(p, command=alias, silent=True)
if not isinstance(prog, NonExistingExternalProgram):
extra_info.append(mlog.blue('(alias)'))
return prog
return None

def program_from_file_for(self, for_machine: MachineChoice, prognames: T.List[mesonlib.FileOrString]
) -> T.Optional[ExternalProgram]:
for p in prognames:
Expand Down Expand Up @@ -1669,6 +1691,10 @@ def program_lookup(self, args: T.List[mesonlib.FileOrString], for_machine: Machi
if progobj:
return progobj

progobj = self.program_from_alias(for_machine, args, extra_info)
if progobj:
return progobj

if args[0] == 'meson':
# Override find_program('meson') to return what we were invoked with
return ExternalProgram('meson', self.environment.get_build_command(), silent=True)
Expand Down
12 changes: 12 additions & 0 deletions mesonbuild/msetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from pathlib import Path
import typing as T

from mesonbuild.utils.universal import MachineChoice

from . import build, coredata, environment, interpreter, mesonlib, mintro, mlog
from .mesonlib import MesonException

Expand Down Expand Up @@ -59,6 +61,14 @@ def add_arguments(parser: argparse.ArgumentParser) -> None:
'newer version of meson.')
parser.add_argument('--clearcache', action='store_true', default=False,
help='Clear cached state (e.g. found dependencies). Since 1.3.0.')
parser.add_argument('--native-program',
default=[],
action='append',
help='Provide a native program override. Since 1.4.0.')
parser.add_argument('--cross-program',
default=[],
action='append',
help='Provide a non-native program override. Since 1.4.0.')
parser.add_argument('builddir', nargs='?', default=None)
parser.add_argument('sourcedir', nargs='?', default=None)

Expand Down Expand Up @@ -256,6 +266,8 @@ def _generate(self, env: environment.Environment, capture: bool, vslite_ctx: T.O
# read from a pipe and wrote into a private file.
self.options.cross_file = env.coredata.cross_files
self.options.native_file = env.coredata.config_files
self.options.cross_program = env.coredata.get_program_aliases(MachineChoice.HOST)
self.options.native_program = env.coredata.get_program_aliases(MachineChoice.BUILD)
coredata.write_cmd_line_file(self.build_dir, self.options)
else:
coredata.update_cmd_line_file(self.build_dir, self.options)
Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class ExternalProgram(mesonlib.HoldableObject):
windows_exts = ('exe', 'msc', 'com', 'bat', 'cmd')
for_machine = MachineChoice.BUILD

def __init__(self, name: str, command: T.Optional[T.List[str]] = None,
def __init__(self, name: str, command: T.Optional[T.Union[str, T.List[str]]] = None,
silent: bool = False, search_dir: T.Optional[str] = None,
extra_search_dirs: T.Optional[T.List[str]] = None):
self.name = name
Expand Down

0 comments on commit 54a475d

Please sign in to comment.