Skip to content

Commit 0e29ec5

Browse files
authored
[breaking] Fix: lib list --fqbn and lib examples --fqbn do not show platform bundled lib when lib of same name is installed globally (arduino#2113)
* Added test * Factored function to determine library compatibility * Made ComputePriority function public * fix: use the libraries resolution algorithm to determine library priority * Slightly refactored 'lib list' command call * Updated UPGRADING.md * Added test for a similar bug in `lib examples` See arduino#1656
1 parent 1ce4abe commit 0e29ec5

File tree

7 files changed

+74
-41
lines changed

7 files changed

+74
-41
lines changed

Diff for: arduino/libraries/libraries.go

+7-15
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ func (library *Library) IsArchitectureIndependent() bool {
181181
return library.IsOptimizedForArchitecture("*") || library.Architectures == nil || len(library.Architectures) == 0
182182
}
183183

184+
// IsCompatibleWith returns true if the library declares compatibility with
185+
// the given architecture. If this function returns false, the library may still
186+
// be compatible with the given architecture, but it's not explicitly declared.
187+
func (library *Library) IsCompatibleWith(arch string) bool {
188+
return library.IsArchitectureIndependent() || library.IsOptimizedForArchitecture(arch)
189+
}
190+
184191
// SourceDir represents a source dir of a library
185192
type SourceDir struct {
186193
Dir *paths.Path
@@ -205,21 +212,6 @@ func (library *Library) SourceDirs() []SourceDir {
205212
return dirs
206213
}
207214

208-
// LocationPriorityFor returns a number representing the location priority for the given library
209-
// using the given platform and referenced-platform. Higher value means higher priority.
210-
func (library *Library) LocationPriorityFor(platformRelease, refPlatformRelease *cores.PlatformRelease) int {
211-
if library.Location == IDEBuiltIn {
212-
return 1
213-
} else if library.ContainerPlatform == refPlatformRelease {
214-
return 2
215-
} else if library.ContainerPlatform == platformRelease {
216-
return 3
217-
} else if library.Location == User {
218-
return 4
219-
}
220-
return 0
221-
}
222-
223215
// DeclaredHeaders returns the C++ headers that the library declares in library.properties
224216
func (library *Library) DeclaredHeaders() []string {
225217
if library.declaredHeaders == nil {

Diff for: arduino/libraries/librariesresolver/cpp.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func (resolver *Cpp) ResolveFor(header, architecture string) *libraries.Library
123123
var found libraries.List
124124
var foundPriority int
125125
for _, lib := range resolver.headers[header] {
126-
libPriority := computePriority(lib, header, architecture)
126+
libPriority := ComputePriority(lib, header, architecture)
127127
msg := " discarded"
128128
if found == nil || foundPriority < libPriority {
129129
found = libraries.List{}
@@ -164,7 +164,10 @@ func simplify(name string) string {
164164
return name
165165
}
166166

167-
func computePriority(lib *libraries.Library, header, arch string) int {
167+
// ComputePriority returns an integer value representing the priority of the library
168+
// for the specified header and architecture. The higher the value, the higher the
169+
// priority.
170+
func ComputePriority(lib *libraries.Library, header, arch string) int {
168171
header = strings.TrimSuffix(header, filepath.Ext(header))
169172
header = simplify(header)
170173
name := simplify(lib.Name)

Diff for: arduino/libraries/librariesresolver/cpp_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ func TestClosestMatchWithTotallyDifferentNames(t *testing.T) {
102102
}
103103

104104
func TestCppHeaderPriority(t *testing.T) {
105-
r1 := computePriority(l1, "calculus_lib.h", "avr")
106-
r2 := computePriority(l2, "calculus_lib.h", "avr")
107-
r3 := computePriority(l3, "calculus_lib.h", "avr")
108-
r4 := computePriority(l4, "calculus_lib.h", "avr")
109-
r5 := computePriority(l5, "calculus_lib.h", "avr")
110-
r6 := computePriority(l6, "calculus_lib.h", "avr")
111-
r7 := computePriority(l7, "calculus_lib.h", "avr")
105+
r1 := ComputePriority(l1, "calculus_lib.h", "avr")
106+
r2 := ComputePriority(l2, "calculus_lib.h", "avr")
107+
r3 := ComputePriority(l3, "calculus_lib.h", "avr")
108+
r4 := ComputePriority(l4, "calculus_lib.h", "avr")
109+
r5 := ComputePriority(l5, "calculus_lib.h", "avr")
110+
r6 := ComputePriority(l6, "calculus_lib.h", "avr")
111+
r7 := ComputePriority(l7, "calculus_lib.h", "avr")
112112
require.True(t, r1 > r2)
113113
require.True(t, r2 > r3)
114114
require.True(t, r3 > r4)

Diff for: commands/lib/list.go

+6-10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/arduino/arduino-cli/arduino/libraries"
2525
"github.com/arduino/arduino-cli/arduino/libraries/librariesindex"
2626
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
27+
"github.com/arduino/arduino-cli/arduino/libraries/librariesresolver"
2728
"github.com/arduino/arduino-cli/commands"
2829
rpc "github.com/arduino/arduino-cli/rpc/cc/arduino/cli/commands/v1"
2930
)
@@ -49,7 +50,7 @@ func LibraryList(ctx context.Context, req *rpc.LibraryListRequest) (*rpc.Library
4950
nameFilter := strings.ToLower(req.GetName())
5051

5152
var allLibs []*installedLib
52-
if f := req.GetFqbn(); f != "" {
53+
if fqbnString := req.GetFqbn(); fqbnString != "" {
5354
allLibs = listLibraries(lm, req.GetUpdatable(), true)
5455
fqbn, err := cores.ParseFQBN(req.GetFqbn())
5556
if err != nil {
@@ -69,22 +70,17 @@ func LibraryList(ctx context.Context, req *rpc.LibraryListRequest) (*rpc.Library
6970
}
7071
}
7172
if latest, has := filteredRes[lib.Library.Name]; has {
72-
if latest.Library.LocationPriorityFor(boardPlatform, refBoardPlatform) >= lib.Library.LocationPriorityFor(boardPlatform, refBoardPlatform) {
73+
latestPriority := librariesresolver.ComputePriority(latest.Library, "", fqbn.PlatformArch)
74+
libPriority := librariesresolver.ComputePriority(lib.Library, "", fqbn.PlatformArch)
75+
if latestPriority >= libPriority {
7376
// Pick library with the best priority
7477
continue
7578
}
7679
}
7780

7881
// Check if library is compatible with board specified by FBQN
79-
compatible := false
80-
for _, arch := range lib.Library.Architectures {
81-
compatible = (arch == fqbn.PlatformArch || arch == "*")
82-
if compatible {
83-
break
84-
}
85-
}
8682
lib.Library.CompatibleWith = map[string]bool{
87-
f: compatible,
83+
fqbnString: lib.Library.IsCompatibleWith(fqbn.PlatformArch),
8884
}
8985

9086
filteredRes[lib.Library.Name] = lib

Diff for: docs/UPGRADING.md

+6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Here you can find a list of migration guides to handle breaking changes between
44

55
## 0.32.0
66

7+
### `arduino-cli` doesn't lookup anymore in the current directory for configuration file.
8+
79
Configuration file lookup in current working directory and its parents is dropped. The command line flag `--config-file`
810
must be specified to use an alternative configuration file from the one in the data directory.
911

@@ -49,6 +51,10 @@ $ arduino-cli outdated --format json
4951
}
5052
```
5153

54+
### golang API: method `github.com/arduino/arduino-cli/arduino/libraries/Library.LocationPriorityFor` removed
55+
56+
That method was outdated and must not be used.
57+
5258
## 0.31.0
5359

5460
### Added `post_install` script support for tools

Diff for: internal/cli/lib/list.go

+3-7
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ not listed, they can be listed by adding the --all flag.`),
4545
Example: " " + os.Args[0] + " lib list",
4646
Args: cobra.MaximumNArgs(1),
4747
Run: func(cmd *cobra.Command, args []string) {
48-
runListCommand(args, all, updatable)
48+
instance := instance.CreateAndInit()
49+
logrus.Info("Executing `arduino-cli lib list`")
50+
List(instance, args, all, updatable)
4951
},
5052
}
5153
listCommand.Flags().BoolVar(&all, "all", false, tr("Include built-in libraries (from platforms and IDE) in listing."))
@@ -54,12 +56,6 @@ not listed, they can be listed by adding the --all flag.`),
5456
return listCommand
5557
}
5658

57-
func runListCommand(args []string, all bool, updatable bool) {
58-
instance := instance.CreateAndInit()
59-
logrus.Info("Executing `arduino-cli lib list`")
60-
List(instance, args, all, updatable)
61-
}
62-
6359
// List gets and prints a list of installed libraries.
6460
func List(instance *rpc.Instance, args []string, all bool, updatable bool) {
6561
installedLibs := GetList(instance, args, all, updatable)

Diff for: internal/integrationtest/lib/lib_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -1547,3 +1547,43 @@ func TestLibQueryParameters(t *testing.T) {
15471547
require.Contains(t, string(stdout),
15481548
"Starting download \x1b[36murl\x1b[0m=\"https://downloads.arduino.cc/libraries/github.com/firmata/Firmata-2.5.9.zip?query=upgrade-builtin\"\n")
15491549
}
1550+
1551+
func TestLibBundlesWhenLibWithTheSameNameIsInstalledGlobally(t *testing.T) {
1552+
env, cli := integrationtest.CreateArduinoCLIWithEnvironment(t)
1553+
defer env.CleanUp()
1554+
1555+
// See: https://github.com/arduino/arduino-cli/issues/1566
1556+
_, _, err := cli.Run("core", "install", "arduino:[email protected]")
1557+
require.NoError(t, err)
1558+
{
1559+
stdout, _, err := cli.Run("lib", "list", "--all", "--fqbn", "arduino:samd:mkrzero", "USBHost", "--format", "json")
1560+
require.NoError(t, err)
1561+
j := requirejson.Parse(t, stdout)
1562+
j.Query(`.[0].library.name`).MustEqual(`"USBHost"`)
1563+
j.Query(`.[0].library.compatible_with."arduino:samd:mkrzero"`).MustEqual(`true`)
1564+
}
1565+
_, _, err = cli.Run("lib", "install", "[email protected]")
1566+
require.NoError(t, err)
1567+
{
1568+
// Check that the architecture-specific library is still listed
1569+
stdout, _, err := cli.Run("lib", "list", "--all", "--fqbn", "arduino:samd:mkrzero", "USBHost", "--format", "json")
1570+
require.NoError(t, err)
1571+
j := requirejson.Parse(t, stdout)
1572+
j.Query(`.[0].library.name`).MustEqual(`"USBHost"`)
1573+
j.Query(`.[0].library.compatible_with."arduino:samd:mkrzero"`).MustEqual(`true`)
1574+
}
1575+
1576+
// See: https://github.com/arduino/arduino-cli/issues/1656
1577+
{
1578+
_, _, err = cli.Run("core", "update-index", "--additional-urls", "https://arduino.esp8266.com/stable/package_esp8266com_index.json")
1579+
require.NoError(t, err)
1580+
_, _, err = cli.Run("core", "install", "--additional-urls", "https://arduino.esp8266.com/stable/package_esp8266com_index.json", "esp8266:[email protected]")
1581+
require.NoError(t, err)
1582+
_, _, err = cli.Run("lib", "install", "[email protected]")
1583+
require.NoError(t, err)
1584+
stdout, _, err := cli.Run("lib", "examples", "--fqbn", "esp8266:esp8266:generic", "ArduinoOTA", "--format", "json")
1585+
require.NoError(t, err)
1586+
requirejson.Parse(t, stdout).Query(`.[].library.examples[0]`).MustContain(`"BasicOTA"`)
1587+
requirejson.Parse(t, stdout).Query(`.[].library.examples[1]`).MustContain(`"OTALeds"`)
1588+
}
1589+
}

0 commit comments

Comments
 (0)