Skip to content

Commit ae68728

Browse files
authored
Auto-import libraries based on sketch profile. (#2951)
* Moved Result structure into his own package This change is preparatory for next refactorings * Moving sourceFile object in his own file * Moved uniqueSourceFileQueue in his own file * Moved includeCache in his own file and made it a field of detector * Fixed comment * Renamed variable (typo) * Simplified handling of de-duplication of cache hit messages This equivalent change moves the 'first' variable closer to his definition and use. * Implemented a better include-cache * Remove the old, no longer used, includeCache * Refactored function it will be useful in the next commits. * Always add to the build the libraries requested in the active sketch profile. This will improve sketch compile time. * Fixed result conversion. * Ensure stable ordering when libraries are auto-included This avoid cache invalidation if recompiled.
1 parent f1621b4 commit ae68728

File tree

14 files changed

+390
-351
lines changed

14 files changed

+390
-351
lines changed

commands/instances.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ func (s *arduinoCoreServerImpl) Init(req *rpc.InitRequest, stream rpc.ArduinoCor
380380
}
381381
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
382382
Path: libDir,
383-
Location: libraries.Unmanaged,
383+
Location: libraries.Profile,
384384
IsSingleLibrary: true,
385385
})
386386
continue
@@ -428,7 +428,7 @@ func (s *arduinoCoreServerImpl) Init(req *rpc.InitRequest, stream rpc.ArduinoCor
428428

429429
lmb.AddLibrariesDir(librariesmanager.LibrariesDir{
430430
Path: libRoot,
431-
Location: libraries.User,
431+
Location: libraries.Profile,
432432
})
433433
}
434434
}

commands/service_compile.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,11 @@ func (s *arduinoCoreServerImpl) Compile(req *rpc.CompileRequest, stream rpc.Ardu
105105
return &cmderrors.CantOpenSketchError{Cause: err}
106106
}
107107

108+
profile := pme.GetProfile()
108109
fqbnIn := req.GetFqbn()
109110
if fqbnIn == "" && sk != nil {
110-
if pme.GetProfile() != nil {
111-
fqbnIn = pme.GetProfile().FQBN
111+
if profile != nil {
112+
fqbnIn = profile.FQBN
112113
} else {
113114
fqbnIn = sk.GetDefaultFQBN()
114115
}
@@ -224,7 +225,7 @@ func (s *arduinoCoreServerImpl) Compile(req *rpc.CompileRequest, stream rpc.Ardu
224225
otherLibrariesDirs.Add(s.settings.LibrariesDir())
225226

226227
var libsManager *librariesmanager.LibrariesManager
227-
if pme.GetProfile() != nil {
228+
if profile != nil {
228229
libsManager = lm
229230
}
230231

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// This file is part of arduino-cli.
2+
//
3+
// Copyright 2024 ARDUINO SA (http://www.arduino.cc/)
4+
//
5+
// This software is released under the GNU General Public License version 3,
6+
// which covers the main part of arduino-cli.
7+
// The terms of this license can be found at:
8+
// https://www.gnu.org/licenses/gpl-3.0.en.html
9+
//
10+
// You can be released from the requirements of the above licenses by purchasing
11+
// a commercial license. Buying such a license is mandatory if you want to
12+
// modify or otherwise use the software for commercial activities involving the
13+
// Arduino software without disclosing the source code of your own applications.
14+
// To purchase a commercial license, send an email to [email protected].
15+
16+
package detector
17+
18+
import (
19+
"encoding/json"
20+
"fmt"
21+
22+
"github.com/arduino/go-paths-helper"
23+
)
24+
25+
type detectorCache struct {
26+
curr int
27+
entries []*detectorCacheEntry
28+
}
29+
30+
type detectorCacheEntry struct {
31+
AddedIncludePath *paths.Path `json:"added_include_path,omitempty"`
32+
CompilingSourcePath *paths.Path `json:"compiling_source_path,omitempty"`
33+
MissingIncludeH *string `json:"missing_include_h,omitempty"`
34+
}
35+
36+
func (e *detectorCacheEntry) String() string {
37+
if e.AddedIncludePath != nil {
38+
return "Added include path: " + e.AddedIncludePath.String()
39+
}
40+
if e.CompilingSourcePath != nil {
41+
return "Compiling source path: " + e.CompilingSourcePath.String()
42+
}
43+
if e.MissingIncludeH != nil {
44+
if *e.MissingIncludeH == "" {
45+
return "No missing include files detected"
46+
}
47+
return "Missing include file: " + *e.MissingIncludeH
48+
}
49+
return "No operation"
50+
}
51+
52+
func (e *detectorCacheEntry) Equals(entry *detectorCacheEntry) bool {
53+
return e.String() == entry.String()
54+
}
55+
56+
func newDetectorCache() *detectorCache {
57+
return &detectorCache{}
58+
}
59+
60+
func (c *detectorCache) String() string {
61+
res := ""
62+
for _, entry := range c.entries {
63+
res += fmt.Sprintln(entry)
64+
}
65+
return res
66+
}
67+
68+
// Load reads a saved cache from the given file.
69+
// If the file do not exists, it does nothing.
70+
func (c *detectorCache) Load(cacheFile *paths.Path) error {
71+
if exist, err := cacheFile.ExistCheck(); err != nil {
72+
return err
73+
} else if !exist {
74+
return nil
75+
}
76+
data, err := cacheFile.ReadFile()
77+
if err != nil {
78+
return err
79+
}
80+
var entries []*detectorCacheEntry
81+
if err := json.Unmarshal(data, &entries); err != nil {
82+
return err
83+
}
84+
c.curr = 0
85+
c.entries = entries
86+
return nil
87+
}
88+
89+
// Expect adds an entry to the cache and checks if it matches the next expected entry.
90+
func (c *detectorCache) Expect(entry *detectorCacheEntry) {
91+
if c.curr < len(c.entries) {
92+
if c.entries[c.curr].Equals(entry) {
93+
// Cache hit, move to the next entry
94+
c.curr++
95+
return
96+
}
97+
// Cache mismatch, invalidate and cut the remainder of the cache
98+
c.entries = c.entries[:c.curr]
99+
}
100+
c.curr++
101+
c.entries = append(c.entries, entry)
102+
}
103+
104+
// Peek returns the next cache entry to be expected or nil if the cache is fully consumed.
105+
func (c *detectorCache) Peek() *detectorCacheEntry {
106+
if c.curr < len(c.entries) {
107+
return c.entries[c.curr]
108+
}
109+
return nil
110+
}
111+
112+
// Save writes the current cache to the given file.
113+
func (c *detectorCache) Save(cacheFile *paths.Path) error {
114+
// Cut off the cache if it is not fully consumed
115+
c.entries = c.entries[:c.curr]
116+
117+
data, err := json.MarshalIndent(c.entries, "", " ")
118+
if err != nil {
119+
return err
120+
}
121+
return cacheFile.WriteFile(data)
122+
}

0 commit comments

Comments
 (0)