@@ -32,6 +32,7 @@ package builder_utils
3232import (
3333 "bytes"
3434 "fmt"
35+ "io"
3536 "os"
3637 "os/exec"
3738 "path/filepath"
@@ -116,6 +117,34 @@ 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+ return sources , nil
146+ }
147+
119148func 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 ) {
120149 for _ , source := range sources {
121150 objectFile , err := compileFileWithRecipe (sourcePath , source , buildPath , buildProperties , includes , recipe , verbose , warningsLevel , logger )
@@ -258,6 +287,28 @@ func nonEmptyString(s string) bool {
258287 return s != constants .EMPTY_STRING
259288}
260289
290+ func CoreOrReferencedCoreHasChanged (corePath , targetCorePath , targetFile string ) bool {
291+
292+ targetFileStat , err := os .Stat (targetFile )
293+ if err == nil {
294+ files , err := findAllFilesInFolder (corePath , true )
295+ if err != nil {
296+ return true
297+ }
298+ for _ , file := range files {
299+ fileStat , err := os .Stat (file )
300+ if err != nil || fileStat .ModTime ().After (targetFileStat .ModTime ()) {
301+ return true
302+ }
303+ }
304+ if targetCorePath != constants .EMPTY_STRING && ! strings .EqualFold (corePath , targetCorePath ) {
305+ return CoreOrReferencedCoreHasChanged (targetCorePath , constants .EMPTY_STRING , targetFile )
306+ }
307+ return false
308+ }
309+ return true
310+ }
311+
261312func ArchiveCompiledFiles (buildPath string , archiveFile string , objectFiles []string , buildProperties properties.Map , verbose bool , logger i18n.Logger ) (string , error ) {
262313 archiveFilePath := filepath .Join (buildPath , archiveFile )
263314
@@ -366,3 +417,59 @@ func ExecRecipeCollectStdErr(buildProperties properties.Map, recipe string, remo
366417func RemoveHyphenMDDFlagFromGCCCommandLine (buildProperties properties.Map ) {
367418 buildProperties [constants .BUILD_PROPERTIES_COMPILER_CPP_FLAGS ] = strings .Replace (buildProperties [constants .BUILD_PROPERTIES_COMPILER_CPP_FLAGS ], "-MMD" , "" , - 1 )
368419}
420+
421+ // CopyFile copies the contents of the file named src to the file named
422+ // by dst. The file will be created if it does not already exist. If the
423+ // destination file exists, all it's contents will be replaced by the contents
424+ // of the source file. The file mode will be copied from the source and
425+ // the copied data is synced/flushed to stable storage.
426+ func CopyFile (src , dst string ) (err error ) {
427+ in , err := os .Open (src )
428+ if err != nil {
429+ return
430+ }
431+ defer in .Close ()
432+
433+ out , err := os .Create (dst )
434+ if err != nil {
435+ return
436+ }
437+ defer func () {
438+ if e := out .Close (); e != nil {
439+ err = e
440+ }
441+ }()
442+
443+ _ , err = io .Copy (out , in )
444+ if err != nil {
445+ return
446+ }
447+
448+ err = out .Sync ()
449+ if err != nil {
450+ return
451+ }
452+
453+ si , err := os .Stat (src )
454+ if err != nil {
455+ return
456+ }
457+ err = os .Chmod (dst , si .Mode ())
458+ if err != nil {
459+ return
460+ }
461+
462+ return
463+ }
464+
465+ // GetCachedCoreArchiveFileName returns the filename to be used to store
466+ // the global cached core.a.
467+ func GetCachedCoreArchiveFileName (fqbn , coreFolder string ) string {
468+ fqbnToUnderscore := strings .Replace (fqbn , ":" , "_" , - 1 )
469+ fqbnToUnderscore = strings .Replace (fqbnToUnderscore , "=" , "_" , - 1 )
470+ if absCoreFolder , err := filepath .Abs (coreFolder ); err == nil {
471+ coreFolder = absCoreFolder
472+ } // silently continue if absolute path can't be detected
473+ hash := utils .MD5Sum ([]byte (coreFolder ))
474+ return "core_" + fqbnToUnderscore + "_" + hash + ".a"
475+ }
0 commit comments