diff --git a/internal/base/Optional.go b/internal/base/Optional.go index 4c1460f..6f5b290 100644 --- a/internal/base/Optional.go +++ b/internal/base/Optional.go @@ -43,6 +43,12 @@ func (x Optional[T]) GetOrElse(orElse T) T { return orElse } } +func (x *Optional[T]) WhatIf(cond func(*T) error) error { + if x.err == nil { + return cond(&x.value) + } + return nil +} func SetOptional[T any, E interface { *T diff --git a/internal/base/SerializableHelpers.go b/internal/base/SerializableHelpers.go index 540e97e..664b2ed 100644 --- a/internal/base/SerializableHelpers.go +++ b/internal/base/SerializableHelpers.go @@ -22,6 +22,12 @@ func (x *Regexp) Set(in string) (err error) { x.Regexp, err = regexp.Compile(in) return } +func (x Regexp) String() string { + if x.Regexp != nil { + return x.Regexp.String() + } + return "" +} func (x *Regexp) MarshalText() ([]byte, error) { return UnsafeBytesFromString(x.String()), nil } diff --git a/internal/hal/generic/ExternalSDK.go b/internal/hal/generic/ExternalSDK.go index b39987a..f910fa2 100644 --- a/internal/hal/generic/ExternalSDK.go +++ b/internal/hal/generic/ExternalSDK.go @@ -76,10 +76,12 @@ func (x ExternalSDKHeaderGenerator) CreateGenerated(unit *compile.Unit, output u return nil, err } - // Archive + // Archive from local filesystem if err := setOptionalSdkParam(unit, "SDK/ArchiveFile", &result.ArchiveFile); err != nil { return nil, err } + + // Archive from remote url if err := setOptionalSdkParam(unit, "SDK/ArchiveURL", &result.ArchiveURL); err != nil { return nil, err } @@ -87,15 +89,6 @@ func (x ExternalSDKHeaderGenerator) CreateGenerated(unit *compile.Unit, output u return nil, err } - // construct absolute path from relative dirname provided (or not in the configuration) - var extractDirname base.Optional[base.InheritableString] - if err := setOptionalSdkParam(unit, "SDK/ExtractDirname", &extractDirname); err != nil { - return nil, err - } - if relativeDirname, err := extractDirname.Get(); err == nil { - result.ExtractDir = base.NewOption(unit.ModuleDir.AbsoluteFolder(relativeDirname.Get())) - } - // Headers/Libraries if err := setOptionalSdkParam(unit, "SDK/Headers", &result.Headers); err != nil { return nil, err @@ -110,6 +103,15 @@ func (x ExternalSDKHeaderGenerator) CreateGenerated(unit *compile.Unit, output u return nil, err } + // Construct absolute path from relative dirname provided (or not in the configuration) + var extractDirname base.Optional[base.InheritableString] + if err := setOptionalSdkParam(unit, "SDK/ExtractDirname", &extractDirname); err != nil { + return nil, err + } + if relativeDirname, err := extractDirname.Get(); err == nil { + result.ExtractDir = base.NewOption(unit.ModuleDir.AbsoluteFolder(relativeDirname.Get()).Normalize()) + } + // Relative include sub-directory in external SDK (defaults to "./include/") if err := setOptionalSdkParam(unit, "SDK/IncludeDirname", &result.IncludeDirname); err != nil { return nil, err @@ -184,7 +186,16 @@ func (x *ExternalSDKGeneratedHeader) prepareSDKDir(bc utils.BuildContext) (utils base.LogVerbose(LogExternalSDK, "%s: using external directory %q for external SDK", x.SDKName, sdkDir) // External SDK stored at designated location - sdkFiles, err := internal_io.ListDirectory(bc, sdkDir) + sdkFiles, err := internal_io.MatchDirectory(bc, sdkDir, + base.Regexp{}, base.Regexp{}, utils.FileSet{}) + + if err == nil { + acceptListRe := x.getArchiveAcceptList() + sdkFiles = base.RemoveUnless(func(f utils.Filename) bool { + return acceptListRe.MatchString(f.Relative(sdkDir)) + }, sdkFiles...) + } + return sdkDir, sdkFiles, err } else if extractDir, err := x.ExtractDir.Get(); err == nil { @@ -297,7 +308,7 @@ func (x *ExternalSDKGeneratedHeader) Generate(bc utils.BuildContext, generated * } } - base.LogVerbose(LogExternalSDK, "%s: found %d SDK library files %q", x.SDKName, len(sdkLibraries)) + base.LogVerbose(LogExternalSDK, "%s: found %d SDK library files", x.SDKName, len(sdkLibraries)) if base.IsLogLevelActive(base.LOG_VERYVERBOSE) { for _, it := range sdkLibraries { base.LogVeryVerbose(LogExternalSDK, "%s: found SDK library %q", x.SDKName, it) diff --git a/internal/io/IO.go b/internal/io/IO.go index 4f8221c..e2b9ed9 100644 --- a/internal/io/IO.go +++ b/internal/io/IO.go @@ -24,8 +24,9 @@ func InitIO() { base.RegisterSerializable[Downloader]() base.RegisterSerializable[DirectoryCreator]() - base.RegisterSerializable[DirectoryGlob]() base.RegisterSerializable[DirectoryList]() + base.RegisterSerializable[DirectoryMatch]() + base.RegisterSerializable[FileDigest]() } @@ -196,74 +197,77 @@ func GlobDirectory( includedGlobs base.StringSet, excludedGlobs base.StringSet, excludedFiles utils.FileSet) (utils.FileSet, error) { - factory := BuildDirectoryGlob(source, includedGlobs, excludedGlobs, excludedFiles) - if glob, err := factory.Need(bc); err == nil { - return glob.Results, nil + return MatchDirectory(bc, source, + utils.MakeGlobRegexp(includedGlobs...), + utils.MakeGlobRegexp(excludedGlobs...), + excludedFiles) +} + +/*************************************** + * Directory Match + ***************************************/ + +func MatchDirectory( + bc utils.BuildContext, + source utils.Directory, + includedRe base.Regexp, + excludedRe base.Regexp, + excludedFiles utils.FileSet) (utils.FileSet, error) { + factory := BuildDirectoryMatch(source, includedRe, excludedRe, excludedFiles) + if match, err := factory.Need(bc); err == nil { + return match.Results, nil } else { return utils.FileSet{}, err } } -type DirectoryGlob struct { +type DirectoryMatch struct { Source utils.Directory - IncludedGlobs base.StringSet - ExcludedGlobs base.StringSet + IncludedRe base.Regexp + ExcludedRe base.Regexp ExcludedFiles utils.FileSet - Results utils.FileSet + + Results utils.FileSet } -func BuildDirectoryGlob( +func BuildDirectoryMatch( source utils.Directory, - includedGlobs base.StringSet, - excludedGlobs base.StringSet, - excludedFiles utils.FileSet) utils.BuildFactoryTyped[*DirectoryGlob] { + includedRe base.Regexp, + excludedRe base.Regexp, + excludedFiles utils.FileSet) utils.BuildFactoryTyped[*DirectoryMatch] { base.Assert(func() bool { return source.Valid() }) - base.Assert(func() bool { return len(includedGlobs) > 0 }) - // make build alias determinist for DirectoryGlob - includedGlobs.Sort() - excludedGlobs.Sort() + if !includedRe.Valid() { + includedRe = utils.MakeGlobRegexp("*") + } + // make build alias determinist for DirectoryGlob excludedFiles = excludedFiles.Normalize() excludedFiles.Sort() - return utils.MakeBuildFactory(func(init utils.BuildInitializer) (DirectoryGlob, error) { - return DirectoryGlob{ + return utils.MakeBuildFactory(func(init utils.BuildInitializer) (DirectoryMatch, error) { + return DirectoryMatch{ Source: utils.SafeNormalize(source), - IncludedGlobs: includedGlobs, - ExcludedGlobs: excludedGlobs, + IncludedRe: includedRe, + ExcludedRe: excludedRe, ExcludedFiles: excludedFiles, Results: utils.FileSet{}, }, nil //init.NeedDirectories(source) // no dependency so to be built every-time }) } -func (x *DirectoryGlob) GetSourceDirectory() utils.Directory { +func (x *DirectoryMatch) GetSourceDirectory() utils.Directory { return x.Source } -func (x *DirectoryGlob) Alias() utils.BuildAlias { +func (x *DirectoryMatch) Alias() utils.BuildAlias { var bb utils.BuildAliasBuilder utils.MakeBuildAliasBuilder(&bb, "UFS", len(x.Source.Path)+1+len(x.Source.Basename())+4) - bb.WriteString('/', "Glob") + bb.WriteString('/', "Match") bb.WriteString('/', x.Source.Path) bb.WriteString('/', x.Source.Basename()) - - for i, it := range x.IncludedGlobs { - if i == 0 { - bb.WriteString('|', it) - } else { - bb.WriteString(';', it) - } - } - - for i, it := range x.ExcludedGlobs { - if i == 0 { - bb.WriteString('|', it) - } else { - bb.WriteString(';', it) - } - } + bb.WriteString('|', x.IncludedRe.String()) + bb.WriteString('|', x.ExcludedRe.String()) for i, it := range x.ExcludedFiles { if i == 0 { @@ -276,7 +280,7 @@ func (x *DirectoryGlob) Alias() utils.BuildAlias { return bb.Alias() } -func (x *DirectoryGlob) Build(bc utils.BuildContext) error { +func (x *DirectoryMatch) Build(bc utils.BuildContext) error { x.Results = utils.FileSet{} if info, err := x.Source.Info(); err == nil { @@ -285,21 +289,15 @@ func (x *DirectoryGlob) Build(bc utils.BuildContext) error { return err } - includeRE := utils.MakeGlobRegexp(x.IncludedGlobs...) - excludeRE := utils.MakeGlobRegexp(x.ExcludedGlobs...) - if !includeRE.Valid() { - includeRE = utils.MakeGlobRegexp("*") - } - err := x.Source.MatchFilesRec(func(f utils.Filename) error { f = utils.SafeNormalize(f) if !x.ExcludedFiles.Contains(f) { - if !excludeRE.Valid() || !excludeRE.MatchString(f.String()) { + if !x.ExcludedRe.Valid() || !x.ExcludedRe.MatchString(f.String()) { x.Results.Append(f) } } return nil - }, includeRE) + }, x.IncludedRe) if err == nil { bc.Annotate(utils.AnnocateBuildCommentf("%d files", len(x.Results))) @@ -307,10 +305,10 @@ func (x *DirectoryGlob) Build(bc utils.BuildContext) error { return err } -func (x *DirectoryGlob) Serialize(ar base.Archive) { +func (x *DirectoryMatch) Serialize(ar base.Archive) { ar.Serializable(&x.Source) - ar.Serializable(&x.IncludedGlobs) - ar.Serializable(&x.ExcludedGlobs) + ar.Serializable(&x.IncludedRe) + ar.Serializable(&x.ExcludedRe) ar.Serializable(&x.ExcludedFiles) ar.Serializable(&x.Results) }