Skip to content

[breaking] Fixed regression in library discovery #1741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions arduino/libraries/librariesresolver/cpp.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"path/filepath"
"strings"

"github.com/arduino/arduino-cli/arduino/cores"
"github.com/arduino/arduino-cli/arduino/libraries"
"github.com/arduino/arduino-cli/arduino/libraries/librariesmanager"
"github.com/arduino/arduino-cli/arduino/utils"
Expand Down Expand Up @@ -53,6 +54,49 @@ func (resolver *Cpp) ScanFromLibrariesManager(lm *librariesmanager.LibrariesMana
return nil
}

// ScanIDEBuiltinLibraries reads ide-builtin librariers loaded in the LibrariesManager to find
// and cache all C++ headers for later retrieval.
func (resolver *Cpp) ScanIDEBuiltinLibraries(lm *librariesmanager.LibrariesManager) error {
for _, libAlternatives := range lm.Libraries {
for _, lib := range libAlternatives.Alternatives {
if lib.Location == libraries.IDEBuiltIn {
resolver.ScanLibrary(lib)
}
}
}
return nil
}

// ScanUserAndUnmanagedLibraries reads user/unmanaged librariers loaded in the LibrariesManager to find
// and cache all C++ headers for later retrieval.
func (resolver *Cpp) ScanUserAndUnmanagedLibraries(lm *librariesmanager.LibrariesManager) error {
for _, libAlternatives := range lm.Libraries {
for _, lib := range libAlternatives.Alternatives {
if lib.Location == libraries.User || lib.Location == libraries.Unmanaged {
resolver.ScanLibrary(lib)
}
}
}
return nil
}

// ScanPlatformLibraries reads platform-bundled libraries for a specific platform loaded in the LibrariesManager
// to find and cache all C++ headers for later retrieval.
func (resolver *Cpp) ScanPlatformLibraries(lm *librariesmanager.LibrariesManager, platform *cores.PlatformRelease) error {
for _, libAlternatives := range lm.Libraries {
for _, lib := range libAlternatives.Alternatives {
if lib.Location != libraries.PlatformBuiltIn && lib.Location != libraries.ReferencedPlatformBuiltIn {
continue
}
if lib.ContainerPlatform != platform {
continue
}
resolver.ScanLibrary(lib)
}
}
return nil
}

// ScanLibrary reads a library to find and cache C++ headers for later retrieval
func (resolver *Cpp) ScanLibrary(lib *libraries.Library) error {
cppHeaders, err := lib.SourceHeaders()
Expand Down
21 changes: 15 additions & 6 deletions legacy/builder/libraries_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,10 @@ func (s *LibrariesLoader) Run(ctx *types.Context) error {
lm.AddLibrariesDir(folder, libraries.IDEBuiltIn)
}

actualPlatform := ctx.ActualPlatform
platform := ctx.TargetPlatform
if actualPlatform != platform {
lm.AddPlatformReleaseLibrariesDir(actualPlatform, libraries.ReferencedPlatformBuiltIn)
if ctx.ActualPlatform != ctx.TargetPlatform {
lm.AddPlatformReleaseLibrariesDir(ctx.ActualPlatform, libraries.ReferencedPlatformBuiltIn)
}
lm.AddPlatformReleaseLibrariesDir(platform, libraries.PlatformBuiltIn)
lm.AddPlatformReleaseLibrariesDir(ctx.TargetPlatform, libraries.PlatformBuiltIn)

librariesFolders := ctx.OtherLibrariesDirs
if err := librariesFolders.ToAbs(); err != nil {
Expand Down Expand Up @@ -72,9 +70,20 @@ func (s *LibrariesLoader) Run(ctx *types.Context) error {
}

resolver := librariesresolver.NewCppResolver()
if err := resolver.ScanFromLibrariesManager(ctx.LibrariesManager); err != nil {
if err := resolver.ScanIDEBuiltinLibraries(ctx.LibrariesManager); err != nil {
return errors.WithStack(err)
}
if err := resolver.ScanUserAndUnmanagedLibraries(ctx.LibrariesManager); err != nil {
return errors.WithStack(err)
}
if err := resolver.ScanPlatformLibraries(ctx.LibrariesManager, ctx.TargetPlatform); err != nil {
return errors.WithStack(err)
}
if ctx.ActualPlatform != ctx.TargetPlatform {
if err := resolver.ScanPlatformLibraries(ctx.LibrariesManager, ctx.ActualPlatform); err != nil {
return errors.WithStack(err)
}
}
ctx.LibrariesResolver = resolver

return nil
Expand Down
19 changes: 19 additions & 0 deletions test/test_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,22 @@ def test_compile_with_profiles(run_command, copy_sketch):
# use profile with the required library -> should succeed
result = run_command(["compile", "-m", "avr2", sketch_path])
assert result.ok


def test_builder_did_not_catch_libs_from_unused_platforms(run_command, copy_sketch):
# Init the environment explicitly
run_command(["core", "update-index"])

sketch_path = copy_sketch("sketch_with_error_including_wire")

# install two platforms with the Wire library bundled
assert run_command(["core", "install", "arduino:avr"])
assert run_command(["core", "install", "arduino:samd"])

# compile for AVR
result = run_command(["compile", "-b", "arduino:avr:uno", sketch_path])
assert result.failed

# check that the libary resolver did not take the SAMD bundled Wire library into account
assert "samd" not in result.stdout
assert "samd" not in result.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include <Wire.h>

this sketch has syntax errors