@ -15,11 +15,12 @@ import os.path
import platform
import importlib
import argparse
import typing as T
from . utils . core import MesonException , MesonBugException
from . import mlog
def errorhandler ( e , command ) :
def errorhandler ( e : Exception , command : str ) - > int :
import traceback
if isinstance ( e , MesonException ) :
mlog . exception ( e )
@ -43,8 +44,8 @@ def errorhandler(e, command):
if command == ' runpython ' :
return 2
elif isinstance ( e , OSError ) :
mlog . exception ( " Unhandled python OSError. This is probably not a Meson bug, "
" but an issue with your build environment. " )
mlog . exception ( Exception ( " Unhandled python OSError. This is probably not a Meson bug, "
" but an issue with your build environment. " ) )
return e . errno
else : # Exception
msg = ' Unhandled python exception '
@ -58,7 +59,7 @@ def errorhandler(e, command):
# Note: when adding arguments, please also add them to the completion
# scripts in $MESONSRC/data/shell-completions/
class CommandLineParser :
def __init__ ( self ) :
def __init__ ( self ) - > None :
# only import these once we do full argparse processing
from . import mconf , mdist , minit , minstall , mintro , msetup , mtest , rewriter , msubprojects , munstable_coredata , mcompile , mdevenv
from . scripts import env2mfile
@ -68,8 +69,8 @@ class CommandLineParser:
self . term_width = shutil . get_terminal_size ( ) . columns
self . formatter = lambda prog : argparse . HelpFormatter ( prog , max_help_position = int ( self . term_width / 2 ) , width = self . term_width )
self . commands = { }
self . hidden_commands = [ ]
self . commands : T . Dict [ str , argparse . ArgumentParser ] = { }
self . hidden_commands : T . List [ str ] = [ ]
self . parser = argparse . ArgumentParser ( prog = ' meson ' , formatter_class = self . formatter )
self . subparsers = self . parser . add_subparsers ( title = ' Commands ' , dest = ' command ' ,
description = ' If no command is specified it defaults to setup command. ' )
@ -109,7 +110,8 @@ class CommandLineParser:
self . add_command ( ' unstable-coredata ' , munstable_coredata . add_arguments , munstable_coredata . run ,
help_msg = argparse . SUPPRESS )
def add_command ( self , name , add_arguments_func , run_func , help_msg , aliases = None ) :
def add_command ( self , name : str , add_arguments_func : T . Callable [ [ argparse . ArgumentParser ] , None ] ,
run_func : T . Callable [ [ argparse . Namespace ] , int ] , help_msg : str , aliases : T . List [ str ] = None ) - > None :
aliases = aliases or [ ]
# FIXME: Cannot have hidden subparser:
# https://bugs.python.org/issue22848
@ -123,13 +125,13 @@ class CommandLineParser:
for i in [ name ] + aliases :
self . commands [ i ] = p
def add_runpython_arguments ( self , parser : argparse . ArgumentParser ) :
def add_runpython_arguments ( self , parser : argparse . ArgumentParser ) - > None :
parser . add_argument ( ' -c ' , action = ' store_true ' , dest = ' eval_arg ' , default = False )
parser . add_argument ( ' --version ' , action = ' version ' , version = platform . python_version ( ) )
parser . add_argument ( ' script_file ' )
parser . add_argument ( ' script_args ' , nargs = argparse . REMAINDER )
def run_runpython_command ( self , options ) :
def run_runpython_command ( self , options : argparse . Namespace ) - > int :
sys . argv [ 1 : ] = options . script_args
if options . eval_arg :
exec ( options . script_file )
@ -139,17 +141,17 @@ class CommandLineParser:
runpy . run_path ( options . script_file , run_name = ' __main__ ' )
return 0
def add_help_arguments ( self , parser ) :
def add_help_arguments ( self , parser : argparse . ArgumentParser ) - > None :
parser . add_argument ( ' command ' , nargs = ' ? ' , choices = list ( self . commands . keys ( ) ) )
def run_help_command ( self , options ) :
def run_help_command ( self , options : argparse . Namespace ) - > int :
if options . command :
self . commands [ options . command ] . print_help ( )
else :
self . parser . print_help ( )
return 0
def run ( self , args ) :
def run ( self , args : T . List [ str ] ) - > int :
implicit_setup_command_notice = False
# If first arg is not a known command, assume user wants to run the setup
# command.
@ -193,7 +195,7 @@ class CommandLineParser:
' Meson will require Python 3.7 or newer ' , fatal = False )
mlog . shutdown ( )
def run_script_command ( script_name , script_args ) :
def run_script_command ( script_name : str , script_args : T . List [ str ] ) - > int :
# Map script name to module name for those that doesn't match
script_map = { ' exe ' : ' meson_exe ' ,
' install ' : ' meson_install ' ,
@ -216,16 +218,16 @@ def run_script_command(script_name, script_args):
mlog . exception ( e )
return 1
def ensure_stdout_accepts_unicode ( ) :
def ensure_stdout_accepts_unicode ( ) - > None :
if sys . stdout . encoding and not sys . stdout . encoding . upper ( ) . startswith ( ' UTF- ' ) :
sys . stdout . reconfigure ( errors = ' surrogateescape ' )
sys . stdout . reconfigure ( errors = ' surrogateescape ' ) # type: ignore[attr-defined]
def set_meson_command ( mainfile ) :
def set_meson_command ( mainfile : str ) - > None :
# Set the meson command that will be used to run scripts and so on
from . import mesonlib
mesonlib . set_meson_command ( mainfile )
def run ( original_args , mainfile ) :
def run ( original_args : T . List [ str ] , mainfile : str ) - > int :
if os . environ . get ( ' MESON_SHOW_DEPRECATIONS ' ) :
# workaround for https://bugs.python.org/issue34624
import warnings
@ -274,7 +276,7 @@ def run(original_args, mainfile):
set_meson_command ( mainfile )
return CommandLineParser ( ) . run ( args )
def main ( ) :
def main ( ) - > int :
# Always resolve the command path so Ninja can find it for regen, tests, etc.
if ' meson.exe ' in sys . executable :
assert os . path . isabs ( sys . executable )