Skip to content

Commit c2678cf

Browse files
facchinmcmaglie
andcommitted
Reuse (cache) object archives in large sketch projects (#2464)
* Reuse archiveCompiledFiles helper for long commandline shrink Since archiveCompiledFiles already handles hot cache correctly, this avoids objs.a being rebuilt even if files don't change. Would be ideal if PathList could expose a generic Filter API (to get rid of the "duplicated" filter) * Upgrade go-paths / remove duplicate filter function * Consider existing archives during the build * Simplified archiveCompiledFiles function signature It doesn't make sense anymore to keep path and filename separated. * Added integration test --------- Co-authored-by: Cristian Maglie <c.maglie@arduino.cc>
1 parent 77222ec commit c2678cf

File tree

8 files changed

+40
-35
lines changed

8 files changed

+40
-35
lines changed

.licenses/go/github.com/arduino/go-paths-helper.dep.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
name: github.com/arduino/go-paths-helper
3-
version: v1.9.2
3+
version: v1.11.0
44
type: go
55
summary:
66
homepage: https://pkg.go.dev/github.com/arduino/go-paths-helper

arduino/builder/archive_compiled_files.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ import (
2121
)
2222

2323
// ArchiveCompiledFiles fixdoc
24-
func (b *Builder) archiveCompiledFiles(buildPath *paths.Path, archiveFile *paths.Path, objectFilesToArchive paths.PathList) (*paths.Path, error) {
25-
archiveFilePath := buildPath.JoinPath(archiveFile)
26-
24+
func (b *Builder) archiveCompiledFiles(archiveFilePath *paths.Path, objectFilesToArchive paths.PathList) (*paths.Path, error) {
2725
if b.onlyUpdateCompilationDatabase {
2826
if b.logger.Verbose() {
2927
b.logger.Info(tr("Skipping archive creation of: %[1]s", archiveFilePath))

arduino/builder/core.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (b *Builder) compileCore() (*paths.Path, paths.PathList, error) {
128128
return nil, nil, errors.WithStack(err)
129129
}
130130

131-
archiveFile, err := b.archiveCompiledFiles(b.coreBuildPath, paths.New("core.a"), coreObjectFiles)
131+
archiveFile, err := b.archiveCompiledFiles(b.coreBuildPath.Join("core.a"), coreObjectFiles)
132132
if err != nil {
133133
return nil, nil, errors.WithStack(err)
134134
}

arduino/builder/libraries.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func (b *Builder) compileLibrary(library *libraries.Library, includes []string)
197197
return nil, errors.WithStack(err)
198198
}
199199
if library.DotALinkage {
200-
archiveFile, err := b.archiveCompiledFiles(libraryBuildPath, paths.New(library.DirName+".a"), libObjectFiles)
200+
archiveFile, err := b.archiveCompiledFiles(libraryBuildPath.Join(library.DirName+".a"), libObjectFiles)
201201
if err != nil {
202202
return nil, errors.WithStack(err)
203203
}

arduino/builder/linker.go

+21-24
Original file line numberDiff line numberDiff line change
@@ -54,34 +54,31 @@ func (b *Builder) link() error {
5454
// it may happen that a subdir/spi.o inside the archive may be overwritten by a anotherdir/spi.o
5555
// because thery are both named spi.o.
5656

57-
properties := b.buildProperties.Clone()
58-
archives := paths.NewPathList()
57+
// Put all the existing archives apart from the other object files
58+
existingArchives := objectFiles.Clone()
59+
existingArchives.FilterSuffix(".a")
60+
objectFiles.FilterOutSuffix(".a")
61+
62+
// Generate an archive for each directory from the remaining object files
63+
newArchives := paths.NewPathList()
5964
for _, object := range objectFiles {
60-
if object.HasSuffix(".a") {
61-
archives.Add(object)
62-
continue
63-
}
6465
archive := object.Parent().Join("objs.a")
65-
if !archives.Contains(archive) {
66-
archives.Add(archive)
67-
// Cleanup old archives
68-
_ = archive.Remove()
69-
}
70-
properties.Set("archive_file", archive.Base())
71-
properties.SetPath("archive_file_path", archive)
72-
properties.SetPath("object_file", object)
73-
74-
command, err := b.prepareCommandForRecipe(properties, "recipe.ar.pattern", false)
75-
if err != nil {
76-
return errors.WithStack(err)
77-
}
78-
79-
if err := b.execCommand(command); err != nil {
80-
return errors.WithStack(err)
81-
}
66+
newArchives.AddIfMissing(archive)
67+
}
68+
for _, archive := range newArchives {
69+
archiveDir := archive.Parent()
70+
relatedObjectFiles := objectFiles.Clone()
71+
relatedObjectFiles.Filter(func(object *paths.Path) bool {
72+
// extract all the object files that are in the same directory of the archive
73+
return object.Parent().EquivalentTo(archiveDir)
74+
})
75+
b.archiveCompiledFiles(archive, relatedObjectFiles)
8276
}
8377

84-
objectFileList = strings.Join(f.Map(archives.AsStrings(), wrapWithDoubleQuotes), " ")
78+
// Put everything together
79+
allArchives := existingArchives.Clone()
80+
allArchives.AddAll(newArchives)
81+
objectFileList = strings.Join(f.Map(allArchives.AsStrings(), wrapWithDoubleQuotes), " ")
8582
objectFileList = "-Wl,--whole-archive " + objectFileList + " -Wl,--no-whole-archive"
8683
}
8784

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ replace github.com/mailru/easyjson => github.com/cmaglie/easyjson v0.8.1
77

88
require (
99
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371
10-
github.com/arduino/go-paths-helper v1.9.2
10+
github.com/arduino/go-paths-helper v1.11.0
1111
github.com/arduino/go-properties-orderedmap v1.8.0
1212
github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b
1313
github.com/arduino/go-win32-utils v1.0.0

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ
5151
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
5252
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
5353
github.com/arduino/go-paths-helper v1.0.1/go.mod h1:HpxtKph+g238EJHq4geEPv9p+gl3v5YYu35Yb+w31Ck=
54-
github.com/arduino/go-paths-helper v1.9.2 h1:omR8DPTL4nbUCWfGey5D+e3WvWfA2zEgoM6ZBRNt7ls=
55-
github.com/arduino/go-paths-helper v1.9.2/go.mod h1:V82BWgAAp4IbmlybxQdk9Bpkz8M4Qyx+RAFKaG9NuvU=
54+
github.com/arduino/go-paths-helper v1.11.0 h1:hkpGb9AtCTByTj2FKutuHWb3klDf4kAKL10hW+fN+oE=
55+
github.com/arduino/go-paths-helper v1.11.0/go.mod h1:jcpW4wr0u69GlXhTYydsdsqAjLaYK5n7oWHfKqOG6LM=
5656
github.com/arduino/go-properties-orderedmap v1.8.0 h1:wEfa6hHdpezrVOh787OmClsf/Kd8qB+zE3P2Xbrn0CQ=
5757
github.com/arduino/go-properties-orderedmap v1.8.0/go.mod h1:DKjD2VXY/NZmlingh4lSFMEYCVubfeArCsGPGDwb2yk=
5858
github.com/arduino/go-timeutils v0.0.0-20171220113728-d1dd9e313b1b h1:9hDi4F2st6dbLC3y4i02zFT5quS4X6iioWifGlVwfy4=

internal/integrationtest/compile_1/compile_test.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"encoding/json"
2222
"fmt"
2323
"os"
24+
"regexp"
2425
"sort"
2526
"strings"
2627
"testing"
@@ -830,8 +831,17 @@ func TestCompileWithArchivesAndLongPaths(t *testing.T) {
830831
sketchPath := paths.New(libOutput[0]["library"].(map[string]interface{})["install_dir"].(string))
831832
sketchPath = sketchPath.Join("examples", "ArduinoIoTCloud-Advanced")
832833

833-
_, _, err = cli.Run("compile", "-b", "esp8266:esp8266:huzzah", sketchPath.String(), "--config-file", "arduino-cli.yaml")
834-
require.NoError(t, err)
834+
t.Run("Compile", func(t *testing.T) {
835+
_, _, err = cli.Run("compile", "-b", "esp8266:esp8266:huzzah", sketchPath.String(), "--config-file", "arduino-cli.yaml")
836+
require.NoError(t, err)
837+
})
838+
839+
t.Run("CheckCachingOfFolderArchives", func(t *testing.T) {
840+
// Run compile again and check if the archive is re-used (cached)
841+
out, _, err := cli.Run("compile", "-b", "esp8266:esp8266:huzzah", sketchPath.String(), "--config-file", "arduino-cli.yaml", "-v")
842+
require.NoError(t, err)
843+
require.True(t, regexp.MustCompile(`(?m)^Using previously compiled file:.*libraries.ArduinoIoTCloud.objs\.a$`).Match(out))
844+
})
835845
}
836846

837847
func TestCompileWithPrecompileLibrary(t *testing.T) {

0 commit comments

Comments
 (0)