@@ -614,29 +614,58 @@ func (pme *Explorer) GetTool(toolID string) *cores.Tool {
614614 }
615615}
616616
617- // FindToolsRequiredForBoard FIXMEDOC
618- func (pme * Explorer ) FindToolsRequiredForBoard (board * cores.Board ) ([]* cores.ToolRelease , error ) {
619- pme .log .Infof ("Searching tools required for board %s" , board )
620-
621- // core := board.Properties["build.core"]
622- platform := board .PlatformRelease
623-
624- // maps "PACKAGER:TOOL" => ToolRelease
625- foundTools := map [string ]* cores.ToolRelease {}
626-
627- // a Platform may not specify required tools (because it's a platform that comes from a
628- // user/hardware dir without a package_index.json) then add all available tools
629- for _ , targetPackage := range pme .packages {
630- for _ , tool := range targetPackage .Tools {
631- rel := tool .GetLatestInstalled ()
632- if rel != nil {
633- foundTools [rel .Tool .Name ] = rel
617+ // FindToolsRequiredForBuild returns the list of ToolReleases needed to build for the specified
618+ // plaftorm. The buildPlatform may be different depending on the selected board.
619+ func (pme * Explorer ) FindToolsRequiredForBuild (platform , buildPlatform * cores.PlatformRelease ) ([]* cores.ToolRelease , error ) {
620+
621+ // maps tool name => all available ToolRelease
622+ allToolsAlternatives := map [string ][]* cores.ToolRelease {}
623+ for _ , tool := range pme .GetAllInstalledToolsReleases () {
624+ alternatives := allToolsAlternatives [tool .Tool .Name ]
625+ alternatives = append (alternatives , tool )
626+ allToolsAlternatives [tool .Tool .Name ] = alternatives
627+ }
628+
629+ // selectBest select the tool with best matching, applying the following rules
630+ // in order of priority:
631+ // - the tool comes from the requested packager
632+ // - the tool comes from the build platform packager
633+ // - the tool has the greatest version
634+ // - the tool packager comes first in alphabetic order
635+ packagerPriority := map [string ]int {}
636+ packagerPriority [platform .Platform .Package .Name ] = 2
637+ if buildPlatform != nil {
638+ packagerPriority [buildPlatform .Platform .Package .Name ] = 1
639+ }
640+ selectBest := func (tools []* cores.ToolRelease ) * cores.ToolRelease {
641+ selected := tools [0 ]
642+ for _ , tool := range tools [1 :] {
643+ if packagerPriority [tool .Tool .Package .Name ] != packagerPriority [selected .Tool .Package .Name ] {
644+ if packagerPriority [tool .Tool .Package .Name ] > packagerPriority [selected .Tool .Package .Name ] {
645+ selected = tool
646+ }
647+ continue
648+ }
649+ if ! tool .Version .Equal (selected .Version ) {
650+ if tool .Version .GreaterThan (selected .Version ) {
651+ selected = tool
652+ }
653+ continue
654+ }
655+ if tool .Tool .Package .Name < selected .Tool .Package .Name {
656+ selected = tool
634657 }
635658 }
659+ return selected
636660 }
637661
638- // replace the default tools above with the specific required by the current platform
662+ // First select the specific tools required by the current platform
639663 requiredTools := []* cores.ToolRelease {}
664+ // The Sorting of the tool dependencies is required because some platforms may depends
665+ // on more than one version of the same tool. For example adafruit:samd has both
666+ // bossac@1.8.0-48-gb176eee and bossac@1.7.0. To allow the runtime property
667+ // {runtime.tools.bossac.path} to be correctly set to the 1.8.0 version we must ensure
668+ // that the returned array is sorted by version.
640669 platform .ToolDependencies .Sort ()
641670 for _ , toolDep := range platform .ToolDependencies {
642671 pme .log .WithField ("tool" , toolDep ).Infof ("Required tool" )
@@ -645,11 +674,15 @@ func (pme *Explorer) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.Too
645674 return nil , fmt .Errorf (tr ("tool release not found: %s" ), toolDep )
646675 }
647676 requiredTools = append (requiredTools , tool )
648- delete (foundTools , tool .Tool .Name )
677+ delete (allToolsAlternatives , tool .Tool .Name )
649678 }
650679
651- for _ , toolRel := range foundTools {
652- requiredTools = append (requiredTools , toolRel )
680+ // Since a Platform may not specify the required tools (because it's a platform that comes
681+ // from a user/hardware dir without a package_index.json) then add all available tools giving
682+ // priority to tools coming from the same packager or referenced packager
683+ for _ , tools := range allToolsAlternatives {
684+ tool := selectBest (tools )
685+ requiredTools = append (requiredTools , tool )
653686 }
654687 return requiredTools , nil
655688}
0 commit comments