Skip to content

Commit c2678cf

Browse files
facchinmcmaglie
andcommitted
Reuse (cache) object archives in large sketch projects (arduino#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 <[email protected]>
1 parent 77222ec commit c2678cf

File tree

8 files changed

+40
-35
lines changed

8 files changed

+40
-35
lines changed

Diff for: .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

Diff for: 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))

Diff for: 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
}

Diff for: 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
}

Diff for: 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

Diff for: 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

Diff for: 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=

Diff for: 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)