aboutsummaryrefslogtreecommitdiff
path: root/compiler_wrapper/compiler_wrapper.go
diff options
context:
space:
mode:
Diffstat (limited to 'compiler_wrapper/compiler_wrapper.go')
-rw-r--r--compiler_wrapper/compiler_wrapper.go163
1 files changed, 56 insertions, 107 deletions
diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go
index 2b9459e4..c614b99f 100644
--- a/compiler_wrapper/compiler_wrapper.go
+++ b/compiler_wrapper/compiler_wrapper.go
@@ -5,7 +5,6 @@
package main
import (
- "bytes"
"fmt"
"io"
"path/filepath"
@@ -38,29 +37,6 @@ func callCompiler(env env, cfg *config, inputCmd *command) int {
return exitCode
}
-// Given the main builder path and the absolute path to our wrapper, returns the path to the
-// 'real' compiler we should invoke.
-func calculateAndroidWrapperPath(mainBuilderPath string, absWrapperPath string) string {
- // FIXME: This combination of using the directory of the symlink but the basename of the
- // link target is strange but is the logic that old android wrapper uses. Change this to use
- // directory and basename either from the absWrapperPath or from the builder.path, but don't
- // mix anymore.
-
- // We need to be careful here: path.Join Clean()s its result, so `./foo` will get
- // transformed to `foo`, which isn't good since we're passing this path to exec.
- basePart := filepath.Base(absWrapperPath) + ".real"
- if !strings.ContainsRune(mainBuilderPath, filepath.Separator) {
- return basePart
- }
-
- dirPart := filepath.Dir(mainBuilderPath)
- if cleanResult := filepath.Join(dirPart, basePart); strings.ContainsRune(cleanResult, filepath.Separator) {
- return cleanResult
- }
-
- return "." + string(filepath.Separator) + basePart
-}
-
func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
if err := checkUnsupportedFlags(inputCmd); err != nil {
return 0, err
@@ -75,12 +51,16 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int
var compilerCmd *command
clangSyntax := processClangSyntaxFlag(mainBuilder)
if cfg.isAndroidWrapper {
- mainBuilder.path = calculateAndroidWrapperPath(mainBuilder.path, mainBuilder.absWrapperPath)
+ // FIXME: This combination of using the directory of the symlink but the
+ // basename of the link target is strange but is the logic that old android
+ // wrapper uses. Change this to use directory and basename either from the
+ // absWrapperPath or from the builder.path, but don't mix anymore.
+ mainBuilder.path = filepath.Join(filepath.Dir(mainBuilder.path), filepath.Base(mainBuilder.absWrapperPath)+".real")
+
switch mainBuilder.target.compilerType {
case clangType:
mainBuilder.addPreUserArgs(mainBuilder.cfg.clangFlags...)
mainBuilder.addPreUserArgs(mainBuilder.cfg.commonFlags...)
- mainBuilder.addPostUserArgs(mainBuilder.cfg.clangPostFlags...)
if _, err := processGomaCccFlags(mainBuilder); err != nil {
return 0, err
}
@@ -90,60 +70,45 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int
default:
return 0, newErrorwithSourceLocf("unsupported compiler: %s", mainBuilder.target.compiler)
}
- } else {
- cSrcFile, tidyFlags, tidyMode := processClangTidyFlags(mainBuilder)
- if mainBuilder.target.compilerType == clangType {
- err := prepareClangCommand(mainBuilder)
- if err != nil {
+ } else if mainBuilder.target.compilerType == clangType {
+ cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
+ sysroot, err := prepareClangCommand(mainBuilder)
+ if err != nil {
+ return 0, err
+ }
+ allowCCache := true
+ if useClangTidy {
+ allowCCache = false
+ clangCmdWithoutGomaAndCCache := mainBuilder.build()
+ if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil {
return 0, err
}
- allowCCache := true
- if tidyMode != tidyModeNone {
- allowCCache = false
- clangCmdWithoutGomaAndCCache := mainBuilder.build()
- var err error
- switch tidyMode {
- case tidyModeTricium:
- if cfg.triciumNitsDir == "" {
- return 0, newErrorwithSourceLocf("tricium linting was requested, but no nits directory is configured")
- }
- err = runClangTidyForTricium(env, clangCmdWithoutGomaAndCCache, cSrcFile, cfg.triciumNitsDir, tidyFlags, cfg.crashArtifactsDir)
- case tidyModeAll:
- err = runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile, tidyFlags)
- default:
- panic(fmt.Sprintf("Unknown tidy mode: %v", tidyMode))
- }
-
- if err != nil {
- return 0, err
- }
- }
- if err := processGomaCCacheFlags(allowCCache, mainBuilder); err != nil {
+ }
+ if err := processGomaCCacheFlags(sysroot, allowCCache, mainBuilder); err != nil {
+ return 0, err
+ }
+ compilerCmd = mainBuilder.build()
+ } else {
+ if clangSyntax {
+ allowCCache := false
+ clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
+ if err != nil {
return 0, err
}
- compilerCmd = mainBuilder.build()
- } else {
- if clangSyntax {
- allowCCache := false
- clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
- if err != nil {
- return 0, err
- }
- gccCmd, err := calcGccCommand(mainBuilder)
- if err != nil {
- return 0, err
- }
- return checkClangSyntax(env, clangCmd, gccCmd)
- }
- compilerCmd, err = calcGccCommand(mainBuilder)
+ gccCmd, err := calcGccCommand(mainBuilder)
if err != nil {
return 0, err
}
+ return checkClangSyntax(env, clangCmd, gccCmd)
+ }
+ compilerCmd, err = calcGccCommand(mainBuilder)
+ if err != nil {
+ return 0, err
}
}
rusageLogfileName := getRusageLogFilename(env)
bisectStage := getBisectStage(env)
- if shouldForceDisableWerror(env, cfg) {
+ if shouldForceDisableWError(env) {
if rusageLogfileName != "" {
return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR")
}
@@ -178,33 +143,35 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int
return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
}
-func prepareClangCommand(builder *commandBuilder) (err error) {
+func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) {
+ sysroot = ""
if !builder.cfg.isHostWrapper {
- processSysrootFlag(builder)
+ sysroot = processSysrootFlag(builder)
}
builder.addPreUserArgs(builder.cfg.clangFlags...)
- if builder.cfg.crashArtifactsDir != "" {
- builder.addPreUserArgs("-fcrash-diagnostics-dir=" + builder.cfg.crashArtifactsDir)
- }
builder.addPostUserArgs(builder.cfg.clangPostFlags...)
calcCommonPreUserArgs(builder)
- return processClangFlags(builder)
+ if err := processClangFlags(builder); err != nil {
+ return "", err
+ }
+ return sysroot, nil
}
func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) {
- err := prepareClangCommand(builder)
+ sysroot, err := prepareClangCommand(builder)
if err != nil {
return nil, err
}
- if err := processGomaCCacheFlags(allowCCache, builder); err != nil {
+ if err := processGomaCCacheFlags(sysroot, allowCCache, builder); err != nil {
return nil, err
}
return builder.build(), nil
}
func calcGccCommand(builder *commandBuilder) (*command, error) {
+ sysroot := ""
if !builder.cfg.isHostWrapper {
- processSysrootFlag(builder)
+ sysroot = processSysrootFlag(builder)
}
builder.addPreUserArgs(builder.cfg.gccFlags...)
if !builder.cfg.isHostWrapper {
@@ -213,7 +180,7 @@ func calcGccCommand(builder *commandBuilder) (*command, error) {
processGccFlags(builder)
if !builder.cfg.isHostWrapper {
allowCCache := true
- if err := processGomaCCacheFlags(allowCCache, builder); err != nil {
+ if err := processGomaCCacheFlags(sysroot, allowCCache, builder); err != nil {
return nil, err
}
}
@@ -231,7 +198,7 @@ func calcCommonPreUserArgs(builder *commandBuilder) {
processSanitizerFlags(builder)
}
-func processGomaCCacheFlags(allowCCache bool, builder *commandBuilder) (err error) {
+func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) (err error) {
gomaccUsed := false
if !builder.cfg.isHostWrapper {
gomaccUsed, err = processGomaCccFlags(builder)
@@ -240,7 +207,7 @@ func processGomaCCacheFlags(allowCCache bool, builder *commandBuilder) (err erro
}
}
if !gomaccUsed && allowCCache {
- processCCacheFlag(builder)
+ processCCacheFlag(sysroot, builder)
}
return nil
}
@@ -258,40 +225,22 @@ func printCompilerError(writer io.Writer, compilerErr error) {
if _, ok := compilerErr.(userError); ok {
fmt.Fprintf(writer, "%s\n", compilerErr)
} else {
- emailAccount := "chromeos-toolchain"
- if isAndroidConfig() {
- emailAccount = "android-llvm"
- }
fmt.Fprintf(writer,
- "Internal error. Please report to %s@google.com.\n%s\n",
- emailAccount, compilerErr)
+ "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
+ compilerErr)
}
}
-func needStdinTee(inputCmd *command) bool {
+func teeStdinIfNeeded(env env, inputCmd *command, dest io.Writer) io.Reader {
+ // We can't use io.TeeReader unconditionally, as that would block
+ // calls to exec.Cmd.Run(), even if the underlying process has already
+ // terminated. See https://github.com/golang/go/issues/7990 for more details.
lastArg := ""
for _, arg := range inputCmd.Args {
if arg == "-" && lastArg != "-o" {
- return true
+ return io.TeeReader(env.stdin(), dest)
}
lastArg = arg
}
- return false
-}
-
-func prebufferStdinIfNeeded(env env, inputCmd *command) (getStdin func() io.Reader, err error) {
- // We pre-buffer the entirety of stdin, since the compiler may exit mid-invocation with an
- // error, which may leave stdin partially read.
- if !needStdinTee(inputCmd) {
- // This won't produce deterministic input to the compiler, but stdin shouldn't
- // matter in this case, so...
- return env.stdin, nil
- }
-
- stdinBuffer := &bytes.Buffer{}
- if _, err := stdinBuffer.ReadFrom(env.stdin()); err != nil {
- return nil, wrapErrorwithSourceLocf(err, "prebuffering stdin")
- }
-
- return func() io.Reader { return bytes.NewReader(stdinBuffer.Bytes()) }, nil
+ return env.stdin()
}