compileopts: improve error reporting of unsupported flags
Этот коммит содержится в:
родитель
29ca1147f5
коммит
76fb3bd177
4 изменённых файлов: 211 добавлений и 9 удалений
|
@ -129,8 +129,8 @@ func (c *Config) NeedsStackObjects() bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scheduler returns the scheduler implementation. Valid values are "coroutines"
|
// Scheduler returns the scheduler implementation. Valid values are "none",
|
||||||
// and "tasks".
|
//"coroutines" and "tasks".
|
||||||
func (c *Config) Scheduler() string {
|
func (c *Config) Scheduler() string {
|
||||||
if c.Options.Scheduler != "" {
|
if c.Options.Scheduler != "" {
|
||||||
return c.Options.Scheduler
|
return c.Options.Scheduler
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
package compileopts
|
package compileopts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
validGCOptions = []string{"none", "leaking", "extalloc", "conservative"}
|
||||||
|
validSchedulerOptions = []string{"none", "tasks", "coroutines"}
|
||||||
|
validPrintSizeOptions = []string{"none", "short", "full"}
|
||||||
|
validPanicStrategyOptions = []string{"print", "trap"}
|
||||||
|
)
|
||||||
|
|
||||||
// Options contains extra options to give to the compiler. These options are
|
// Options contains extra options to give to the compiler. These options are
|
||||||
// usually passed from the command line.
|
// usually passed from the command line.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
|
@ -21,3 +33,53 @@ type Options struct {
|
||||||
TestConfig TestConfig
|
TestConfig TestConfig
|
||||||
Programmer string
|
Programmer string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify performs a validation on the given options, raising an error if options are not valid.
|
||||||
|
func (o *Options) Verify() error {
|
||||||
|
if o.GC != "" {
|
||||||
|
valid := isInArray(validGCOptions, o.GC)
|
||||||
|
if !valid {
|
||||||
|
return fmt.Errorf(`invalid gc option '%s': valid values are %s`,
|
||||||
|
o.GC,
|
||||||
|
strings.Join(validGCOptions, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Scheduler != "" {
|
||||||
|
valid := isInArray(validSchedulerOptions, o.Scheduler)
|
||||||
|
if !valid {
|
||||||
|
return fmt.Errorf(`invalid scheduler option '%s': valid values are %s`,
|
||||||
|
o.Scheduler,
|
||||||
|
strings.Join(validSchedulerOptions, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.PrintSizes != "" {
|
||||||
|
valid := isInArray(validPrintSizeOptions, o.PrintSizes)
|
||||||
|
if !valid {
|
||||||
|
return fmt.Errorf(`invalid size option '%s': valid values are %s`,
|
||||||
|
o.PrintSizes,
|
||||||
|
strings.Join(validPrintSizeOptions, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.PanicStrategy != "" {
|
||||||
|
valid := isInArray(validPanicStrategyOptions, o.PanicStrategy)
|
||||||
|
if !valid {
|
||||||
|
return fmt.Errorf(`invalid panic option '%s': valid values are %s`,
|
||||||
|
o.PanicStrategy,
|
||||||
|
strings.Join(validPanicStrategyOptions, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInArray(arr []string, item string) bool {
|
||||||
|
for _, i := range arr {
|
||||||
|
if i == item {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
138
compileopts/options_test.go
Обычный файл
138
compileopts/options_test.go
Обычный файл
|
@ -0,0 +1,138 @@
|
||||||
|
package compileopts_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/tinygo-org/tinygo/compileopts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVerifyOptions(t *testing.T) {
|
||||||
|
|
||||||
|
expectedGCError := errors.New(`invalid gc option 'incorrect': valid values are none, leaking, extalloc, conservative`)
|
||||||
|
expectedSchedulerError := errors.New(`invalid scheduler option 'incorrect': valid values are none, tasks, coroutines`)
|
||||||
|
expectedPrintSizeError := errors.New(`invalid size option 'incorrect': valid values are none, short, full`)
|
||||||
|
expectedPanicStrategyError := errors.New(`invalid panic option 'incorrect': valid values are print, trap`)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
opts compileopts.Options
|
||||||
|
expectedError error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "OptionsEmpty",
|
||||||
|
opts: compileopts.Options{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidGCOption",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
GC: "incorrect",
|
||||||
|
},
|
||||||
|
expectedError: expectedGCError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GCOptionNone",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
GC: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GCOptionLeaking",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
GC: "leaking",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GCOptionExtalloc",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
GC: "extalloc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "GCOptionConservative",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
GC: "conservative",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidSchedulerOption",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
Scheduler: "incorrect",
|
||||||
|
},
|
||||||
|
expectedError: expectedSchedulerError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SchedulerOptionNone",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
Scheduler: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SchedulerOptionTasks",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
Scheduler: "tasks",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SchedulerOptionCoroutines",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
Scheduler: "coroutines",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidPrintSizeOption",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PrintSizes: "incorrect",
|
||||||
|
},
|
||||||
|
expectedError: expectedPrintSizeError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PrintSizeOptionNone",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PrintSizes: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PrintSizeOptionShort",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PrintSizes: "short",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PrintSizeOptionFull",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PrintSizes: "full",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "InvalidPanicOption",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PanicStrategy: "incorrect",
|
||||||
|
},
|
||||||
|
expectedError: expectedPanicStrategyError,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PanicOptionPrint",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PanicStrategy: "print",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "PanicOptionTrap",
|
||||||
|
opts: compileopts.Options{
|
||||||
|
PanicStrategy: "trap",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := tc.opts.Verify()
|
||||||
|
if tc.expectedError != err {
|
||||||
|
if tc.expectedError.Error() != err.Error() {
|
||||||
|
t.Errorf("expected %v, got %v", tc.expectedError, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
16
main.go
16
main.go
|
@ -699,7 +699,7 @@ func main() {
|
||||||
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
opt := flag.String("opt", "z", "optimization level: 0, 1, 2, s, z")
|
||||||
gc := flag.String("gc", "", "garbage collector to use (none, leaking, extalloc, conservative)")
|
gc := flag.String("gc", "", "garbage collector to use (none, leaking, extalloc, conservative)")
|
||||||
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
panicStrategy := flag.String("panic", "print", "panic strategy (print, trap)")
|
||||||
scheduler := flag.String("scheduler", "", "which scheduler to use (coroutines, tasks)")
|
scheduler := flag.String("scheduler", "", "which scheduler to use (none, coroutines, tasks)")
|
||||||
printIR := flag.Bool("printir", false, "print LLVM IR")
|
printIR := flag.Bool("printir", false, "print LLVM IR")
|
||||||
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
dumpSSA := flag.Bool("dumpssa", false, "dump internal Go SSA")
|
||||||
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
verifyIR := flag.Bool("verifyir", false, "run extra verification steps on LLVM IR")
|
||||||
|
@ -759,12 +759,6 @@ func main() {
|
||||||
options.LDFlags = strings.Split(*ldFlags, " ")
|
options.LDFlags = strings.Split(*ldFlags, " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
if *panicStrategy != "print" && *panicStrategy != "trap" {
|
|
||||||
fmt.Fprintln(os.Stderr, "Panic strategy must be either print or trap.")
|
|
||||||
usage()
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if options.HeapSize, err = parseSize(*heapSize); err != nil {
|
if options.HeapSize, err = parseSize(*heapSize); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "Could not read heap size:", *heapSize)
|
fmt.Fprintln(os.Stderr, "Could not read heap size:", *heapSize)
|
||||||
|
@ -774,6 +768,13 @@ func main() {
|
||||||
|
|
||||||
os.Setenv("CC", "clang -target="+*target)
|
os.Setenv("CC", "clang -target="+*target)
|
||||||
|
|
||||||
|
err = options.Verify()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err.Error())
|
||||||
|
usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
switch command {
|
switch command {
|
||||||
case "build":
|
case "build":
|
||||||
if *outpath == "" {
|
if *outpath == "" {
|
||||||
|
@ -792,6 +793,7 @@ func main() {
|
||||||
if options.Target == "" && filepath.Ext(*outpath) == ".wasm" {
|
if options.Target == "" && filepath.Ext(*outpath) == ".wasm" {
|
||||||
options.Target = "wasm"
|
options.Target = "wasm"
|
||||||
}
|
}
|
||||||
|
|
||||||
err := Build(pkgName, *outpath, options)
|
err := Build(pkgName, *outpath, options)
|
||||||
handleCompilerError(err)
|
handleCompilerError(err)
|
||||||
case "build-library":
|
case "build-library":
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче