Skip to content

Commit 55a11b0

Browse files
committed
[WIP] Archive compiled core and use in any compatible project
1 parent bc2c38f commit 55a11b0

File tree

5 files changed

+141
-0
lines changed

5 files changed

+141
-0
lines changed

src/arduino.cc/builder/builder_utils/utils.go

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ package builder_utils
3232
import (
3333
"bytes"
3434
"fmt"
35+
"io"
3536
"os"
3637
"os/exec"
3738
"path/filepath"
@@ -116,6 +117,36 @@ func findFilesInFolder(sourcePath string, extension string, recurse bool) ([]str
116117
return sources, nil
117118
}
118119

120+
func findAllFilesInFolder(sourcePath string, recurse bool) ([]string, error) {
121+
files, err := utils.ReadDirFiltered(sourcePath, utils.FilterFiles())
122+
if err != nil {
123+
return nil, i18n.WrapError(err)
124+
}
125+
var sources []string
126+
for _, file := range files {
127+
sources = append(sources, filepath.Join(sourcePath, file.Name()))
128+
}
129+
130+
if recurse {
131+
folders, err := utils.ReadDirFiltered(sourcePath, utils.FilterDirs)
132+
if err != nil {
133+
return nil, i18n.WrapError(err)
134+
}
135+
136+
for _, folder := range folders {
137+
otherSources, err := findAllFilesInFolder(filepath.Join(sourcePath, folder.Name()), recurse)
138+
if err != nil {
139+
return nil, i18n.WrapError(err)
140+
}
141+
sources = append(sources, otherSources...)
142+
}
143+
}
144+
145+
fmt.Println(sources)
146+
147+
return sources, nil
148+
}
149+
119150
func compileFilesWithRecipe(objectFiles []string, sourcePath string, sources []string, buildPath string, buildProperties properties.Map, includes []string, recipe string, verbose bool, warningsLevel string, logger i18n.Logger) ([]string, error) {
120151
for _, source := range sources {
121152
objectFile, err := compileFileWithRecipe(sourcePath, source, buildPath, buildProperties, includes, recipe, verbose, warningsLevel, logger)
@@ -258,6 +289,24 @@ func nonEmptyString(s string) bool {
258289
return s != constants.EMPTY_STRING
259290
}
260291

292+
func CheckIfRecompileIsAvoidable(corePath string, archiveFile string) bool {
293+
archiveFileStat, err := os.Stat(archiveFile)
294+
if err == nil {
295+
files, err := findAllFilesInFolder(corePath, true)
296+
if err != nil {
297+
return false
298+
}
299+
for _, file := range files {
300+
fileStat, err := os.Stat(file)
301+
if err != nil || fileStat.ModTime().After(archiveFileStat.ModTime()) {
302+
return false
303+
}
304+
}
305+
return true
306+
}
307+
return false
308+
}
309+
261310
func ArchiveCompiledFiles(buildPath string, archiveFile string, objectFiles []string, buildProperties properties.Map, verbose bool, logger i18n.Logger) (string, error) {
262311
archiveFilePath := filepath.Join(buildPath, archiveFile)
263312

@@ -366,3 +415,67 @@ func ExecRecipeCollectStdErr(buildProperties properties.Map, recipe string, remo
366415
func RemoveHyphenMDDFlagFromGCCCommandLine(buildProperties properties.Map) {
367416
buildProperties[constants.BUILD_PROPERTIES_COMPILER_CPP_FLAGS] = strings.Replace(buildProperties[constants.BUILD_PROPERTIES_COMPILER_CPP_FLAGS], "-MMD", "", -1)
368417
}
418+
419+
// CopyFile copies a file from src to dst. If src and dst files exist, and are
420+
// the same, then return success. Otherise, attempt to create a hard link
421+
// between the two files. If that fail, copy the file contents from src to dst.
422+
func CopyFile(src, dst string) (err error) {
423+
sfi, err := os.Stat(src)
424+
if err != nil {
425+
return
426+
}
427+
if !sfi.Mode().IsRegular() {
428+
// cannot copy non-regular files (e.g., directories,
429+
// symlinks, devices, etc.)
430+
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
431+
}
432+
dfi, err := os.Stat(dst)
433+
if err != nil {
434+
if !os.IsNotExist(err) {
435+
return
436+
}
437+
} else {
438+
if !(dfi.Mode().IsRegular()) {
439+
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
440+
}
441+
if os.SameFile(sfi, dfi) {
442+
return
443+
}
444+
}
445+
if err = os.Link(src, dst); err == nil {
446+
return
447+
}
448+
err = copyFileContents(src, dst)
449+
return
450+
}
451+
452+
// copyFileContents copies the contents of the file named src to the file named
453+
// by dst. The file will be created if it does not already exist. If the
454+
// destination file exists, all it's contents will be replaced by the contents
455+
// of the source file.
456+
func copyFileContents(src, dst string) (err error) {
457+
in, err := os.Open(src)
458+
if err != nil {
459+
return
460+
}
461+
defer in.Close()
462+
out, err := os.Create(dst)
463+
if err != nil {
464+
return
465+
}
466+
defer func() {
467+
cerr := out.Close()
468+
if err == nil {
469+
err = cerr
470+
}
471+
}()
472+
if _, err = io.Copy(out, in); err != nil {
473+
return
474+
}
475+
err = out.Sync()
476+
return
477+
}
478+
479+
func GetCoreArchivePath(fqbnToUnderscore string) string {
480+
return os.TempDir() + "/core_" + fqbnToUnderscore + ".a"
481+
}

src/arduino.cc/builder/constants/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ const BUILD_PROPERTIES_EXTRA_TIME_DST = "extra.time.dst"
5555
const BUILD_PROPERTIES_EXTRA_TIME_LOCAL = "extra.time.local"
5656
const BUILD_PROPERTIES_EXTRA_TIME_UTC = "extra.time.utc"
5757
const BUILD_PROPERTIES_EXTRA_TIME_ZONE = "extra.time.zone"
58+
const BUILD_PROPERTIES_FQBN = "build.fqbn"
5859
const BUILD_PROPERTIES_INCLUDES = "includes"
5960
const BUILD_PROPERTIES_OBJECT_FILE = "object_file"
6061
const BUILD_PROPERTIES_OBJECT_FILES = "object_files"

src/arduino.cc/builder/phases/core_builder.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,17 @@ func compileCore(buildPath string, buildProperties properties.Map, verbose bool,
8484
}
8585
}
8686

87+
targetArchivedCore := builder_utils.GetCoreArchivePath(buildProperties[constants.BUILD_PROPERTIES_FQBN])
88+
noNeedToRecompile := builder_utils.CheckIfRecompileIsAvoidable(coreFolder, targetArchivedCore)
89+
90+
if noNeedToRecompile {
91+
// use archived core
92+
if verbose {
93+
logger.Println(constants.LOG_LEVEL_INFO, "Using precompiled core")
94+
}
95+
return targetArchivedCore, variantObjectFiles, nil
96+
}
97+
8798
coreObjectFiles, err := builder_utils.CompileFiles([]string{}, coreFolder, true, buildPath, buildProperties, includes, verbose, warningsLevel, logger)
8899
if err != nil {
89100
return "", nil, i18n.WrapError(err)
@@ -94,5 +105,8 @@ func compileCore(buildPath string, buildProperties properties.Map, verbose bool,
94105
return "", nil, i18n.WrapError(err)
95106
}
96107

108+
// archive core.a
109+
builder_utils.CopyFile(archiveFile, targetArchivedCore)
110+
97111
return archiveFile, variantObjectFiles, nil
98112
}

src/arduino.cc/builder/setup_build_properties.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func (s *SetupBuildProperties) Run(ctx *types.Context) error {
7070
buildProperties[constants.BUILD_PROPERTIES_RUNTIME_PLATFORM_PATH] = targetPlatform.Folder
7171
buildProperties[constants.BUILD_PROPERTIES_RUNTIME_HARDWARE_PATH] = filepath.Join(targetPlatform.Folder, "..")
7272
buildProperties[constants.BUILD_PROPERTIES_RUNTIME_IDE_VERSION] = ctx.ArduinoAPIVersion
73+
buildProperties[constants.BUILD_PROPERTIES_FQBN] = strings.Replace(ctx.FQBN, ":", "_", -1)
7374
buildProperties[constants.IDE_VERSION] = ctx.ArduinoAPIVersion
7475
buildProperties[constants.BUILD_PROPERTIES_RUNTIME_OS] = utils.PrettyOSName()
7576

src/arduino.cc/builder/utils/utils.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,18 @@ func FilterFilesWithExtensions(extensions ...string) filterFiles {
150150
}
151151
}
152152

153+
func FilterFiles() filterFiles {
154+
return func(files []os.FileInfo) []os.FileInfo {
155+
var filtered []os.FileInfo
156+
for _, file := range files {
157+
if !file.IsDir() {
158+
filtered = append(filtered, file)
159+
}
160+
}
161+
return filtered
162+
}
163+
}
164+
153165
var SOURCE_CONTROL_FOLDERS = map[string]bool{"CVS": true, "RCS": true, ".git": true, ".github": true, ".svn": true, ".hg": true, ".bzr": true, ".vscode": true}
154166

155167
func IsSCCSOrHiddenFile(file os.FileInfo) bool {

0 commit comments

Comments
 (0)