@@ -618,25 +618,51 @@ func (pme *Explorer) GetTool(toolID string) *cores.Tool {
618618func (pme * Explorer ) FindToolsRequiredForBoard (board * cores.Board ) ([]* cores.ToolRelease , error ) {
619619 pme .log .Infof ("Searching tools required for board %s" , board )
620620
621- // core := board.Properties["build.core"]
622621 platform := board .PlatformRelease
623622
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
623+ // maps tool name => all available ToolRelease
624+ allToolsAlternatives := map [string ][]* cores.ToolRelease {}
625+ for _ , tool := range pme .GetAllInstalledToolsReleases () {
626+ alternatives := allToolsAlternatives [tool .Tool .Name ]
627+ alternatives = append (alternatives , tool )
628+ allToolsAlternatives [tool .Tool .Name ] = alternatives
629+ }
630+
631+ // selectBest select the tool with best matching, applying the following rules
632+ // in order of priority:
633+ // - the tool comes from the requested packager
634+ // - the tool has the greatest version
635+ // - the tool packager comes first in alphabetic order
636+ selectBest := func (tools []* cores.ToolRelease , packager string ) * cores.ToolRelease {
637+ selected := tools [0 ]
638+ namePriority := map [string ]int {packager : 1 }
639+ for _ , tool := range tools [1 :] {
640+ if namePriority [tool .Tool .Package .Name ] != namePriority [selected .Tool .Package .Name ] {
641+ if namePriority [tool .Tool .Package .Name ] > namePriority [selected .Tool .Package .Name ] {
642+ selected = tool
643+ }
644+ continue
645+ }
646+ if ! tool .Version .Equal (selected .Version ) {
647+ if tool .Version .GreaterThan (selected .Version ) {
648+ selected = tool
649+ }
650+ continue
651+ }
652+ if tool .Tool .Package .Name < selected .Tool .Package .Name {
653+ selected = tool
634654 }
635655 }
656+ return selected
636657 }
637658
638- // replace the default tools above with the specific required by the current platform
659+ // First select the specific tools required by the current platform
639660 requiredTools := []* cores.ToolRelease {}
661+ // The Sorting of the tool dependencies is required because some platforms may depends
662+ // on more than one version of the same tool. For example adafruit:samd has both
663+ // [email protected] and [email protected] . To allow the runtime property 664+ // {runtime.tools.bossac.path} to be correctly set to the 1.8.0 version we must ensure
665+ // taht the returned array is sorted by version.
640666 platform .ToolDependencies .Sort ()
641667 for _ , toolDep := range platform .ToolDependencies {
642668 pme .log .WithField ("tool" , toolDep ).Infof ("Required tool" )
@@ -645,11 +671,15 @@ func (pme *Explorer) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.Too
645671 return nil , fmt .Errorf (tr ("tool release not found: %s" ), toolDep )
646672 }
647673 requiredTools = append (requiredTools , tool )
648- delete (foundTools , tool .Tool .Name )
674+ delete (allToolsAlternatives , tool .Tool .Name )
649675 }
650676
651- for _ , toolRel := range foundTools {
652- requiredTools = append (requiredTools , toolRel )
677+ // Since a Platform may not specify the required tools (because it's a platform that comes
678+ // from a user/hardware dir without a package_index.json) then add all available tools giving
679+ // priority to tools coming from the same packager
680+ for _ , tools := range allToolsAlternatives {
681+ tool := selectBest (tools , platform .Platform .Package .Name )
682+ requiredTools = append (requiredTools , tool )
653683 }
654684 return requiredTools , nil
655685}
0 commit comments