diff options
author | Ayke van Laethem <[email protected]> | 2020-04-02 21:14:07 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2020-04-03 12:41:44 +0200 |
commit | f06d7d1bd6cf5d5231dde4de8ef4ae5ecd908074 (patch) | |
tree | 75a607804bb0323a9d782e662bf3c96a3a962dcf /builder/tools.go | |
parent | 407149e323d8235cf8bce153201195ddbe2eaa65 (diff) | |
download | tinygo-f06d7d1bd6cf5d5231dde4de8ef4ae5ecd908074.tar.gz tinygo-f06d7d1bd6cf5d5231dde4de8ef4ae5ecd908074.zip |
builder: run tools (clang, ...) as separate processes
This is necessary because LLVM defines many options in global variables
that are modified when invoking Clang. In particular, LLVM 10 seems to
have a bug in which it always sets the -pgo-warn-misexpect flag. Setting
it multiple times (over various cc1 invocations) results in an error:
clang (LLVM option parsing): for the --pgo-warn-misexpect option: may only occur zero or one times!
This is fixed by running the Clang invocation in a new `tinygo`
invocation.
Because we've had issues with lld in the past, also run lld in a
separate process so similar issues won't happen with lld in the future.
Diffstat (limited to 'builder/tools.go')
-rw-r--r-- | builder/tools.go | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/builder/tools.go b/builder/tools.go new file mode 100644 index 000000000..bc0f97824 --- /dev/null +++ b/builder/tools.go @@ -0,0 +1,59 @@ +package builder + +import ( + "errors" + "os" + "os/exec" + + "github.com/tinygo-org/tinygo/goenv" +) + +// runCCompiler invokes a C compiler with the given arguments. +func runCCompiler(command string, flags ...string) error { + if hasBuiltinTools && command == "clang" { + // Compile this with the internal Clang compiler. + headerPath := getClangHeaderPath(goenv.Get("TINYGOROOT")) + if headerPath == "" { + return errors.New("could not locate Clang headers") + } + flags = append(flags, "-I"+headerPath) + cmd := exec.Command(os.Args[0], append([]string{"clang"}, flags...)...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() + } + + // Running some other compiler. Maybe it has been defined in the + // commands map (unlikely). + if cmdNames, ok := commands[command]; ok { + return execCommand(cmdNames, flags...) + } + + // Alternatively, run the compiler directly. + cmd := exec.Command(command, flags...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +// link invokes a linker with the given name and flags. +func link(linker string, flags ...string) error { + if hasBuiltinTools && (linker == "ld.lld" || linker == "wasm-ld") { + // Run command with internal linker. + cmd := exec.Command(os.Args[0], append([]string{linker}, flags...)...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() + } + + // Fall back to external command. + if cmdNames, ok := commands[linker]; ok { + return execCommand(cmdNames, flags...) + } + + cmd := exec.Command(linker, flags...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Dir = goenv.Get("TINYGOROOT") + return cmd.Run() +} |