@@ -130,6 +130,7 @@ def get_env_dependencies(
130130 exclude_pattern = None ,
131131 permit_unsatisfiable_variants = False ,
132132 merge_build_host_on_same_platform = True ,
133+ extra_specs = None ,
133134):
134135 specs = m .get_depends_top_and_out (env )
135136 # replace x.x with our variant's numpy version, or else conda tries to literally go get x.x
@@ -148,6 +149,8 @@ def get_env_dependencies(
148149 )
149150
150151 dependencies = set (dependencies )
152+ if extra_specs :
153+ dependencies |= set (extra_specs )
151154 unsat = None
152155 random_string = "" .join (
153156 random .choice (string .ascii_uppercase + string .digits ) for _ in range (10 )
@@ -183,7 +186,7 @@ def get_env_dependencies(
183186 specs = [package_record_to_requirement (prec ) for prec in precs ]
184187 return (
185188 utils .ensure_list (
186- (specs + subpackages + pass_through_deps )
189+ (specs + subpackages + pass_through_deps + ( extra_specs or []) )
187190 or m .get_value (f"requirements/{ env } " , [])
188191 ),
189192 precs ,
@@ -441,13 +444,15 @@ def _read_upstream_pin_files(
441444 env ,
442445 permit_unsatisfiable_variants ,
443446 exclude_pattern ,
447+ extra_specs ,
444448):
445449 deps , precs , unsat = get_env_dependencies (
446450 m ,
447451 env ,
448452 m .config .variant ,
449453 exclude_pattern ,
450454 permit_unsatisfiable_variants = permit_unsatisfiable_variants ,
455+ extra_specs = extra_specs ,
451456 )
452457 # extend host deps with strong build run exports. This is important for things like
453458 # vc feature activation to work correctly in the host env.
@@ -459,12 +464,18 @@ def _read_upstream_pin_files(
459464 )
460465
461466
462- def add_upstream_pins (m : MetaData , permit_unsatisfiable_variants , exclude_pattern ):
467+ def add_upstream_pins (
468+ m : MetaData , permit_unsatisfiable_variants , exclude_pattern , extra_specs
469+ ):
463470 """Applies run_exports from any build deps to host and run sections"""
464471 # if we have host deps, they're more important than the build deps.
465472 requirements = m .get_section ("requirements" )
466473 build_deps , build_unsat , extra_run_specs_from_build = _read_upstream_pin_files (
467- m , "build" , permit_unsatisfiable_variants , exclude_pattern
474+ m ,
475+ "build" ,
476+ permit_unsatisfiable_variants ,
477+ exclude_pattern ,
478+ [] if m .is_cross else extra_specs ,
468479 )
469480
470481 # is there a 'host' section?
@@ -490,7 +501,7 @@ def add_upstream_pins(m: MetaData, permit_unsatisfiable_variants, exclude_patter
490501 host_reqs .extend (extra_run_specs_from_build .get ("strong" , []))
491502
492503 host_deps , host_unsat , extra_run_specs_from_host = _read_upstream_pin_files (
493- m , "host" , permit_unsatisfiable_variants , exclude_pattern
504+ m , "host" , permit_unsatisfiable_variants , exclude_pattern , extra_specs
494505 )
495506 if m .noarch or m .noarch_python :
496507 extra_run_specs = set (extra_run_specs_from_host .get ("noarch" , []))
@@ -647,9 +658,40 @@ def finalize_metadata(
647658 utils .insert_variant_versions (requirements , m .config .variant , "build" )
648659 utils .insert_variant_versions (requirements , m .config .variant , "host" )
649660
661+ host_requirements = requirements .get ("host" if m .is_cross else "build" , [])
662+ host_requirement_names = [req .split (" " )[0 ] for req in host_requirements ]
663+ extra_specs = []
664+ if output and output_excludes and not is_top_level and host_requirement_names :
665+ reqs = {}
666+
667+ # we first make a mapping of output -> requirements
668+ for (name , _ ), (_ , other_meta ) in m .other_outputs .items ():
669+ if name == m .name ():
670+ continue
671+ other_meta_reqs = other_meta .meta .get ("requirements" , {}).get ("run" , [])
672+ reqs [name ] = set (other_meta_reqs )
673+
674+ seen = set ()
675+ # for each subpackage that is a dependency we add its dependencies
676+ # and transitive dependencies if the dependency of the subpackage
677+ # is a subpackage.
678+ to_process = set (
679+ name for (name , _ ) in m .other_outputs if name in host_requirement_names
680+ )
681+ while to_process :
682+ name = to_process .pop ()
683+ if name == m .name ():
684+ continue
685+ for req in reqs [name ]:
686+ req_name = req .split (" " )[0 ]
687+ if req_name not in reqs :
688+ extra_specs .append (req )
689+ elif req_name not in seen :
690+ to_process .add (req_name )
691+
650692 m = parent_metadata .get_output_metadata (m .get_rendered_output (m .name ()))
651693 build_unsat , host_unsat = add_upstream_pins (
652- m , permit_unsatisfiable_variants , exclude_pattern
694+ m , permit_unsatisfiable_variants , exclude_pattern , extra_specs
653695 )
654696 # getting this AFTER add_upstream_pins is important, because that function adds deps
655697 # to the metadata.
@@ -677,6 +719,7 @@ def finalize_metadata(
677719 m .config .variant ,
678720 exclude_pattern = exclude_pattern ,
679721 permit_unsatisfiable_variants = permit_unsatisfiable_variants ,
722+ extra_specs = extra_specs ,
680723 )
681724 full_build_dep_versions = {
682725 dep .split ()[0 ]: " " .join (dep .split ()[1 :]) for dep in full_build_deps
0 commit comments