@ -2779,10 +2779,9 @@ external dependencies (including libraries) must go to "dependencies".''')
self . subproject_dir , dirname ) )
return subproject
subproject_dir_abs = os . path . join ( self . environment . get_source_dir ( ) , self . subproject_dir )
r = wrap . Resolver ( subproject_dir_abs , self . coredata . get_builtin_option ( ' wrap_mode ' ) , current_subproject = self . subproject )
r = self . environment . wrap_resolver
try :
resolved = r . resolve ( dirname , method )
resolved = r . resolve ( dirname , method , self . subproject )
except wrap . WrapException as e :
subprojdir = os . path . join ( self . subproject_dir , r . directory )
if isinstance ( e , wrap . WrapNotFoundException ) :
@ -2798,7 +2797,7 @@ external dependencies (including libraries) must go to "dependencies".''')
raise e
subdir = os . path . join ( self . subproject_dir , resolved )
subdir_abs = os . path . join ( subproject_dir_abs , resolved )
subdir_abs = os . path . join ( self . environment . get_source_dir ( ) , subdir )
os . makedirs ( os . path . join ( self . build . environment . get_build_dir ( ) , subdir ) , exist_ok = True )
self . global_args_frozen = True
@ -3062,6 +3061,10 @@ external dependencies (including libraries) must go to "dependencies".''')
self . subproject_dir = spdirname
self . build . subproject_dir = self . subproject_dir
if not self . is_subproject ( ) :
wrap_mode = self . coredata . get_builtin_option ( ' wrap_mode ' )
subproject_dir_abs = os . path . join ( self . environment . get_source_dir ( ) , self . subproject_dir )
self . environment . wrap_resolver = wrap . Resolver ( subproject_dir_abs , wrap_mode )
self . build . projects [ self . subproject ] = proj_name
mlog . log ( ' Project name: ' , mlog . bold ( proj_name ) )
@ -3248,7 +3251,7 @@ external dependencies (including libraries) must go to "dependencies".''')
return success
def program_from_file_for ( self , for_machine , prognames , silent ) :
def program_from_file_for ( self , for_machine , prognames ) :
for p in unholder ( prognames ) :
if isinstance ( p , mesonlib . File ) :
continue # Always points to a local (i.e. self generated) file.
@ -3287,15 +3290,13 @@ external dependencies (including libraries) must go to "dependencies".''')
if progobj . found ( ) :
return progobj
def program_from_overrides ( self , command_names , silent = False ) :
def program_from_overrides ( self , command_names , extra_info ) :
for name in command_names :
if not isinstance ( name , str ) :
continue
if name in self . build . find_overrides :
exe = self . build . find_overrides [ name ]
if not silent :
mlog . log ( ' Program ' , mlog . bold ( name ) , ' found: ' , mlog . green ( ' YES ' ) ,
' (overridden: %s ) ' % exe . description ( ) )
extra_info . append ( mlog . blue ( ' (overriden) ' ) )
return ExternalProgramHolder ( exe , self . subproject , self . backend )
return None
@ -3313,40 +3314,75 @@ external dependencies (including libraries) must go to "dependencies".''')
% name )
self . build . find_overrides [ name ] = exe
def notfound_program ( self , args ) :
return ExternalProgramHolder ( dependencies . NonExistingExternalProgram ( ' ' . join ( args ) ) , self . subproject )
# TODO update modules to always pass `for_machine`. It is bad-form to assume
# the host machine.
def find_program_impl ( self , args , for_machine : MachineChoice = MachineChoice . HOST ,
required = True , silent = True , wanted = ' ' , search_dirs = None ) :
if not isinstance ( args , list ) :
args = [ args ]
args = mesonlib . listify ( args )
progobj = self . program_from_overrides ( args , silent = silent )
extra_info = [ ]
progobj = self . program_lookup ( args , for_machine , required , search_dirs , extra_info )
if progobj is None :
progobj = self . program_from_file_for ( for_machine , args , silent = silent )
if progobj is None :
progobj = self . program_from_system ( args , search_dirs , silent = silent )
if progobj is None and args [ 0 ] . endswith ( ' python3 ' ) :
prog = dependencies . ExternalProgram ( ' python3 ' , mesonlib . python_command , silent = True )
progobj = ExternalProgramHolder ( prog , self . subproject )
if required and ( progobj is None or not progobj . found ( ) ) :
raise InvalidArguments ( ' Program(s) {!r} not found or not executable ' . format ( args ) )
if progobj is None :
return ExternalProgramHolder ( dependencies . NonExistingExternalProgram ( ' ' . join ( args ) ) , self . subproject )
# Only store successful lookups
self . store_name_lookups ( args )
progobj = self . notfound_program ( args )
if not progobj . found ( ) :
mlog . log ( ' Program ' , mlog . bold ( progobj . get_name ( ) ) , ' found: ' , mlog . red ( ' NO ' ) )
if required :
m = ' Program {!r} not found '
raise InterpreterException ( m . format ( progobj . get_name ( ) ) )
return progobj
if wanted :
version = progobj . get_version ( self )
is_found , not_found , found = mesonlib . version_compare_many ( version , wanted )
if not is_found :
mlog . log ( ' Program ' , mlog . bold ( progobj . get_name ( ) ) , ' found: ' , mlog . red ( ' NO ' ) ,
' found {!r} but need: ' . format ( version ) ,
' , ' . join ( [ " ' {} ' " . format ( e ) for e in not_found ] ) )
' found ' , mlog . normal_cyan ( version ) , ' but need: ' ,
mlog . bold ( ' , ' . join ( [ " ' {} ' " . format ( e ) for e in not_found ] ) ) )
if required :
m = ' Invalid version of program, need {!r} {!r} found {!r} . '
raise InvalidArguments ( m . format ( progobj . get_name ( ) , not_found , version ) )
return ExternalProgramHolder ( dependencies . NonExistingExternalProgram ( ' ' . join ( args ) ) , self . subproject )
raise InterpreterException ( m . format ( progobj . get_name ( ) , not_found , version ) )
return self . notfound_program ( args )
extra_info . insert ( 0 , mlog . normal_cyan ( version ) )
# Only store successful lookups
self . store_name_lookups ( args )
mlog . log ( ' Program ' , mlog . bold ( progobj . get_name ( ) ) , ' found: ' , mlog . green ( ' YES ' ) , * extra_info )
return progobj
def program_lookup ( self , args , for_machine , required , search_dirs , extra_info ) :
progobj = self . program_from_overrides ( args , extra_info )
if progobj :
return progobj
fallback = None
wrap_mode = self . coredata . get_builtin_option ( ' wrap_mode ' )
if wrap_mode != WrapMode . nofallback :
fallback = self . environment . wrap_resolver . find_program_provider ( args )
if fallback and wrap_mode == WrapMode . forcefallback :
return self . find_program_fallback ( fallback , args , required , extra_info )
progobj = self . program_from_file_for ( for_machine , args )
if progobj is None :
progobj = self . program_from_system ( args , search_dirs , silent = True )
if progobj is None and args [ 0 ] . endswith ( ' python3 ' ) :
prog = dependencies . ExternalProgram ( ' python3 ' , mesonlib . python_command , silent = True )
progobj = ExternalProgramHolder ( prog , self . subproject ) if prog . found ( ) else None
if progobj is None and fallback and required :
progobj = self . find_program_fallback ( fallback , args , required , extra_info )
return progobj
def find_program_fallback ( self , fallback , args , required , extra_info ) :
mlog . log ( ' Fallback to subproject ' , mlog . bold ( fallback ) , ' which provides program ' ,
mlog . bold ( ' ' . join ( args ) ) )
sp_kwargs = { ' required ' : required }
self . do_subproject ( fallback , ' meson ' , sp_kwargs )
return self . program_from_overrides ( args , extra_info )
@FeatureNewKwargs ( ' find_program ' , ' 0.53.0 ' , [ ' dirs ' ] )
@FeatureNewKwargs ( ' find_program ' , ' 0.52.0 ' , [ ' version ' ] )
@FeatureNewKwargs ( ' find_program ' , ' 0.49.0 ' , [ ' disabler ' ] )
@ -3359,7 +3395,7 @@ external dependencies (including libraries) must go to "dependencies".''')
disabled , required , feature = extract_required_kwarg ( kwargs , self . subproject )
if disabled :
mlog . log ( ' Program ' , mlog . bold ( ' ' . join ( args ) ) , ' skipped: feature ' , mlog . bold ( feature ) , ' disabled ' )
return ExternalProgramHolder ( dependencies . NonExistingExternalP rogram( ' ' . join ( args ) ) , self . subproject )
return self . notfound_p rogram( args )
search_dirs = extract_search_dirs ( kwargs )
wanted = mesonlib . stringlistify ( kwargs . get ( ' version ' , [ ] ) )
@ -3453,8 +3489,12 @@ external dependencies (including libraries) must go to "dependencies".''')
raise DependencyException ( m . format ( display_name ) )
return DependencyHolder ( cached_dep , self . subproject )
else :
m = ' Subproject {} did not override dependency {} '
raise DependencyException ( m . format ( subproj_path , display_name ) )
if required :
m = ' Subproject {} did not override dependency {} '
raise DependencyException ( m . format ( subproj_path , display_name ) )
mlog . log ( ' Dependency ' , mlog . bold ( display_name ) , ' from subproject ' ,
mlog . bold ( subproj_path ) , ' found: ' , mlog . red ( ' NO ' ) )
return self . notfound_dependency ( )
if subproject . found ( ) :
self . verify_fallback_consistency ( dirname , varname , cached_dep )
dep = self . subprojects [ dirname ] . get_variable_method ( [ varname ] , { } )
@ -3549,6 +3589,18 @@ external dependencies (including libraries) must go to "dependencies".''')
return self . notfound_dependency ( )
has_fallback = ' fallback ' in kwargs
if not has_fallback and name :
# Add an implicit fallback if we have a wrap file or a directory with the same name,
# but only if this dependency is required. It is common to first check for a pkg-config,
# then fallback to use find_library() and only afterward check again the dependency
# with a fallback. If the fallback has already been configured then we have to use it
# even if the dependency is not required.
provider = self . environment . wrap_resolver . find_dep_provider ( name )
dirname = mesonlib . listify ( provider ) [ 0 ]
if provider and ( required or dirname in self . subprojects ) :
kwargs [ ' fallback ' ] = provider
has_fallback = True
if ' default_options ' in kwargs and not has_fallback :
mlog . warning ( ' The " default_options " keyworg argument does nothing without a " fallback " keyword argument. ' ,
location = self . current_node )