diff options
Diffstat (limited to 'compiler_wrapper/compiler_wrapper.go')
-rw-r--r-- | compiler_wrapper/compiler_wrapper.go | 223 |
1 files changed, 46 insertions, 177 deletions
diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go index 986eabab..2b9459e4 100644 --- a/compiler_wrapper/compiler_wrapper.go +++ b/compiler_wrapper/compiler_wrapper.go @@ -6,14 +6,10 @@ package main import ( "bytes" - "context" - "errors" "fmt" "io" "path/filepath" - "strconv" "strings" - "time" ) func callCompiler(env env, cfg *config, inputCmd *command) int { @@ -65,50 +61,6 @@ func calculateAndroidWrapperPath(mainBuilderPath string, absWrapperPath string) return "." + string(filepath.Separator) + basePart } -func runAndroidClangTidy(env env, cmd *command) error { - timeout, found := env.getenv("TIDY_TIMEOUT") - if !found { - return env.exec(cmd) - } - seconds, err := strconv.Atoi(timeout) - if err != nil || seconds == 0 { - return env.exec(cmd) - } - getSourceFile := func() string { - // Note: This depends on Android build system's clang-tidy command line format. - // Last non-flag before "--" in cmd.Args is used as the source file name. - sourceFile := "unknown_file" - for _, arg := range cmd.Args { - if arg == "--" { - break - } - if strings.HasPrefix(arg, "-") { - continue - } - sourceFile = arg - } - return sourceFile - } - startTime := time.Now() - err = env.runWithTimeout(cmd, time.Duration(seconds)*time.Second) - if !errors.Is(err, context.DeadlineExceeded) { - // When used time is over half of TIDY_TIMEOUT, give a warning. - // These warnings allow users to fix slow jobs before they get worse. - usedSeconds := int(time.Now().Sub(startTime) / time.Second) - if usedSeconds > seconds/2 { - warning := "%s:1:1: warning: clang-tidy used %d seconds.\n" - fmt.Fprintf(env.stdout(), warning, getSourceFile(), usedSeconds) - } - return err - } - // When DeadllineExceeded, print warning messages. - warning := "%s:1:1: warning: clang-tidy aborted after %d seconds.\n" - fmt.Fprintf(env.stdout(), warning, getSourceFile(), seconds) - fmt.Fprintf(env.stdout(), "TIMEOUT: %s %s\n", cmd.Path, strings.Join(cmd.Args, " ")) - // Do not stop Android build. Just give a warning and return no error. - return nil -} - func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) { if err := checkUnsupportedFlags(inputCmd); err != nil { return 0, err @@ -122,15 +74,6 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int env = mainBuilder.env var compilerCmd *command clangSyntax := processClangSyntaxFlag(mainBuilder) - - rusageEnabled := isRusageEnabled(env) - - // Disable CCache for rusage logs - // Note: Disabling Goma causes timeout related INFRA_FAILUREs in builders - allowCCache := !rusageEnabled - remoteBuildUsed := false - - workAroundKernelBugWithRetries := false if cfg.isAndroidWrapper { mainBuilder.path = calculateAndroidWrapperPath(mainBuilder.path, mainBuilder.absWrapperPath) switch mainBuilder.target.compilerType { @@ -138,9 +81,7 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int mainBuilder.addPreUserArgs(mainBuilder.cfg.clangFlags...) mainBuilder.addPreUserArgs(mainBuilder.cfg.commonFlags...) mainBuilder.addPostUserArgs(mainBuilder.cfg.clangPostFlags...) - inheritGomaFromEnv := true - // Android doesn't support rewrapper; don't try to use it. - if remoteBuildUsed, err = processGomaCccFlags(mainBuilder, inheritGomaFromEnv); err != nil { + if _, err := processGomaCccFlags(mainBuilder); err != nil { return 0, err } compilerCmd = mainBuilder.build() @@ -156,18 +97,19 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int if err != nil { return 0, err } + allowCCache := true if tidyMode != tidyModeNone { allowCCache = false - clangCmdWithoutRemoteBuildAndCCache := mainBuilder.build() + 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, clangCmdWithoutRemoteBuildAndCCache, cSrcFile, cfg.triciumNitsDir, tidyFlags, cfg.crashArtifactsDir) + err = runClangTidyForTricium(env, clangCmdWithoutGomaAndCCache, cSrcFile, cfg.triciumNitsDir, tidyFlags, cfg.crashArtifactsDir) case tidyModeAll: - err = runClangTidy(env, clangCmdWithoutRemoteBuildAndCCache, cSrcFile, tidyFlags) + err = runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile, tidyFlags) default: panic(fmt.Sprintf("Unknown tidy mode: %v", tidyMode)) } @@ -176,135 +118,64 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int return 0, err } } - if remoteBuildUsed, err = processRemoteBuildAndCCacheFlags(allowCCache, mainBuilder); err != nil { + if err := processGomaCCacheFlags(allowCCache, mainBuilder); err != nil { return 0, err } compilerCmd = mainBuilder.build() } else { if clangSyntax { - allowCCache = false - _, clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone()) + allowCCache := false + clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone()) if err != nil { return 0, err } - _, gccCmd, err := calcGccCommand(rusageEnabled, mainBuilder) + gccCmd, err := calcGccCommand(mainBuilder) if err != nil { return 0, err } return checkClangSyntax(env, clangCmd, gccCmd) } - remoteBuildUsed, compilerCmd, err = calcGccCommand(rusageEnabled, mainBuilder) + compilerCmd, err = calcGccCommand(mainBuilder) if err != nil { return 0, err } - workAroundKernelBugWithRetries = true } } - + rusageLogfileName := getRusageLogFilename(env) bisectStage := getBisectStage(env) - - if rusageEnabled { - compilerCmd = removeRusageFromCommand(compilerCmd) - } - - if shouldForceDisableWerror(env, cfg, mainBuilder.target.compilerType) { + if shouldForceDisableWerror(env, cfg) { + if rusageLogfileName != "" { + return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR") + } if bisectStage != "" { return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR") } return doubleBuildWithWNoError(env, cfg, compilerCmd) } if shouldCompileWithFallback(env) { - if rusageEnabled { - return 0, newUserErrorf("TOOLCHAIN_RUSAGE_OUTPUT is meaningless with ANDROID_LLVM_PREBUILT_COMPILER_PATH") + if rusageLogfileName != "" { + return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR") } if bisectStage != "" { - return 0, newUserErrorf("BISECT_STAGE is meaningless with ANDROID_LLVM_PREBUILT_COMPILER_PATH") + return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR") } return compileWithFallback(env, cfg, compilerCmd, mainBuilder.absWrapperPath) } - if bisectStage != "" { - if rusageEnabled { - return 0, newUserErrorf("TOOLCHAIN_RUSAGE_OUTPUT is meaningless with BISECT_STAGE") + if rusageLogfileName != "" { + if bisectStage != "" { + return 0, newUserErrorf("BISECT_STAGE is meaningless with GETRUSAGE") } + return logRusage(env, rusageLogfileName, compilerCmd) + } + if bisectStage != "" { compilerCmd, err = calcBisectCommand(env, cfg, bisectStage, compilerCmd) if err != nil { return 0, err } } - - errRetryCompilation := errors.New("compilation retry requested") - var runCompiler func(willLogRusage bool) (int, error) - if !workAroundKernelBugWithRetries { - runCompiler = func(willLogRusage bool) (int, error) { - var err error - if willLogRusage { - err = env.run(compilerCmd, env.stdin(), env.stdout(), env.stderr()) - } else if cfg.isAndroidWrapper && mainBuilder.target.compilerType == clangTidyType { - // Only clang-tidy has timeout feature now. - err = runAndroidClangTidy(env, compilerCmd) - } else { - // Note: We return from this in non-fatal circumstances only if the - // underlying env is not really doing an exec, e.g. commandRecordingEnv. - err = env.exec(compilerCmd) - } - return wrapSubprocessErrorWithSourceLoc(compilerCmd, err) - } - } else { - getStdin, err := prebufferStdinIfNeeded(env, compilerCmd) - if err != nil { - return 0, wrapErrorwithSourceLocf(err, "prebuffering stdin: %v", err) - } - - stdoutBuffer := &bytes.Buffer{} - stderrBuffer := &bytes.Buffer{} - retryAttempt := 0 - runCompiler = func(willLogRusage bool) (int, error) { - retryAttempt++ - stdoutBuffer.Reset() - stderrBuffer.Reset() - - exitCode, compilerErr := wrapSubprocessErrorWithSourceLoc(compilerCmd, - env.run(compilerCmd, getStdin(), stdoutBuffer, stderrBuffer)) - - if compilerErr != nil || exitCode != 0 { - if retryAttempt < kernelBugRetryLimit && (errorContainsTracesOfKernelBug(compilerErr) || containsTracesOfKernelBug(stdoutBuffer.Bytes()) || containsTracesOfKernelBug(stderrBuffer.Bytes())) { - return exitCode, errRetryCompilation - } - } - _, stdoutErr := stdoutBuffer.WriteTo(env.stdout()) - _, stderrErr := stderrBuffer.WriteTo(env.stderr()) - if stdoutErr != nil { - return exitCode, wrapErrorwithSourceLocf(err, "writing stdout: %v", stdoutErr) - } - if stderrErr != nil { - return exitCode, wrapErrorwithSourceLocf(err, "writing stderr: %v", stderrErr) - } - return exitCode, compilerErr - } - } - - for { - var exitCode int - commitRusage, err := maybeCaptureRusage(env, compilerCmd, func(willLogRusage bool) error { - var err error - exitCode, err = runCompiler(willLogRusage) - return err - }) - - switch { - case err == errRetryCompilation: - // Loop around again. - case err != nil: - return exitCode, err - default: - if !remoteBuildUsed { - if err := commitRusage(exitCode); err != nil { - return exitCode, fmt.Errorf("commiting rusage: %v", err) - } - } - return exitCode, err - } - } + // Note: We return an exit code only if the underlying env is not + // really doing an exec, e.g. commandRecordingEnv. + return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd)) } func prepareClangCommand(builder *commandBuilder) (err error) { @@ -320,40 +191,38 @@ func prepareClangCommand(builder *commandBuilder) (err error) { return processClangFlags(builder) } -func calcClangCommand(allowCCache bool, builder *commandBuilder) (bool, *command, error) { +func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) { err := prepareClangCommand(builder) if err != nil { - return false, nil, err + return nil, err } - remoteBuildUsed, err := processRemoteBuildAndCCacheFlags(allowCCache, builder) - if err != nil { - return remoteBuildUsed, nil, err + if err := processGomaCCacheFlags(allowCCache, builder); err != nil { + return nil, err } - return remoteBuildUsed, builder.build(), nil + return builder.build(), nil } -func calcGccCommand(enableRusage bool, builder *commandBuilder) (bool, *command, error) { +func calcGccCommand(builder *commandBuilder) (*command, error) { if !builder.cfg.isHostWrapper { processSysrootFlag(builder) } builder.addPreUserArgs(builder.cfg.gccFlags...) - calcCommonPreUserArgs(builder) + if !builder.cfg.isHostWrapper { + calcCommonPreUserArgs(builder) + } processGccFlags(builder) - - remoteBuildUsed := false if !builder.cfg.isHostWrapper { - var err error - if remoteBuildUsed, err = processRemoteBuildAndCCacheFlags(!enableRusage, builder); err != nil { - return remoteBuildUsed, nil, err + allowCCache := true + if err := processGomaCCacheFlags(allowCCache, builder); err != nil { + return nil, err } } - return remoteBuildUsed, builder.build(), nil + return builder.build(), nil } func calcCommonPreUserArgs(builder *commandBuilder) { builder.addPreUserArgs(builder.cfg.commonFlags...) if !builder.cfg.isHostWrapper { - processLibGCCFlags(builder) processPieFlags(builder) processThumbCodeFlags(builder) processStackProtectorFlags(builder) @@ -362,18 +231,18 @@ func calcCommonPreUserArgs(builder *commandBuilder) { processSanitizerFlags(builder) } -func processRemoteBuildAndCCacheFlags(allowCCache bool, builder *commandBuilder) (remoteBuildUsed bool, err error) { - remoteBuildUsed = false +func processGomaCCacheFlags(allowCCache bool, builder *commandBuilder) (err error) { + gomaccUsed := false if !builder.cfg.isHostWrapper { - remoteBuildUsed, err = processRemoteBuildFlags(builder) + gomaccUsed, err = processGomaCccFlags(builder) if err != nil { - return remoteBuildUsed, err + return err } } - if !remoteBuildUsed && allowCCache { + if !gomaccUsed && allowCCache { processCCacheFlag(builder) } - return remoteBuildUsed, nil + return nil } func getAbsWrapperPath(env env, wrapperCmd *command) (string, error) { |