Skip to content

Commit

Permalink
Refactor Downloaded and Generated to handle data-driven external SDK
Browse files Browse the repository at this point in the history
Can either use an external path, an external archive to be compressed, or
a http link to a compressed archive, when using the new archetype "SDK/External".
Those arguments along other options are specified through module variable exports.
Also, Optional[] of serializable values can now be serialized.
  • Loading branch information
poppolopoppo committed Oct 11, 2024
1 parent 15efdfa commit 32ab411
Show file tree
Hide file tree
Showing 19 changed files with 672 additions and 161 deletions.
15 changes: 12 additions & 3 deletions compile/Facet.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package compile

import (
"errors"
"fmt"
"regexp"
"strings"
Expand Down Expand Up @@ -283,6 +284,8 @@ func (vars VariableSubstitutions) ExpandFilename(it utils.Filename) utils.Filena
* Variable Definitions
***************************************/

var ErrUnknownVar = errors.New("unknown variable")

func (vars VariableDefinitions) Prepare() VariableSubstitutions {
return NewVariableSubstituions(vars...)
}
Expand All @@ -295,12 +298,18 @@ func (vars *VariableDefinitions) Add(name, value string) {
})
}
}
func (vars VariableDefinitions) Get(from string) string {
func (vars VariableDefinitions) Get(from string) (string, error) {
if i, ok := vars.IndexOf(from); ok {
return vars[i].Value, nil
} else {
return "", ErrUnknownVar
}
}
func (vars VariableDefinitions) GetOrElse(from, orElse string) string {
if i, ok := vars.IndexOf(from); ok {
return vars[i].Value
} else {
base.LogPanic(LogCompile, "variable-substitutions: could not find [[:%s:]] in %v", from, vars)
return ""
return orElse
}
}
func (vars VariableDefinitions) IndexOf(from string) (int, bool) {
Expand Down
27 changes: 18 additions & 9 deletions compile/Generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ type Generated interface {
}

type BuildGenerated struct {
OutputFile utils.Filename
GeneratedName string
OutputFile utils.Filename
Generated
}

Expand All @@ -40,6 +41,7 @@ func (x *BuildGenerated) Build(bc utils.BuildContext) error {
return err
}
func (x *BuildGenerated) Serialize(ar base.Archive) {
ar.String(&x.GeneratedName)
ar.Serializable(&x.OutputFile)
base.SerializeExternal(ar, &x.Generated)
}
Expand All @@ -49,7 +51,7 @@ func (x *BuildGenerated) Serialize(ar base.Archive) {
***************************************/

type Generator interface {
CreateGenerated(unit *Unit, output utils.Filename) Generated
CreateGenerated(unit *Unit, output utils.Filename) (Generated, error)
base.Serializable
}

Expand Down Expand Up @@ -95,15 +97,22 @@ func (rules *GeneratorRules) GetGenerateFile(unit *Unit) utils.Filename {
return rules.GetGenerateDir(unit).AbsoluteFile(rules.GeneratedName)
}

func (rules *GeneratorRules) CreateGenerated(bc utils.BuildContext, module Module, unit *Unit) (*BuildGenerated, error) {
func (rules *GeneratorRules) CreateGenerated(bc utils.BuildContext, module Module, unit *Unit) (result *BuildGenerated, err error) {
outputFile := rules.GetGenerateFile(unit)
generated := &BuildGenerated{
OutputFile: outputFile,
Generated: rules.Generator.CreateGenerated(unit, outputFile),

var generated Generated
generated, err = rules.Generator.CreateGenerated(unit, outputFile)
if err != nil {
return
}

err := bc.OutputNode(utils.WrapBuildFactory(func(bi utils.BuildInitializer) (*BuildGenerated, error) {
return generated, bi.NeedFactories(internal_io.BuildDirectoryCreator(outputFile.Dirname))
result = &BuildGenerated{
GeneratedName: rules.GeneratedName,
OutputFile: outputFile,
Generated: generated,
}
err = bc.OutputNode(utils.WrapBuildFactory(func(bi utils.BuildInitializer) (*BuildGenerated, error) {
return result, bi.NeedFactories(internal_io.BuildDirectoryCreator(outputFile.Dirname))
}))
return generated, err
return result, err
}
3 changes: 1 addition & 2 deletions compile/Unit.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"strings"

"github.com/poppolopoppo/ppb/internal/base"
"github.com/poppolopoppo/ppb/utils"

internal_io "github.com/poppolopoppo/ppb/internal/io"

Expand Down Expand Up @@ -73,7 +72,7 @@ func (x *TargetAlias) UnmarshalText(data []byte) error {
return x.Set(base.UnsafeStringFromBytes(data))
}
func (x TargetAlias) AutoComplete(in base.AutoComplete) {
if bg, ok := in.GetUserParam().(utils.BuildGraphReadPort); ok {
if bg, ok := in.GetUserParam().(BuildGraphReadPort); ok {
var modules base.SetT[Module]
ForeachBuildable(bg, func(_ BuildAlias, m Module) error {
modules.Append(m)
Expand Down
14 changes: 13 additions & 1 deletion internal/base/Optional.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package base

import "errors"
import (
"errors"
)

/***************************************
* Optional[T] holds a value or an error, with value semantics
Expand Down Expand Up @@ -41,3 +43,13 @@ func (x Optional[T]) GetOrElse(orElse T) T {
return orElse
}
}

func SetOptional[T any, E interface {
*T
Set(string) error
}](in string, optional *Optional[T]) (err error) {
if err = E(&optional.value).Set(in); err == nil {
optional.err = nil
}
return
}
21 changes: 21 additions & 0 deletions internal/base/Serializable.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,27 @@ func SerializeExternal[T Serializable](ar Archive, external *T) {
ar.Serializable(*external)
}

func SerializeOptional[T any, E interface {
*T
Serializable
}](ar Archive, optional *Optional[T]) {
if ar.Flags().IsLoading() {
var valid bool
ar.Bool(&valid)
if valid {
ar.Serializable(E(&optional.value))
} else {
optional.err = ErrEmptyOptional
}
} else {
valid := optional.Valid()
ar.Bool(&valid)
if valid {
ar.Serializable(E(&optional.value))
}
}
}

func SerializeCompactSigned[Signed constraints.Signed](ar Archive, index *Signed) {
var b byte
if ar.Flags().IsLoading() {
Expand Down
105 changes: 105 additions & 0 deletions internal/base/SerializableHelpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package base

import (
"net/url"
"regexp"
"strings"
)

/***************************************
* Serializable Regexp
***************************************/

type Regexp struct {
*regexp.Regexp
}

func NewRegexp(pattern string) Regexp {
return Regexp{regexp.MustCompile(pattern)}
}
func (x Regexp) Valid() bool { return x.Regexp != nil }
func (x *Regexp) Set(in string) (err error) {
x.Regexp, err = regexp.Compile(in)
return
}
func (x *Regexp) MarshalText() ([]byte, error) {
return UnsafeBytesFromString(x.String()), nil
}
func (x *Regexp) UnmarshalText(data []byte) error {
return x.Set(UnsafeStringFromBytes(data))
}
func (x *Regexp) Serialize(ar Archive) {
if ar.Flags().IsLoading() {
var url string
ar.String(&url)
if err := x.Set(url); err != nil {
ar.OnError(err)
}
} else {
url := x.String()
ar.String(&url)
}
}
func (x Regexp) Concat(patterns ...Regexp) Regexp {
merged := strings.Builder{}

var n int
if x.Valid() {
n++
merged.WriteString("(?:") // non-capturing group
merged.WriteString(x.String())
merged.WriteRune(')')
} else if len(patterns) == 0 {
return Regexp{} // invalid pattern
}

for _, it := range patterns {
if it.Valid() {
if n > 0 {
merged.WriteRune('|')
}
n++
merged.WriteString("(?:") // non-capturing group
merged.WriteString(it.String())
merged.WriteRune(')')
}
}

if n > 0 {
return Regexp{Regexp: regexp.MustCompile(merged.String())}
} else {
return Regexp{}
}
}

/***************************************
* Serializable URL
***************************************/

type Url struct {
*url.URL
}

func (x Url) Valid() bool { return x.URL != nil }
func (x *Url) Set(in string) (err error) {
x.URL, err = url.Parse(in)
return
}
func (x *Url) MarshalText() ([]byte, error) {
return UnsafeBytesFromString(x.String()), nil
}
func (x *Url) UnmarshalText(data []byte) error {
return x.Set(UnsafeStringFromBytes(data))
}
func (x *Url) Serialize(ar Archive) {
if ar.Flags().IsLoading() {
var url string
ar.String(&url)
if err := x.Set(url); err != nil {
ar.OnError(err)
}
} else {
url := x.String()
ar.String(&url)
}
}
2 changes: 1 addition & 1 deletion internal/cmd/Completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func filterCompletion(args *CompletionArgs, output func(string) error, values ..
keys.Sort()

globRE := utils.MakeGlobRegexp(keys...)
if globRE == nil {
if !globRE.Valid() {
return fmt.Errorf("invalid regular expression: %q", keys)
}

Expand Down
14 changes: 9 additions & 5 deletions internal/cmd/Vcxproj.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/poppolopoppo/ppb/compile"
"github.com/poppolopoppo/ppb/internal/base"
internal_io "github.com/poppolopoppo/ppb/internal/io"
"github.com/poppolopoppo/ppb/utils"

//lint:ignore ST1001 ignore dot imports warning
. "github.com/poppolopoppo/ppb/utils"
Expand All @@ -21,7 +20,7 @@ var CommandVcxproj = NewCommand(
"vcxproj",
"generate projects and solution for Visual Studio",
OptionCommandRun(func(cc CommandContext) error {
bg := utils.CommandEnv.BuildGraph().OpenWritePort(base.ThreadPoolDebugId{Category: "Vcxproj"})
bg := CommandEnv.BuildGraph().OpenWritePort(base.ThreadPoolDebugId{Category: "Vcxproj"})
defer bg.Close()

solutionFile := UFS.Output.File(CommandEnv.Prefix() + ".sln")
Expand Down Expand Up @@ -376,10 +375,15 @@ func (x *VcxProjectBuilder) Build(bc BuildContext) error {
return bc.OutputFile(generator.ProjectOutput, generator.FiltersOutput)
}

func (x *VcxProjectBuilder) vcxProjectConfig(config *VcxProjectConfig, u *compile.Unit) error {
func (x *VcxProjectBuilder) vcxProjectConfig(config *VcxProjectConfig, u *compile.Unit) (err error) {
if config.PlatformToolset, err = u.Facet.Exports.Get("VisualStudio/PlatformToolset"); err == nil {
config.PlatformToolset = fmt.Sprint("v", config.PlatformToolset)
} else {
return err
}

config.Platform = x.SolutionPlatform(u.TargetAlias.PlatformName)
config.Config = u.TargetAlias.ConfigName
config.PlatformToolset = fmt.Sprint("v", u.Facet.Exports.Get("VisualStudio/PlatformToolset"))
config.OutputFile = u.OutputFile
config.OutputDirectory = u.OutputFile.Dirname
config.IntermediateDirectory = u.IntermediateDir
Expand Down Expand Up @@ -408,7 +412,7 @@ func (x *VcxProjectBuilder) vcxProjectConfig(config *VcxProjectConfig, u *compil
config.LocalDebuggerEnvironment = strings.Join(append(u.Environment.Export(), "^$(LocalDebuggerEnvironment)"), htmlLineFeed)
}
}
return nil
return
}

/***************************************
Expand Down
Loading

0 comments on commit 32ab411

Please sign in to comment.