main: refactor build option passing

The list of options passed to build/run/gdb/etc commands was getting
unwieldly and hard to add extra options to. Put all common build options
in a single build config struct so that these options are more
centralized.
Этот коммит содержится в:
Ayke van Laethem 2018-10-24 23:53:44 +02:00
родитель fcd44c02cd
коммит 980dceb192
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
2 изменённых файлов: 50 добавлений и 24 удалений

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

@ -22,24 +22,32 @@ var commands = map[string]string{
"clang": "clang-7", "clang": "clang-7",
} }
type BuildConfig struct {
opt string
printIR bool
dumpSSA bool
debug bool
printSizes string
}
// Helper function for Compiler object. // Helper function for Compiler object.
func Compile(pkgName, outpath, opt string, spec *TargetSpec, printIR, dumpSSA, debug bool, printSizes string, action func(string) error) error { func Compile(pkgName, outpath string, spec *TargetSpec, config *BuildConfig, action func(string) error) error {
config := compiler.Config{ compilerConfig := compiler.Config{
Triple: spec.Triple, Triple: spec.Triple,
Debug: debug, Debug: config.debug,
DumpSSA: dumpSSA, DumpSSA: config.dumpSSA,
RootDir: sourceDir(), RootDir: sourceDir(),
GOPATH: getGopath(), GOPATH: getGopath(),
BuildTags: spec.BuildTags, BuildTags: spec.BuildTags,
} }
c, err := compiler.NewCompiler(pkgName, config) c, err := compiler.NewCompiler(pkgName, compilerConfig)
if err != nil { if err != nil {
return err return err
} }
// Compile Go code to IR. // Compile Go code to IR.
parseErr := func() error { parseErr := func() error {
if printIR { if config.printIR {
// Run this even if c.Compile() panics. // Run this even if c.Compile() panics.
defer func() { defer func() {
fmt.Println("Generated LLVM IR:") fmt.Println("Generated LLVM IR:")
@ -60,7 +68,7 @@ func Compile(pkgName, outpath, opt string, spec *TargetSpec, printIR, dumpSSA, d
// 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 opt { switch config.opt {
case "none:", "0": case "none:", "0":
c.Optimize(0, 0, 0) // -O0 c.Optimize(0, 0, 0) // -O0
case "1": case "1":
@ -72,7 +80,7 @@ func Compile(pkgName, outpath, opt string, spec *TargetSpec, printIR, dumpSSA, d
case "z": case "z":
c.Optimize(2, 2, 5) // -Oz, default c.Optimize(2, 2, 5) // -Oz, default
default: default:
return errors.New("unknown optimization level: -opt=" + opt) return errors.New("unknown optimization level: -opt=" + config.opt)
} }
if err := c.Verify(); err != nil { if err := c.Verify(); err != nil {
return err return err
@ -143,12 +151,12 @@ func Compile(pkgName, outpath, opt string, spec *TargetSpec, printIR, dumpSSA, d
return err return err
} }
if printSizes == "short" || printSizes == "full" { if config.printSizes == "short" || config.printSizes == "full" {
sizes, err := Sizes(executable) sizes, err := Sizes(executable)
if err != nil { if err != nil {
return err return err
} }
if printSizes == "short" { if config.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 {
@ -181,13 +189,13 @@ func Compile(pkgName, outpath, opt string, spec *TargetSpec, printIR, dumpSSA, d
} }
} }
func Build(pkgName, outpath, target, opt string, printIR, dumpSSA, debug bool, printSizes string) error { func Build(pkgName, outpath, target string, config *BuildConfig) error {
spec, err := LoadTarget(target) spec, err := LoadTarget(target)
if err != nil { if err != nil {
return err return err
} }
return Compile(pkgName, outpath, opt, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { return Compile(pkgName, outpath, spec, config, 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)
@ -215,13 +223,13 @@ func Build(pkgName, outpath, target, opt string, printIR, dumpSSA, debug bool, p
}) })
} }
func Flash(pkgName, target, opt, port string, printIR, dumpSSA, debug bool, printSizes string) error { func Flash(pkgName, target, port string, config *BuildConfig) error {
spec, err := LoadTarget(target) spec, err := LoadTarget(target)
if err != nil { if err != nil {
return err return err
} }
return Compile(pkgName, ".hex", opt, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error { return Compile(pkgName, ".hex", spec, config, func(tmppath string) error {
if spec.Flasher == "" { if spec.Flasher == "" {
return errors.New("no flash command specified - did you miss a -target flag?") return errors.New("no flash command specified - did you miss a -target flag?")
} }
@ -244,7 +252,7 @@ func Flash(pkgName, target, opt, port string, printIR, dumpSSA, debug bool, prin
// //
// 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, opt, port string, printIR, dumpSSA, ocdOutput bool, printSizes string) error { func FlashGDB(pkgName, target, port string, ocdOutput bool, config *BuildConfig) error {
spec, err := LoadTarget(target) spec, err := LoadTarget(target)
if err != nil { if err != nil {
return err return err
@ -254,8 +262,7 @@ func FlashGDB(pkgName, target, opt, port string, printIR, dumpSSA, ocdOutput boo
return errors.New("gdb not configured in the target specification") return errors.New("gdb not configured in the target specification")
} }
debug := true // always enable debug symbols return Compile(pkgName, "", spec, config, func(tmppath string) error {
return Compile(pkgName, "", opt, spec, printIR, dumpSSA, debug, printSizes, func(tmppath string) error {
if len(spec.OCDDaemon) != 0 { if len(spec.OCDDaemon) != 0 {
// We need a separate debugging daemon for on-chip debugging. // We need a separate debugging daemon for on-chip debugging.
daemon := exec.Command(spec.OCDDaemon[0], spec.OCDDaemon[1:]...) daemon := exec.Command(spec.OCDDaemon[0], spec.OCDDaemon[1:]...)
@ -346,7 +353,7 @@ func Run(pkgName string) error {
} }
// Compile and run the given program in an emulator. // Compile and run the given program in an emulator.
func Emulate(pkgName, target, opt string) error { func Emulate(pkgName, target string, config *BuildConfig) error {
spec, err := LoadTarget(target) spec, err := LoadTarget(target)
if err != nil { if err != nil {
return err return err
@ -355,7 +362,7 @@ func Emulate(pkgName, target, opt string) error {
return errors.New("no emulator configured for this target") return errors.New("no emulator configured for this target")
} }
return Compile(pkgName, ".elf", opt, spec, false, false, false, "", func(tmppath string) error { return Compile(pkgName, ".elf", spec, config, func(tmppath string) error {
args := append(spec.Emulator[1:], tmppath) args := append(spec.Emulator[1:], tmppath)
cmd := exec.Command(spec.Emulator[0], args...) cmd := exec.Command(spec.Emulator[0], args...)
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
@ -401,6 +408,13 @@ func main() {
command := os.Args[1] command := os.Args[1]
flag.CommandLine.Parse(os.Args[2:]) flag.CommandLine.Parse(os.Args[2:])
config := &BuildConfig{
opt: *opt,
printIR: *printIR,
dumpSSA: *dumpSSA,
debug: !*nodebug,
printSizes: *printSize,
}
os.Setenv("CC", "clang -target="+*target) os.Setenv("CC", "clang -target="+*target)
@ -420,7 +434,7 @@ func main() {
if target == "" && filepath.Ext(*outpath) == ".wasm" { if target == "" && filepath.Ext(*outpath) == ".wasm" {
target = "wasm" target = "wasm"
} }
err := Build(flag.Arg(0), *outpath, target, *opt, *printIR, *dumpSSA, !*nodebug, *printSize) err := Build(flag.Arg(0), *outpath, target, config)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error:", err) fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1) os.Exit(1)
@ -433,9 +447,14 @@ func main() {
} }
var err error var err error
if command == "flash" { if command == "flash" {
err = Flash(flag.Arg(0), *target, *opt, *port, *printIR, *dumpSSA, !*nodebug, *printSize) err = Flash(flag.Arg(0), *target, *port, config)
} else { } else {
err = FlashGDB(flag.Arg(0), *target, *opt, *port, *printIR, *dumpSSA, *ocdOutput, *printSize) if !config.debug {
fmt.Fprintln(os.Stderr, "Debug disabled while running gdb?")
usage()
os.Exit(1)
}
err = FlashGDB(flag.Arg(0), *target, *port, *ocdOutput, config)
} }
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error:", err) fmt.Fprintln(os.Stderr, "error:", err)
@ -451,7 +470,7 @@ func main() {
if *target == "" { if *target == "" {
err = Run(flag.Arg(0)) err = Run(flag.Arg(0))
} else { } else {
err = Emulate(flag.Arg(0), *target, *opt) err = Emulate(flag.Arg(0), *target, config)
} }
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error:", err) fmt.Fprintln(os.Stderr, "error:", err)

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

@ -59,8 +59,15 @@ func runTest(path, tmpdir string, target string, t *testing.T) {
} }
// Build the test binary. // Build the test binary.
config := &BuildConfig{
opt: "z",
printIR: false,
dumpSSA: false,
debug: false,
printSizes: "",
}
binary := filepath.Join(tmpdir, "test") binary := filepath.Join(tmpdir, "test")
err = Build(path, binary, target, "z", false, false, false, "") err = Build(path, binary, target, config)
if err != nil { if err != nil {
t.Log("failed to build:", err) t.Log("failed to build:", err)
t.Fail() t.Fail()