mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-01 09:37:48 +00:00
2de0635140
We use ThinLTO for linking, but we use it in a way that doesn't give most of its benefits: we merge all the bitcode files into a single LLVM module and run some optimizations on it before linking. Therefore, this works more like a traditional "full" LTO link rather than a true thin link. This commit adds a new experimental -lto=thin option to do a true ThinLTO link. The main benefit is that linking will be a lot faster, especially for large programs consisting of many packages. At the moment, it only works for programs that don't do interface type asserts and don't call interface methods. It also probably won't work on WebAssembly and baremetal systems. But it's part of a larger goal towards a truly incremental build system: https://github.com/tinygo-org/tinygo/issues/2870 Once interface type asserts and method calls are converted to a vtable-like implementation, most programs should just work on linux/darwin/windows.
129 lines
3.6 KiB
Go
129 lines
3.6 KiB
Go
package compileopts
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
validGCOptions = []string{"none", "leaking", "conservative", "custom", "precise"}
|
|
validSchedulerOptions = []string{"none", "tasks", "asyncify"}
|
|
validSerialOptions = []string{"none", "uart", "usb"}
|
|
validPrintSizeOptions = []string{"none", "short", "full"}
|
|
validPanicStrategyOptions = []string{"print", "trap"}
|
|
validOptOptions = []string{"none", "0", "1", "2", "s", "z"}
|
|
validLTOOptions = []string{"legacy", "thin"}
|
|
)
|
|
|
|
// Options contains extra options to give to the compiler. These options are
|
|
// usually passed from the command line, but can also be passed in environment
|
|
// variables for example.
|
|
type Options struct {
|
|
GOOS string // environment variable
|
|
GOARCH string // environment variable
|
|
GOARM string // environment variable (only used with GOARCH=arm)
|
|
Target string
|
|
Opt string
|
|
LTO string
|
|
GC string
|
|
PanicStrategy string
|
|
Scheduler string
|
|
StackSize uint64 // goroutine stack size (if none could be automatically determined)
|
|
Serial string
|
|
Work bool // -work flag to print temporary build directory
|
|
InterpTimeout time.Duration
|
|
PrintIR bool
|
|
DumpSSA bool
|
|
VerifyIR bool
|
|
PrintCommands func(cmd string, args ...string) `json:"-"`
|
|
Semaphore chan struct{} `json:"-"` // -p flag controls cap
|
|
Debug bool
|
|
PrintSizes string
|
|
PrintAllocs *regexp.Regexp // regexp string
|
|
PrintStacks bool
|
|
Tags []string
|
|
GlobalValues map[string]map[string]string // map[pkgpath]map[varname]value
|
|
TestConfig TestConfig
|
|
Programmer string
|
|
OpenOCDCommands []string
|
|
LLVMFeatures string
|
|
Directory string
|
|
PrintJSON bool
|
|
Monitor bool
|
|
BaudRate int
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// 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.Serial != "" {
|
|
valid := isInArray(validSerialOptions, o.Serial)
|
|
if !valid {
|
|
return fmt.Errorf(`invalid serial option '%s': valid values are %s`,
|
|
o.Serial,
|
|
strings.Join(validSerialOptions, ", "))
|
|
}
|
|
}
|
|
|
|
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, ", "))
|
|
}
|
|
}
|
|
|
|
if o.Opt != "" {
|
|
if !isInArray(validOptOptions, o.Opt) {
|
|
return fmt.Errorf("invalid -opt=%s: valid values are %s", o.Opt, strings.Join(validOptOptions, ", "))
|
|
}
|
|
}
|
|
|
|
if o.LTO != "" {
|
|
if !isInArray(validLTOOptions, o.LTO) {
|
|
return fmt.Errorf("invalid -lto=%s: valid values are %s", o.LTO, strings.Join(validLTOOptions, ", "))
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func isInArray(arr []string, item string) bool {
|
|
for _, i := range arr {
|
|
if i == item {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|