blob: 9d7b76e56e5bc83292743e2c2e505136efd26023 [file] [log] [blame]
Tobias Boschcfa8c242019-07-19 03:29:40 -07001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Tobias Boschef8f9692019-06-10 15:50:33 -07005package main
6
7import (
George Burgess IV26caa2f2020-02-28 14:36:01 -08008 "bytes"
George Burgess IVcbc852e2021-01-25 13:11:02 -08009 "errors"
Tobias Bosch900dbc92019-06-24 09:31:39 -070010 "fmt"
11 "io"
Tobias Boschef8f9692019-06-10 15:50:33 -070012 "path/filepath"
Tobias Bosch5f98f2d2019-08-15 17:17:57 -070013 "strings"
Tobias Boschef8f9692019-06-10 15:50:33 -070014)
15
Tobias Bosch900dbc92019-06-24 09:31:39 -070016func callCompiler(env env, cfg *config, inputCmd *command) int {
Tobias Bosch900dbc92019-06-24 09:31:39 -070017 var compilerErr error
Tobias Bosch5edca502019-08-26 12:53:41 -070018
19 if !filepath.IsAbs(inputCmd.Path) && !strings.HasPrefix(inputCmd.Path, ".") &&
20 !strings.ContainsRune(inputCmd.Path, filepath.Separator) {
Tobias Bosch5f98f2d2019-08-15 17:17:57 -070021 if resolvedPath, err := resolveAgainstPathEnv(env, inputCmd.Path); err == nil {
22 inputCmd = &command{
23 Path: resolvedPath,
24 Args: inputCmd.Args,
25 EnvUpdates: inputCmd.EnvUpdates,
26 }
27 } else {
28 compilerErr = err
29 }
30 }
31 exitCode := 0
32 if compilerErr == nil {
Tobias Bosch8dd67e12019-10-28 14:26:51 -070033 exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd)
Tobias Bosch900dbc92019-06-24 09:31:39 -070034 }
35 if compilerErr != nil {
36 printCompilerError(env.stderr(), compilerErr)
37 exitCode = 1
38 }
39 return exitCode
40}
41
George Burgess IVc94f2432020-03-04 17:32:44 -080042// Given the main builder path and the absolute path to our wrapper, returns the path to the
43// 'real' compiler we should invoke.
44func calculateAndroidWrapperPath(mainBuilderPath string, absWrapperPath string) string {
45 // FIXME: This combination of using the directory of the symlink but the basename of the
46 // link target is strange but is the logic that old android wrapper uses. Change this to use
47 // directory and basename either from the absWrapperPath or from the builder.path, but don't
48 // mix anymore.
49
50 // We need to be careful here: path.Join Clean()s its result, so `./foo` will get
51 // transformed to `foo`, which isn't good since we're passing this path to exec.
52 basePart := filepath.Base(absWrapperPath) + ".real"
53 if !strings.ContainsRune(mainBuilderPath, filepath.Separator) {
54 return basePart
55 }
56
57 dirPart := filepath.Dir(mainBuilderPath)
58 if cleanResult := filepath.Join(dirPart, basePart); strings.ContainsRune(cleanResult, filepath.Separator) {
59 return cleanResult
60 }
61
62 return "." + string(filepath.Separator) + basePart
63}
64
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070065func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
Tobias Bosch900dbc92019-06-24 09:31:39 -070066 if err := checkUnsupportedFlags(inputCmd); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070067 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070068 }
Tobias Boschd8684172019-07-08 10:59:14 -070069 mainBuilder, err := newCommandBuilder(env, cfg, inputCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -070070 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070071 return 0, err
Tobias Boschef8f9692019-06-10 15:50:33 -070072 }
Tobias Bosch58472812019-07-11 04:24:52 -070073 processPrintConfigFlag(mainBuilder)
74 processPrintCmdlineFlag(mainBuilder)
75 env = mainBuilder.env
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070076 var compilerCmd *command
Tobias Boschd8684172019-07-08 10:59:14 -070077 clangSyntax := processClangSyntaxFlag(mainBuilder)
George Burgess IVcbc852e2021-01-25 13:11:02 -080078
Ryan Beltran7c59ee02021-02-22 23:58:40 +000079 rusageEnabled := isRusageEnabled(env)
80
Ryan Beltraned235352021-03-22 19:30:54 +000081 // Disable CCache for rusage logs
82 // Note: Disabling Goma causes timeout related INFRA_FAILUREs in builders
Ryan Beltran7c59ee02021-02-22 23:58:40 +000083 allowCCache := !rusageEnabled
Ryan Beltrancc6e72a2021-04-20 16:10:49 +000084 gomaUsed := false
Ryan Beltran7c59ee02021-02-22 23:58:40 +000085
George Burgess IVcbc852e2021-01-25 13:11:02 -080086 workAroundKernelBugWithRetries := false
Tobias Bosch8cb363f2019-10-17 07:44:13 -070087 if cfg.isAndroidWrapper {
George Burgess IVc94f2432020-03-04 17:32:44 -080088 mainBuilder.path = calculateAndroidWrapperPath(mainBuilder.path, mainBuilder.absWrapperPath)
Tobias Bosch8cb363f2019-10-17 07:44:13 -070089 switch mainBuilder.target.compilerType {
90 case clangType:
91 mainBuilder.addPreUserArgs(mainBuilder.cfg.clangFlags...)
92 mainBuilder.addPreUserArgs(mainBuilder.cfg.commonFlags...)
Pirama Arumuga Nainarefb75cf2020-10-21 13:57:01 -070093 mainBuilder.addPostUserArgs(mainBuilder.cfg.clangPostFlags...)
Ryan Beltrancc6e72a2021-04-20 16:10:49 +000094 if gomaUsed, err = processGomaCccFlags(mainBuilder); err != nil {
Tobias Bosch8cb363f2019-10-17 07:44:13 -070095 return 0, err
96 }
97 compilerCmd = mainBuilder.build()
98 case clangTidyType:
99 compilerCmd = mainBuilder.build()
100 default:
101 return 0, newErrorwithSourceLocf("unsupported compiler: %s", mainBuilder.target.compiler)
102 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700103 } else {
George Burgess IVcb465002020-07-20 16:53:39 -0700104 cSrcFile, tidyFlags, tidyMode := processClangTidyFlags(mainBuilder)
105 if mainBuilder.target.compilerType == clangType {
106 err := prepareClangCommand(mainBuilder)
Tobias Boschd8684172019-07-08 10:59:14 -0700107 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -0700108 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -0700109 }
George Burgess IVcb465002020-07-20 16:53:39 -0700110 if tidyMode != tidyModeNone {
111 allowCCache = false
112 clangCmdWithoutGomaAndCCache := mainBuilder.build()
113 var err error
114 switch tidyMode {
115 case tidyModeTricium:
116 if cfg.triciumNitsDir == "" {
117 return 0, newErrorwithSourceLocf("tricium linting was requested, but no nits directory is configured")
118 }
George Burgess IV0a377f42020-08-05 15:03:36 -0700119 err = runClangTidyForTricium(env, clangCmdWithoutGomaAndCCache, cSrcFile, cfg.triciumNitsDir, tidyFlags, cfg.crashArtifactsDir)
George Burgess IVcb465002020-07-20 16:53:39 -0700120 case tidyModeAll:
121 err = runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile, tidyFlags)
122 default:
123 panic(fmt.Sprintf("Unknown tidy mode: %v", tidyMode))
124 }
125
126 if err != nil {
127 return 0, err
128 }
129 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000130 if gomaUsed, err = processGomaCCacheFlags(allowCCache, mainBuilder); err != nil {
George Burgess IVcb465002020-07-20 16:53:39 -0700131 return 0, err
132 }
133 compilerCmd = mainBuilder.build()
134 } else {
135 if clangSyntax {
Ryan Beltran7c59ee02021-02-22 23:58:40 +0000136 allowCCache = false
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000137 _, clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
George Burgess IVcb465002020-07-20 16:53:39 -0700138 if err != nil {
139 return 0, err
140 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000141 _, gccCmd, err := calcGccCommand(rusageEnabled, mainBuilder)
George Burgess IVcb465002020-07-20 16:53:39 -0700142 if err != nil {
143 return 0, err
144 }
145 return checkClangSyntax(env, clangCmd, gccCmd)
146 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000147 gomaUsed, compilerCmd, err = calcGccCommand(rusageEnabled, mainBuilder)
Tobias Boschc58f8d52019-09-30 10:37:42 -0700148 if err != nil {
149 return 0, err
150 }
George Burgess IVcbc852e2021-01-25 13:11:02 -0800151 workAroundKernelBugWithRetries = true
Tobias Boschc58f8d52019-09-30 10:37:42 -0700152 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700153 }
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000154
Tobias Bosch9780ea92019-07-11 01:19:42 -0700155 bisectStage := getBisectStage(env)
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000156
Ryan Beltran7c59ee02021-02-22 23:58:40 +0000157 if rusageEnabled {
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000158 compilerCmd = removeRusageFromCommand(compilerCmd)
159 }
160
George Burgess IV81267152021-01-25 12:11:56 -0800161 if shouldForceDisableWerror(env, cfg, mainBuilder.target.compilerType) {
Tobias Bosch9780ea92019-07-11 01:19:42 -0700162 if bisectStage != "" {
163 return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR")
164 }
Ryan Beltran7c59ee02021-02-22 23:58:40 +0000165 return doubleBuildWithWNoError(env, cfg, compilerCmd)
Tobias Boschf6d9f4f2019-07-09 08:09:01 -0700166 }
Tobias Boschc88ee8a2019-10-01 15:00:52 -0700167 if shouldCompileWithFallback(env) {
Ryan Beltran7c59ee02021-02-22 23:58:40 +0000168 if rusageEnabled {
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000169 return 0, newUserErrorf("TOOLCHAIN_RUSAGE_OUTPUT is meaningless with ANDROID_LLVM_PREBUILT_COMPILER_PATH")
Tobias Boschc88ee8a2019-10-01 15:00:52 -0700170 }
171 if bisectStage != "" {
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000172 return 0, newUserErrorf("BISECT_STAGE is meaningless with ANDROID_LLVM_PREBUILT_COMPILER_PATH")
Tobias Boschc88ee8a2019-10-01 15:00:52 -0700173 }
174 return compileWithFallback(env, cfg, compilerCmd, mainBuilder.absWrapperPath)
175 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700176 if bisectStage != "" {
Ryan Beltran7c59ee02021-02-22 23:58:40 +0000177 if rusageEnabled {
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000178 return 0, newUserErrorf("TOOLCHAIN_RUSAGE_OUTPUT is meaningless with BISECT_STAGE")
179 }
Tobias Bosch820bffa2019-09-30 15:53:52 -0700180 compilerCmd, err = calcBisectCommand(env, cfg, bisectStage, compilerCmd)
181 if err != nil {
182 return 0, err
183 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700184 }
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000185
George Burgess IVcbc852e2021-01-25 13:11:02 -0800186 errRetryCompilation := errors.New("compilation retry requested")
187 var runCompiler func(willLogRusage bool) (int, error)
188 if !workAroundKernelBugWithRetries {
189 runCompiler = func(willLogRusage bool) (int, error) {
190 var err error
191 if willLogRusage {
192 err = env.run(compilerCmd, env.stdin(), env.stdout(), env.stderr())
193 } else {
194 // Note: We return from this in non-fatal circumstances only if the
195 // underlying env is not really doing an exec, e.g. commandRecordingEnv.
196 err = env.exec(compilerCmd)
197 }
198 return wrapSubprocessErrorWithSourceLoc(compilerCmd, err)
George Burgess IVde5be162021-01-25 15:50:54 -0800199 }
George Burgess IVcbc852e2021-01-25 13:11:02 -0800200 } else {
201 getStdin, err := prebufferStdinIfNeeded(env, compilerCmd)
202 if err != nil {
203 return 0, wrapErrorwithSourceLocf(err, "prebuffering stdin: %v", err)
204 }
205
206 stdoutBuffer := &bytes.Buffer{}
207 stderrBuffer := &bytes.Buffer{}
208 retryAttempt := 0
209 runCompiler = func(willLogRusage bool) (int, error) {
210 retryAttempt++
211 stdoutBuffer.Reset()
212 stderrBuffer.Reset()
213
214 exitCode, compilerErr := wrapSubprocessErrorWithSourceLoc(compilerCmd,
215 env.run(compilerCmd, getStdin(), stdoutBuffer, stderrBuffer))
216
217 if compilerErr != nil || exitCode != 0 {
218 if retryAttempt < kernelBugRetryLimit && (errorContainsTracesOfKernelBug(compilerErr) || containsTracesOfKernelBug(stdoutBuffer.Bytes()) || containsTracesOfKernelBug(stderrBuffer.Bytes())) {
219 return exitCode, errRetryCompilation
220 }
221 }
222 _, stdoutErr := stdoutBuffer.WriteTo(env.stdout())
223 _, stderrErr := stderrBuffer.WriteTo(env.stderr())
224 if stdoutErr != nil {
225 return exitCode, wrapErrorwithSourceLocf(err, "writing stdout: %v", stdoutErr)
226 }
227 if stderrErr != nil {
228 return exitCode, wrapErrorwithSourceLocf(err, "writing stderr: %v", stderrErr)
229 }
230 return exitCode, compilerErr
231 }
Ryan Beltran7ee49e42021-01-19 01:52:42 +0000232 }
233
George Burgess IVcbc852e2021-01-25 13:11:02 -0800234 for {
235 var exitCode int
Ryan Beltran7c59ee02021-02-22 23:58:40 +0000236 commitRusage, err := maybeCaptureRusage(env, compilerCmd, func(willLogRusage bool) error {
George Burgess IVcbc852e2021-01-25 13:11:02 -0800237 var err error
238 exitCode, err = runCompiler(willLogRusage)
239 return err
240 })
241
242 switch {
243 case err == errRetryCompilation:
244 // Loop around again.
245 case err != nil:
246 return exitCode, err
247 default:
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000248 if !gomaUsed {
249 if err := commitRusage(exitCode); err != nil {
250 return exitCode, fmt.Errorf("commiting rusage: %v", err)
251 }
George Burgess IVcbc852e2021-01-25 13:11:02 -0800252 }
George Burgess IVcbc852e2021-01-25 13:11:02 -0800253 return exitCode, err
254 }
255 }
Tobias Boschd8684172019-07-08 10:59:14 -0700256}
257
Manoj Gupta28979262020-03-13 11:05:26 -0700258func prepareClangCommand(builder *commandBuilder) (err error) {
Tobias Bosch8cb363f2019-10-17 07:44:13 -0700259 if !builder.cfg.isHostWrapper {
Manoj Gupta28979262020-03-13 11:05:26 -0700260 processSysrootFlag(builder)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700261 }
Tobias Boschd8684172019-07-08 10:59:14 -0700262 builder.addPreUserArgs(builder.cfg.clangFlags...)
George Burgess IV1713d252020-08-07 19:17:52 -0700263 if builder.cfg.crashArtifactsDir != "" {
264 builder.addPreUserArgs("-fcrash-diagnostics-dir=" + builder.cfg.crashArtifactsDir)
265 }
Caroline Tice8ac33e02019-10-28 09:48:18 -0700266 builder.addPostUserArgs(builder.cfg.clangPostFlags...)
Tobias Boschd8684172019-07-08 10:59:14 -0700267 calcCommonPreUserArgs(builder)
Manoj Gupta28979262020-03-13 11:05:26 -0700268 return processClangFlags(builder)
Tobias Bosch198a3c92019-07-17 04:22:34 -0700269}
270
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000271func calcClangCommand(allowCCache bool, builder *commandBuilder) (bool, *command, error) {
Manoj Gupta28979262020-03-13 11:05:26 -0700272 err := prepareClangCommand(builder)
Tobias Bosch198a3c92019-07-17 04:22:34 -0700273 if err != nil {
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000274 return false, nil, err
Tobias Boschd8684172019-07-08 10:59:14 -0700275 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000276 gomaUsed, err := processGomaCCacheFlags(allowCCache, builder)
277 if err != nil {
278 return gomaUsed, nil, err
Tobias Boschc58f8d52019-09-30 10:37:42 -0700279 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000280 return gomaUsed, builder.build(), nil
Tobias Boschd8684172019-07-08 10:59:14 -0700281}
282
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000283func calcGccCommand(enableRusage bool, builder *commandBuilder) (bool, *command, error) {
Tobias Boschb27c8f22019-07-19 06:53:07 -0700284 if !builder.cfg.isHostWrapper {
Manoj Gupta28979262020-03-13 11:05:26 -0700285 processSysrootFlag(builder)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700286 }
Tobias Boschd8684172019-07-08 10:59:14 -0700287 builder.addPreUserArgs(builder.cfg.gccFlags...)
Manoj Guptaefefb1a2021-01-28 21:46:53 -0800288 calcCommonPreUserArgs(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700289 processGccFlags(builder)
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000290
291 gomaUsed := false
Tobias Boschb27c8f22019-07-19 06:53:07 -0700292 if !builder.cfg.isHostWrapper {
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000293 var err error
294 if gomaUsed, err = processGomaCCacheFlags(!enableRusage, builder); err != nil {
295 return gomaUsed, nil, err
Tobias Boschc58f8d52019-09-30 10:37:42 -0700296 }
Tobias Boschb27c8f22019-07-19 06:53:07 -0700297 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000298 return gomaUsed, builder.build(), nil
Tobias Boschd8684172019-07-08 10:59:14 -0700299}
300
301func calcCommonPreUserArgs(builder *commandBuilder) {
302 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Bosch8cb363f2019-10-17 07:44:13 -0700303 if !builder.cfg.isHostWrapper {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700304 processPieFlags(builder)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700305 processThumbCodeFlags(builder)
Tobias Bosch1cd5f842019-08-20 10:05:33 -0700306 processStackProtectorFlags(builder)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700307 processX86Flags(builder)
308 }
Tobias Bosch8cb363f2019-10-17 07:44:13 -0700309 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700310}
311
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000312func processGomaCCacheFlags(allowCCache bool, builder *commandBuilder) (gomaccUsed bool, err error) {
313
314 gomaccUsed = false
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700315 if !builder.cfg.isHostWrapper {
Ryan Beltran1f5fbfa2021-04-13 08:57:02 +0000316 gomaccUsed, err = processGomaCccFlags(builder)
Tobias Boschc58f8d52019-09-30 10:37:42 -0700317 if err != nil {
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000318 return gomaccUsed, err
Tobias Boschc58f8d52019-09-30 10:37:42 -0700319 }
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700320 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700321 if !gomaccUsed && allowCCache {
Manoj Gupta28979262020-03-13 11:05:26 -0700322 processCCacheFlag(builder)
Tobias Boschef8f9692019-06-10 15:50:33 -0700323 }
Ryan Beltrancc6e72a2021-04-20 16:10:49 +0000324 return gomaccUsed, nil
Tobias Boschef8f9692019-06-10 15:50:33 -0700325}
326
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700327func getAbsWrapperPath(env env, wrapperCmd *command) (string, error) {
Tobias Bosch58472812019-07-11 04:24:52 -0700328 wrapperPath := getAbsCmdPath(env, wrapperCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -0700329 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
330 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700331 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700332 }
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700333 return evaledCmdPath, nil
Tobias Boschef8f9692019-06-10 15:50:33 -0700334}
335
Tobias Bosch900dbc92019-06-24 09:31:39 -0700336func printCompilerError(writer io.Writer, compilerErr error) {
337 if _, ok := compilerErr.(userError); ok {
338 fmt.Fprintf(writer, "%s\n", compilerErr)
339 } else {
George Burgess IV2efe72e2020-06-18 20:37:28 -0700340 emailAccount := "chromeos-toolchain"
341 if isAndroidConfig() {
342 emailAccount = "android-llvm"
343 }
Tobias Bosch900dbc92019-06-24 09:31:39 -0700344 fmt.Fprintf(writer,
George Burgess IV2efe72e2020-06-18 20:37:28 -0700345 "Internal error. Please report to %s@google.com.\n%s\n",
346 emailAccount, compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700347 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700348}
Tobias Bosch6f59a662019-08-20 15:37:11 -0700349
George Burgess IV26caa2f2020-02-28 14:36:01 -0800350func needStdinTee(inputCmd *command) bool {
Tobias Bosch6f59a662019-08-20 15:37:11 -0700351 lastArg := ""
352 for _, arg := range inputCmd.Args {
353 if arg == "-" && lastArg != "-o" {
George Burgess IV26caa2f2020-02-28 14:36:01 -0800354 return true
Tobias Bosch6f59a662019-08-20 15:37:11 -0700355 }
356 lastArg = arg
357 }
George Burgess IV26caa2f2020-02-28 14:36:01 -0800358 return false
359}
360
361func prebufferStdinIfNeeded(env env, inputCmd *command) (getStdin func() io.Reader, err error) {
362 // We pre-buffer the entirety of stdin, since the compiler may exit mid-invocation with an
363 // error, which may leave stdin partially read.
364 if !needStdinTee(inputCmd) {
365 // This won't produce deterministic input to the compiler, but stdin shouldn't
366 // matter in this case, so...
367 return env.stdin, nil
368 }
369
370 stdinBuffer := &bytes.Buffer{}
371 if _, err := stdinBuffer.ReadFrom(env.stdin()); err != nil {
372 return nil, wrapErrorwithSourceLocf(err, "prebuffering stdin")
373 }
374
375 return func() io.Reader { return bytes.NewReader(stdinBuffer.Bytes()) }, nil
Tobias Bosch6f59a662019-08-20 15:37:11 -0700376}