blob: 1eacb578b868c94018a2c6b1b9edd0cd27a8e384 [file] [log] [blame]
Tobias Boschef8f9692019-06-10 15:50:33 -07001package main
2
3import (
Tobias Bosch900dbc92019-06-24 09:31:39 -07004 "fmt"
5 "io"
Tobias Boschef8f9692019-06-10 15:50:33 -07006 "path/filepath"
7 "strings"
Tobias Bosch900dbc92019-06-24 09:31:39 -07008 "syscall"
Tobias Boschef8f9692019-06-10 15:50:33 -07009)
10
Tobias Bosch900dbc92019-06-24 09:31:39 -070011func callCompiler(env env, cfg *config, inputCmd *command) int {
12 exitCode := 0
13 var compilerErr error
14 if shouldForwardToOldWrapper(env, inputCmd) {
15 // TODO: Once this is only checking for bisect, create a command
16 // that directly calls the bisect driver in calcCompilerCommand.
17 exitCode, compilerErr = forwardToOldWrapper(env, cfg, inputCmd)
18 } else if cfg.oldWrapperPath != "" {
19 exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd)
20 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070021 exitCode, compilerErr = callCompilerWithExec(env, cfg, inputCmd)
Tobias Bosch900dbc92019-06-24 09:31:39 -070022 }
23 if compilerErr != nil {
24 printCompilerError(env.stderr(), compilerErr)
25 exitCode = 1
26 }
27 return exitCode
28}
29
30func callCompilerWithRunAndCompareToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
31 recordingEnv := &commandRecordingEnv{
32 env: env,
33 }
Tobias Boschd8684172019-07-08 10:59:14 -070034 compilerCmd, exitCode, err := calcCompilerCommand(recordingEnv, cfg, inputCmd)
35 if err != nil || exitCode != 0 {
Tobias Bosch900dbc92019-06-24 09:31:39 -070036 return exitCode, err
37 }
38 exitCode = 0
39 // Note: we are not using env.exec here so that we can compare the exit code
40 // against the old wrapper too.
41 if err := recordingEnv.run(compilerCmd, env.stdout(), env.stderr()); err != nil {
42 if userErr, ok := getCCacheError(compilerCmd, err); ok {
43 return exitCode, userErr
44 }
45 var ok bool
46 if exitCode, ok = getExitCode(err); !ok {
Tobias Boschd8684172019-07-08 10:59:14 -070047 return exitCode, wrapErrorwithSourceLocf(err, "failed to execute %#v", compilerCmd)
Tobias Bosch900dbc92019-06-24 09:31:39 -070048 }
49 }
50 if err := compareToOldWrapper(env, cfg, inputCmd, recordingEnv.cmdResults); err != nil {
51 return exitCode, err
52 }
53 return exitCode, nil
54}
55
Tobias Boschd8684172019-07-08 10:59:14 -070056func callCompilerWithExec(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
57 compilerCmd, exitCode, err := calcCompilerCommand(env, cfg, inputCmd)
58 if err != nil || exitCode != 0 {
59 return exitCode, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070060 }
61 if err := env.exec(compilerCmd); err != nil {
62 // Note: No need to check for exit code error as exec will
63 // stop this control flow once the command started executing.
64 if userErr, ok := getCCacheError(compilerCmd, err); ok {
Tobias Boschd8684172019-07-08 10:59:14 -070065 return exitCode, userErr
Tobias Bosch900dbc92019-06-24 09:31:39 -070066 }
Tobias Boschd8684172019-07-08 10:59:14 -070067 return exitCode, wrapErrorwithSourceLocf(err, "failed to execute %#v", compilerCmd)
Tobias Bosch900dbc92019-06-24 09:31:39 -070068 }
Tobias Boschd8684172019-07-08 10:59:14 -070069 return exitCode, nil
Tobias Bosch900dbc92019-06-24 09:31:39 -070070}
71
Tobias Boschd8684172019-07-08 10:59:14 -070072func calcCompilerCommand(env env, cfg *config, inputCmd *command) (compilerCmd *command, exitCode int, err error) {
Tobias Bosch900dbc92019-06-24 09:31:39 -070073 if err := checkUnsupportedFlags(inputCmd); err != nil {
Tobias Boschd8684172019-07-08 10:59:14 -070074 return nil, exitCode, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070075 }
Tobias Boschd8684172019-07-08 10:59:14 -070076 mainBuilder, err := newCommandBuilder(env, cfg, inputCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -070077 if err != nil {
Tobias Boschd8684172019-07-08 10:59:14 -070078 return nil, exitCode, err
Tobias Boschef8f9692019-06-10 15:50:33 -070079 }
Tobias Boschd8684172019-07-08 10:59:14 -070080 clangSyntax := processClangSyntaxFlag(mainBuilder)
81 if mainBuilder.target.compilerType == clangType {
Tobias Bosch38f3c422019-07-08 11:03:26 -070082 cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
83 compilerCmd, err = calcClangCommand(useClangTidy, mainBuilder)
Tobias Boschd8684172019-07-08 10:59:14 -070084 if err != nil {
85 return nil, exitCode, err
86 }
Tobias Bosch38f3c422019-07-08 11:03:26 -070087 if useClangTidy {
88 if err := runClangTidy(env, compilerCmd, cSrcFile); err != nil {
89 return nil, exitCode, err
90 }
91 }
Tobias Boschef8f9692019-06-10 15:50:33 -070092 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070093 if clangSyntax {
Tobias Bosch38f3c422019-07-08 11:03:26 -070094 forceLocal := false
95 clangCmd, err := calcClangCommand(forceLocal, mainBuilder.clone())
Tobias Boschd8684172019-07-08 10:59:14 -070096 if err != nil {
97 return nil, 0, err
98 }
99 exitCode, err = checkClangSyntax(env, clangCmd)
100 if err != nil || exitCode != 0 {
101 return nil, exitCode, err
102 }
103 }
104 compilerCmd = calcGccCommand(mainBuilder)
Tobias Boschef8f9692019-06-10 15:50:33 -0700105 }
Tobias Boschd8684172019-07-08 10:59:14 -0700106
107 return compilerCmd, exitCode, nil
108}
109
Tobias Bosch38f3c422019-07-08 11:03:26 -0700110func calcClangCommand(forceLocal bool, builder *commandBuilder) (*command, error) {
Tobias Boschd8684172019-07-08 10:59:14 -0700111 sysroot := processSysrootFlag(builder)
112 builder.addPreUserArgs(builder.cfg.clangFlags...)
113 calcCommonPreUserArgs(builder)
114 if err := processClangFlags(builder); err != nil {
115 return nil, err
116 }
Tobias Bosch38f3c422019-07-08 11:03:26 -0700117 if !forceLocal {
118 processGomaCCacheFlags(sysroot, builder)
119 }
Tobias Boschd8684172019-07-08 10:59:14 -0700120 return builder.build(), nil
121}
122
123func calcGccCommand(builder *commandBuilder) *command {
124 sysroot := processSysrootFlag(builder)
125 builder.addPreUserArgs(builder.cfg.gccFlags...)
126 calcCommonPreUserArgs(builder)
127 processGccFlags(builder)
128 processGomaCCacheFlags(sysroot, builder)
129 return builder.build()
130}
131
132func calcCommonPreUserArgs(builder *commandBuilder) {
133 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Boschef8f9692019-06-10 15:50:33 -0700134 processPieFlags(builder)
135 processStackProtectorFlags(builder)
136 processThumbCodeFlags(builder)
137 processX86Flags(builder)
138 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700139}
140
141func processGomaCCacheFlags(sysroot string, builder *commandBuilder) {
Tobias Boschef8f9692019-06-10 15:50:33 -0700142 gomaccUsed := processGomaCccFlags(builder)
143 if !gomaccUsed {
144 processCCacheFlag(sysroot, builder)
145 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700146}
147
Tobias Boschef8f9692019-06-10 15:50:33 -0700148func getAbsWrapperDir(env env, wrapperPath string) (string, error) {
149 if !filepath.IsAbs(wrapperPath) {
150 wrapperPath = filepath.Join(env.getwd(), wrapperPath)
151 }
152 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
153 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700154 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700155 }
156 return filepath.Dir(evaledCmdPath), nil
157}
158
Tobias Bosch900dbc92019-06-24 09:31:39 -0700159func getCCacheError(compilerCmd *command, compilerCmdErr error) (ccacheErr userError, ok bool) {
160 if en, ok := compilerCmdErr.(syscall.Errno); ok && en == syscall.ENOENT &&
161 strings.Contains(compilerCmd.path, "ccache") {
162 ccacheErr =
163 newUserErrorf("ccache not found under %s. Please install it",
164 compilerCmd.path)
165 return ccacheErr, ok
Tobias Boschef8f9692019-06-10 15:50:33 -0700166 }
Tobias Bosch900dbc92019-06-24 09:31:39 -0700167 return ccacheErr, false
168}
169
170func printCompilerError(writer io.Writer, compilerErr error) {
171 if _, ok := compilerErr.(userError); ok {
172 fmt.Fprintf(writer, "%s\n", compilerErr)
173 } else {
174 fmt.Fprintf(writer,
175 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
176 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700177 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700178}