@@ -618,25 +618,50 @@ 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+ for _ , tool := range tools [1 :] {
639+ if tool .Tool .Package .Name != selected .Tool .Package .Name {
640+ if tool .Tool .Package .Name == packager {
641+ selected = tool
642+ }
643+ continue
644+ }
645+ if ! tool .Version .Equal (selected .Version ) {
646+ if tool .Version .GreaterThan (selected .Version ) {
647+ selected = tool
648+ }
649+ continue
650+ }
651+ if tool .Tool .Package .Name < selected .Tool .Package .Name {
652+ selected = tool
634653 }
635654 }
655+ return selected
636656 }
637657
638- // replace the default tools above with the specific required by the current platform
658+ // First select the specific tools required by the current platform
639659 requiredTools := []* cores.ToolRelease {}
660+ // The Sorting of the tool dependencies is required because some platforms may depends
661+ // on more than one version of the same tool. For example adafruit:samd has both
662+ // [email protected] and [email protected] . To allow the runtime property 663+ // {runtime.tools.bossac.path} to be correctly set to the 1.8.0 version we must ensure
664+ // taht the returned array is sorted by version.
640665 platform .ToolDependencies .Sort ()
641666 for _ , toolDep := range platform .ToolDependencies {
642667 pme .log .WithField ("tool" , toolDep ).Infof ("Required tool" )
@@ -645,11 +670,15 @@ func (pme *Explorer) FindToolsRequiredForBoard(board *cores.Board) ([]*cores.Too
645670 return nil , fmt .Errorf (tr ("tool release not found: %s" ), toolDep )
646671 }
647672 requiredTools = append (requiredTools , tool )
648- delete (foundTools , tool .Tool .Name )
673+ delete (allToolsAlternatives , tool .Tool .Name )
649674 }
650675
651- for _ , toolRel := range foundTools {
652- requiredTools = append (requiredTools , toolRel )
676+ // Since a Platform may not specify the required tools (because it's a platform that comes
677+ // from a user/hardware dir without a package_index.json) then add all available tools giving
678+ // priority to tools coming from the same packager
679+ for _ , tools := range allToolsAlternatives {
680+ tool := selectBest (tools , platform .Platform .Package .Name )
681+ requiredTools = append (requiredTools , tool )
653682 }
654683 return requiredTools , nil
655684}
0 commit comments