• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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
5package main
6
7import (
8	"bufio"
9	"bytes"
10	"fmt"
11	"io"
12	"os"
13	"path/filepath"
14	"strings"
15	"syscall"
16	"time"
17)
18
19const prebuiltCompilerPathKey = "ANDROID_LLVM_PREBUILT_COMPILER_PATH"
20
21func shouldCompileWithFallback(env env) bool {
22	value, _ := env.getenv(prebuiltCompilerPathKey)
23	return value != ""
24}
25
26// FIXME: Deduplicate this logic with the logic for FORCE_DISABLE_WERROR
27// (the logic here is from Android, the logic for FORCE_DISABLE_WERROR is from ChromeOS)
28func compileWithFallback(env env, cfg *config, originalCmd *command, absWrapperPath string) (exitCode int, err error) {
29	firstCmd := &command{
30		Path:       originalCmd.Path,
31		Args:       originalCmd.Args,
32		EnvUpdates: originalCmd.EnvUpdates,
33	}
34	// We only want to pass extra flags to clang and clang++.
35	if base := filepath.Base(originalCmd.Path); base == "clang.real" || base == "clang++.real" {
36		// We may introduce some new warnings after rebasing and we need to
37		// disable them before we fix those warnings.
38		extraArgs, _ := env.getenv("ANDROID_LLVM_FALLBACK_DISABLED_WARNINGS")
39		firstCmd.Args = append(
40			append(firstCmd.Args, "-fno-color-diagnostics"),
41			strings.Split(extraArgs, " ")...,
42		)
43	}
44
45	getStdin, err := prebufferStdinIfNeeded(env, firstCmd)
46	if err != nil {
47		return 0, wrapErrorwithSourceLocf(err, "prebuffering stdin: %v", err)
48	}
49
50	firstCmdStderrBuffer := &bytes.Buffer{}
51	firstCmdExitCode, err := wrapSubprocessErrorWithSourceLoc(firstCmd,
52		env.run(firstCmd, getStdin(), env.stdout(), io.MultiWriter(env.stderr(), firstCmdStderrBuffer)))
53	if err != nil {
54		return 0, err
55	}
56
57	if firstCmdExitCode == 0 {
58		return 0, nil
59	}
60	stderrRedirectPath, _ := env.getenv("ANDROID_LLVM_STDERR_REDIRECT")
61	f, err := os.OpenFile(stderrRedirectPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
62	if err != nil {
63		return 0, wrapErrorwithSourceLocf(err, "error opening stderr file %s", stderrRedirectPath)
64	}
65	lockSuccess := false
66	for i := 0; i < 30; i++ {
67		err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
68		if err == nil {
69			lockSuccess = true
70			break
71		}
72		if errno, ok := err.(syscall.Errno); ok {
73			if errno == syscall.EAGAIN || errno == syscall.EACCES {
74				time.Sleep(500 * time.Millisecond)
75				err = nil
76			}
77		}
78		if err != nil {
79			return 0, wrapErrorwithSourceLocf(err, "error waiting to lock file %s", stderrRedirectPath)
80		}
81	}
82	if !lockSuccess {
83		return 0, wrapErrorwithSourceLocf(err, "timeout waiting to lock file %s", stderrRedirectPath)
84	}
85	w := bufio.NewWriter(f)
86	w.WriteString("==================COMMAND:====================\n")
87	fmt.Fprintf(w, "%s %s\n\n", firstCmd.Path, strings.Join(firstCmd.Args, " "))
88	firstCmdStderrBuffer.WriteTo(w)
89	w.WriteString("==============================================\n\n")
90	if err := w.Flush(); err != nil {
91		return 0, wrapErrorwithSourceLocf(err, "unable to write to file %s", stderrRedirectPath)
92	}
93	if err := f.Close(); err != nil {
94		return 0, wrapErrorwithSourceLocf(err, "error closing file %s", stderrRedirectPath)
95	}
96
97	prebuiltCompilerPath, _ := env.getenv(prebuiltCompilerPathKey)
98	fallbackCmd := &command{
99		Path: filepath.Join(prebuiltCompilerPath, filepath.Base(absWrapperPath)),
100		// Don't use extra args added (from ANDROID_LLVM_FALLBACK_DISABLED_WARNINGS) for clang and
101		// clang++ above.  They may not be recognized by the fallback clang.
102		Args: originalCmd.Args,
103		// Delete prebuiltCompilerPathKey so the fallback doesn't keep
104		// calling itself in case of an error.
105		EnvUpdates: append(originalCmd.EnvUpdates, prebuiltCompilerPathKey+"="),
106	}
107	return wrapSubprocessErrorWithSourceLoc(fallbackCmd,
108		env.run(fallbackCmd, getStdin(), env.stdout(), env.stderr()))
109}
110