main: move compile options to compileopts package

Этот коммит содержится в:
Ayke van Laethem 2019-10-31 16:38:49 +01:00 коммит произвёл Ron Evans
родитель ef600965aa
коммит 59cc901340
3 изменённых файлов: 83 добавлений и 80 удалений

21
compileopts/options.go Обычный файл
Просмотреть файл

@ -0,0 +1,21 @@
package compileopts
// Options contains extra options to give to the compiler. These options are
// usually passed from the command line.
type Options struct {
Opt string
GC string
PanicStrategy string
Scheduler string
PrintIR bool
DumpSSA bool
VerifyIR bool
Debug bool
PrintSizes string
CFlags []string
LDFlags []string
Tags string
WasmAbi string
HeapSize int64
TestConfig TestConfig
}

126
main.go
Просмотреть файл

@ -48,40 +48,22 @@ func (e *multiError) Error() string {
return e.Errs[0].Error() return e.Errs[0].Error()
} }
type BuildConfig struct {
opt string
gc string
panicStrategy string
scheduler string
printIR bool
dumpSSA bool
verifyIR bool
debug bool
printSizes string
cFlags []string
ldFlags []string
tags string
wasmAbi string
heapSize int64
testConfig compileopts.TestConfig
}
// Helper function for Compiler object. // Helper function for Compiler object.
func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *BuildConfig, action func(string) error) error { func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, options *compileopts.Options, action func(string) error) error {
if config.gc == "" && spec.GC != "" { if options.GC == "" && spec.GC != "" {
config.gc = spec.GC options.GC = spec.GC
} }
root := goenv.Get("TINYGOROOT") root := goenv.Get("TINYGOROOT")
// Merge and adjust CFlags. // Merge and adjust CFlags.
cflags := append([]string{}, config.cFlags...) cflags := append([]string{}, options.CFlags...)
for _, flag := range spec.CFlags { for _, flag := range spec.CFlags {
cflags = append(cflags, strings.Replace(flag, "{root}", root, -1)) cflags = append(cflags, strings.Replace(flag, "{root}", root, -1))
} }
// Merge and adjust LDFlags. // Merge and adjust LDFlags.
ldflags := append([]string{}, config.ldFlags...) ldflags := append([]string{}, options.LDFlags...)
for _, flag := range spec.LDFlags { for _, flag := range spec.LDFlags {
ldflags = append(ldflags, strings.Replace(flag, "{root}", root, -1)) ldflags = append(ldflags, strings.Replace(flag, "{root}", root, -1))
} }
@ -101,12 +83,12 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
for i := 1; i <= minor; i++ { for i := 1; i <= minor; i++ {
tags = append(tags, fmt.Sprintf("go1.%d", i)) tags = append(tags, fmt.Sprintf("go1.%d", i))
} }
if extraTags := strings.Fields(config.tags); len(extraTags) != 0 { if extraTags := strings.Fields(options.Tags); len(extraTags) != 0 {
tags = append(tags, extraTags...) tags = append(tags, extraTags...)
} }
scheduler := spec.Scheduler scheduler := spec.Scheduler
if config.scheduler != "" { if options.Scheduler != "" {
scheduler = config.scheduler scheduler = options.Scheduler
} }
compilerConfig := &compileopts.Config{ compilerConfig := &compileopts.Config{
Triple: spec.Triple, Triple: spec.Triple,
@ -114,20 +96,20 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
Features: spec.Features, Features: spec.Features,
GOOS: spec.GOOS, GOOS: spec.GOOS,
GOARCH: spec.GOARCH, GOARCH: spec.GOARCH,
GC: config.gc, GC: options.GC,
PanicStrategy: config.panicStrategy, PanicStrategy: options.PanicStrategy,
Scheduler: scheduler, Scheduler: scheduler,
CFlags: cflags, CFlags: cflags,
LDFlags: ldflags, LDFlags: ldflags,
ClangHeaders: getClangHeaderPath(root), ClangHeaders: getClangHeaderPath(root),
Debug: config.debug, Debug: options.Debug,
DumpSSA: config.dumpSSA, DumpSSA: options.DumpSSA,
VerifyIR: config.verifyIR, VerifyIR: options.VerifyIR,
TINYGOROOT: root, TINYGOROOT: root,
GOROOT: goroot, GOROOT: goroot,
GOPATH: goenv.Get("GOPATH"), GOPATH: goenv.Get("GOPATH"),
BuildTags: tags, BuildTags: tags,
TestConfig: config.testConfig, TestConfig: options.TestConfig,
} }
c, err := compiler.NewCompiler(pkgName, compilerConfig) c, err := compiler.NewCompiler(pkgName, compilerConfig)
if err != nil { if err != nil {
@ -142,7 +124,7 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
} }
return &multiError{errs} return &multiError{errs}
} }
if config.printIR { if options.PrintIR {
fmt.Println("; Generated LLVM IR:") fmt.Println("; Generated LLVM IR:")
fmt.Println(c.IR()) fmt.Println(c.IR())
} }
@ -150,7 +132,7 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
return errors.New("verification error after IR construction") return errors.New("verification error after IR construction")
} }
err = interp.Run(c.Module(), config.dumpSSA) err = interp.Run(c.Module(), options.DumpSSA)
if err != nil { if err != nil {
return err return err
} }
@ -167,7 +149,7 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
// keep functions interoperable, pass int64 types as pointers to // keep functions interoperable, pass int64 types as pointers to
// stack-allocated values. // stack-allocated values.
// Use -wasm-abi=generic to disable this behaviour. // Use -wasm-abi=generic to disable this behaviour.
if config.wasmAbi == "js" && strings.HasPrefix(spec.Triple, "wasm") { if options.WasmAbi == "js" && strings.HasPrefix(spec.Triple, "wasm") {
err := c.ExternalInt64AsPtr() err := c.ExternalInt64AsPtr()
if err != nil { if err != nil {
return err return err
@ -176,7 +158,7 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
// Optimization levels here are roughly the same as Clang, but probably not // Optimization levels here are roughly the same as Clang, but probably not
// exactly. // exactly.
switch config.opt { switch options.Opt {
case "none:", "0": case "none:", "0":
err = c.Optimize(0, 0, 0) // -O0 err = c.Optimize(0, 0, 0) // -O0
case "1": case "1":
@ -188,7 +170,7 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
case "z": case "z":
err = c.Optimize(2, 2, 5) // -Oz, default err = c.Optimize(2, 2, 5) // -Oz, default
default: default:
err = errors.New("unknown optimization level: -opt=" + config.opt) err = errors.New("unknown optimization level: -opt=" + options.Opt)
} }
if err != nil { if err != nil {
return err return err
@ -255,7 +237,7 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
if spec.GOARCH == "wasm" { if spec.GOARCH == "wasm" {
// Round heap size to next multiple of 65536 (the WebAssembly page // Round heap size to next multiple of 65536 (the WebAssembly page
// size). // size).
heapSize := (config.heapSize + (65536 - 1)) &^ (65536 - 1) heapSize := (options.HeapSize + (65536 - 1)) &^ (65536 - 1)
ldflags = append(ldflags, "--initial-memory="+strconv.FormatInt(heapSize, 10)) ldflags = append(ldflags, "--initial-memory="+strconv.FormatInt(heapSize, 10))
} }
@ -297,12 +279,12 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
return &commandError{"failed to link", executable, err} return &commandError{"failed to link", executable, err}
} }
if config.printSizes == "short" || config.printSizes == "full" { if options.PrintSizes == "short" || options.PrintSizes == "full" {
sizes, err := Sizes(executable) sizes, err := Sizes(executable)
if err != nil { if err != nil {
return err return err
} }
if config.printSizes == "short" { if options.PrintSizes == "short" {
fmt.Printf(" code data bss | flash ram\n") fmt.Printf(" code data bss | flash ram\n")
fmt.Printf("%7d %7d %7d | %7d %7d\n", sizes.Code, sizes.Data, sizes.BSS, sizes.Code+sizes.Data, sizes.Data+sizes.BSS) fmt.Printf("%7d %7d %7d | %7d %7d\n", sizes.Code, sizes.Data, sizes.BSS, sizes.Code+sizes.Data, sizes.Data+sizes.BSS)
} else { } else {
@ -335,13 +317,13 @@ func Compile(pkgName, outpath string, spec *compileopts.TargetSpec, config *Buil
} }
} }
func Build(pkgName, outpath, target string, config *BuildConfig) error { func Build(pkgName, outpath, target string, options *compileopts.Options) error {
spec, err := compileopts.LoadTarget(target) spec, err := compileopts.LoadTarget(target)
if err != nil { if err != nil {
return err return err
} }
return Compile(pkgName, outpath, spec, config, func(tmppath string) error { return Compile(pkgName, outpath, spec, options, func(tmppath string) error {
if err := os.Rename(tmppath, outpath); err != nil { if err := os.Rename(tmppath, outpath); err != nil {
// Moving failed. Do a file copy. // Moving failed. Do a file copy.
inf, err := os.Open(tmppath) inf, err := os.Open(tmppath)
@ -369,15 +351,15 @@ func Build(pkgName, outpath, target string, config *BuildConfig) error {
}) })
} }
func Test(pkgName, target string, config *BuildConfig) error { func Test(pkgName, target string, options *compileopts.Options) error {
spec, err := compileopts.LoadTarget(target) spec, err := compileopts.LoadTarget(target)
if err != nil { if err != nil {
return err return err
} }
spec.BuildTags = append(spec.BuildTags, "test") spec.BuildTags = append(spec.BuildTags, "test")
config.testConfig.CompileTestBinary = true options.TestConfig.CompileTestBinary = true
return Compile(pkgName, ".elf", spec, config, func(tmppath string) error { return Compile(pkgName, ".elf", spec, options, func(tmppath string) error {
cmd := exec.Command(tmppath) cmd := exec.Command(tmppath)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr
@ -396,7 +378,7 @@ func Test(pkgName, target string, config *BuildConfig) error {
}) })
} }
func Flash(pkgName, target, port string, config *BuildConfig) error { func Flash(pkgName, target, port string, options *compileopts.Options) error {
spec, err := compileopts.LoadTarget(target) spec, err := compileopts.LoadTarget(target)
if err != nil { if err != nil {
return err return err
@ -432,7 +414,7 @@ func Flash(pkgName, target, port string, config *BuildConfig) error {
return errors.New("unknown flash method: " + spec.FlashMethod) return errors.New("unknown flash method: " + spec.FlashMethod)
} }
return Compile(pkgName, fileExt, spec, config, func(tmppath string) error { return Compile(pkgName, fileExt, spec, options, func(tmppath string) error {
// do we need port reset to put MCU into bootloader mode? // do we need port reset to put MCU into bootloader mode?
if spec.PortReset == "true" { if spec.PortReset == "true" {
err := touchSerialPortAt1200bps(port) err := touchSerialPortAt1200bps(port)
@ -503,7 +485,7 @@ func Flash(pkgName, target, port string, config *BuildConfig) error {
// //
// Note: this command is expected to execute just before exiting, as it // Note: this command is expected to execute just before exiting, as it
// modifies global state. // modifies global state.
func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig) error { func FlashGDB(pkgName, target, port string, ocdOutput bool, options *compileopts.Options) error {
spec, err := compileopts.LoadTarget(target) spec, err := compileopts.LoadTarget(target)
if err != nil { if err != nil {
return err return err
@ -513,7 +495,7 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
return errors.New("gdb not configured in the target specification") return errors.New("gdb not configured in the target specification")
} }
return Compile(pkgName, "", spec, config, func(tmppath string) error { return Compile(pkgName, "", spec, options, func(tmppath string) error {
// Find a good way to run GDB. // Find a good way to run GDB.
gdbInterface := spec.FlashMethod gdbInterface := spec.FlashMethod
switch gdbInterface { switch gdbInterface {
@ -594,13 +576,13 @@ func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig)
} }
// Compile and run the given program, directly or in an emulator. // Compile and run the given program, directly or in an emulator.
func Run(pkgName, target string, config *BuildConfig) error { func Run(pkgName, target string, options *compileopts.Options) error {
spec, err := compileopts.LoadTarget(target) spec, err := compileopts.LoadTarget(target)
if err != nil { if err != nil {
return err return err
} }
return Compile(pkgName, ".elf", spec, config, func(tmppath string) error { return Compile(pkgName, ".elf", spec, options, func(tmppath string) error {
if len(spec.Emulator) == 0 { if len(spec.Emulator) == 0 {
// Run directly. // Run directly.
cmd := exec.Command(tmppath) cmd := exec.Command(tmppath)
@ -777,26 +759,26 @@ func main() {
command := os.Args[1] command := os.Args[1]
flag.CommandLine.Parse(os.Args[2:]) flag.CommandLine.Parse(os.Args[2:])
config := &BuildConfig{ options := &compileopts.Options{
opt: *opt, Opt: *opt,
gc: *gc, GC: *gc,
panicStrategy: *panicStrategy, PanicStrategy: *panicStrategy,
scheduler: *scheduler, Scheduler: *scheduler,
printIR: *printIR, PrintIR: *printIR,
dumpSSA: *dumpSSA, DumpSSA: *dumpSSA,
verifyIR: *verifyIR, VerifyIR: *verifyIR,
debug: !*nodebug, Debug: !*nodebug,
printSizes: *printSize, PrintSizes: *printSize,
tags: *tags, Tags: *tags,
wasmAbi: *wasmAbi, WasmAbi: *wasmAbi,
} }
if *cFlags != "" { if *cFlags != "" {
config.cFlags = strings.Split(*cFlags, " ") options.CFlags = strings.Split(*cFlags, " ")
} }
if *ldFlags != "" { if *ldFlags != "" {
config.ldFlags = strings.Split(*ldFlags, " ") options.LDFlags = strings.Split(*ldFlags, " ")
} }
if *panicStrategy != "print" && *panicStrategy != "trap" { if *panicStrategy != "print" && *panicStrategy != "trap" {
@ -806,7 +788,7 @@ func main() {
} }
var err error var err error
if config.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)
usage() usage()
os.Exit(1) os.Exit(1)
@ -833,7 +815,7 @@ func main() {
if target == "" && filepath.Ext(*outpath) == ".wasm" { if target == "" && filepath.Ext(*outpath) == ".wasm" {
target = "wasm" target = "wasm"
} }
err := Build(pkgName, *outpath, target, config) err := Build(pkgName, *outpath, target, options)
handleCompilerError(err) handleCompilerError(err)
case "build-builtins": case "build-builtins":
// Note: this command is only meant to be used while making a release! // Note: this command is only meant to be used while making a release!
@ -856,15 +838,15 @@ func main() {
os.Exit(1) os.Exit(1)
} }
if command == "flash" { if command == "flash" {
err := Flash(flag.Arg(0), *target, *port, config) err := Flash(flag.Arg(0), *target, *port, options)
handleCompilerError(err) handleCompilerError(err)
} else { } else {
if !config.debug { if !options.Debug {
fmt.Fprintln(os.Stderr, "Debug disabled while running gdb?") fmt.Fprintln(os.Stderr, "Debug disabled while running gdb?")
usage() usage()
os.Exit(1) os.Exit(1)
} }
err := FlashGDB(flag.Arg(0), *target, *port, *ocdOutput, config) err := FlashGDB(flag.Arg(0), *target, *port, *ocdOutput, options)
handleCompilerError(err) handleCompilerError(err)
} }
case "run": case "run":
@ -873,7 +855,7 @@ func main() {
usage() usage()
os.Exit(1) os.Exit(1)
} }
err := Run(flag.Arg(0), *target, config) err := Run(flag.Arg(0), *target, options)
handleCompilerError(err) handleCompilerError(err)
case "test": case "test":
pkgName := "." pkgName := "."
@ -884,7 +866,7 @@ func main() {
usage() usage()
os.Exit(1) os.Exit(1)
} }
err := Test(pkgName, *target, config) err := Test(pkgName, *target, options)
handleCompilerError(err) handleCompilerError(err)
case "clean": case "clean":
// remove cache directory // remove cache directory

Просмотреть файл

@ -115,14 +115,14 @@ func runTest(path, tmpdir string, target string, t *testing.T) {
} }
// Build the test binary. // Build the test binary.
config := &BuildConfig{ config := &compileopts.Options{
opt: "z", Opt: "z",
printIR: false, PrintIR: false,
dumpSSA: false, DumpSSA: false,
verifyIR: true, VerifyIR: true,
debug: false, Debug: false,
printSizes: "", PrintSizes: "",
wasmAbi: "js", WasmAbi: "js",
} }
binary := filepath.Join(tmpdir, "test") binary := filepath.Join(tmpdir, "test")
err = Build("./"+path, binary, target, config) err = Build("./"+path, binary, target, config)