blob: 8c5825e8a5a0faa8f9d30f95e3e88ab5a88276a6 [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"
Tobias Boschef8f9692019-06-10 15:50:33 -07007)
8
Tobias Bosch900dbc92019-06-24 09:31:39 -07009func callCompiler(env env, cfg *config, inputCmd *command) int {
10 exitCode := 0
11 var compilerErr error
12 if shouldForwardToOldWrapper(env, inputCmd) {
13 // TODO: Once this is only checking for bisect, create a command
14 // that directly calls the bisect driver in calcCompilerCommand.
15 exitCode, compilerErr = forwardToOldWrapper(env, cfg, inputCmd)
16 } else if cfg.oldWrapperPath != "" {
17 exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd)
18 } else {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070019 exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd)
Tobias Bosch900dbc92019-06-24 09:31:39 -070020 }
21 if compilerErr != nil {
22 printCompilerError(env.stderr(), compilerErr)
23 exitCode = 1
24 }
25 return exitCode
26}
27
28func callCompilerWithRunAndCompareToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
29 recordingEnv := &commandRecordingEnv{
30 env: env,
31 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070032 // Note: this won't do a real exec as recordingEnv redirects exec to run.
33 if exitCode, err = callCompilerInternal(recordingEnv, cfg, inputCmd); err != nil {
34 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070035 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070036 if err = compareToOldWrapper(env, cfg, inputCmd, recordingEnv.cmdResults, exitCode); err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -070037 return exitCode, err
38 }
39 return exitCode, nil
40}
41
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070042func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
Tobias Bosch900dbc92019-06-24 09:31:39 -070043 if err := checkUnsupportedFlags(inputCmd); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070044 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070045 }
Tobias Boschd8684172019-07-08 10:59:14 -070046 mainBuilder, err := newCommandBuilder(env, cfg, inputCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -070047 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070048 return 0, err
Tobias Boschef8f9692019-06-10 15:50:33 -070049 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070050 var compilerCmd *command
Tobias Boschd8684172019-07-08 10:59:14 -070051 clangSyntax := processClangSyntaxFlag(mainBuilder)
52 if mainBuilder.target.compilerType == clangType {
Tobias Bosch38f3c422019-07-08 11:03:26 -070053 cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
54 compilerCmd, err = calcClangCommand(useClangTidy, mainBuilder)
Tobias Boschd8684172019-07-08 10:59:14 -070055 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070056 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070057 }
Tobias Bosch38f3c422019-07-08 11:03:26 -070058 if useClangTidy {
59 if err := runClangTidy(env, compilerCmd, cSrcFile); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070060 return 0, err
Tobias Bosch38f3c422019-07-08 11:03:26 -070061 }
62 }
Tobias Boschef8f9692019-06-10 15:50:33 -070063 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070064 if clangSyntax {
Tobias Bosch38f3c422019-07-08 11:03:26 -070065 forceLocal := false
66 clangCmd, err := calcClangCommand(forceLocal, mainBuilder.clone())
Tobias Boschd8684172019-07-08 10:59:14 -070067 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070068 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070069 }
70 exitCode, err = checkClangSyntax(env, clangCmd)
71 if err != nil || exitCode != 0 {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070072 return exitCode, err
Tobias Boschd8684172019-07-08 10:59:14 -070073 }
74 }
75 compilerCmd = calcGccCommand(mainBuilder)
Tobias Boschef8f9692019-06-10 15:50:33 -070076 }
Tobias Bosch9d609302019-07-10 06:16:04 -070077 rusageLogfileName := getRusageLogFilename(env)
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070078 if shouldForceDisableWError(env) {
Tobias Bosch9d609302019-07-10 06:16:04 -070079 if rusageLogfileName != "" {
80 return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR")
81 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070082 return doubleBuildWithWNoError(env, cfg, compilerCmd)
83 }
Tobias Bosch9d609302019-07-10 06:16:04 -070084 if rusageLogfileName != "" {
85 return logRusage(env, rusageLogfileName, compilerCmd)
86 }
Tobias Bosch9332d212019-07-10 06:23:57 -070087 // Note: We return an exit code only if the underlying env is not
88 // really doing an exec, e.g. commandRecordingEnv.
89 return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
Tobias Boschd8684172019-07-08 10:59:14 -070090}
91
Tobias Bosch38f3c422019-07-08 11:03:26 -070092func calcClangCommand(forceLocal bool, builder *commandBuilder) (*command, error) {
Tobias Boschd8684172019-07-08 10:59:14 -070093 sysroot := processSysrootFlag(builder)
94 builder.addPreUserArgs(builder.cfg.clangFlags...)
95 calcCommonPreUserArgs(builder)
96 if err := processClangFlags(builder); err != nil {
97 return nil, err
98 }
Tobias Bosch38f3c422019-07-08 11:03:26 -070099 if !forceLocal {
100 processGomaCCacheFlags(sysroot, builder)
101 }
Tobias Boschd8684172019-07-08 10:59:14 -0700102 return builder.build(), nil
103}
104
105func calcGccCommand(builder *commandBuilder) *command {
106 sysroot := processSysrootFlag(builder)
107 builder.addPreUserArgs(builder.cfg.gccFlags...)
108 calcCommonPreUserArgs(builder)
109 processGccFlags(builder)
110 processGomaCCacheFlags(sysroot, builder)
111 return builder.build()
112}
113
114func calcCommonPreUserArgs(builder *commandBuilder) {
115 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Boschef8f9692019-06-10 15:50:33 -0700116 processPieFlags(builder)
117 processStackProtectorFlags(builder)
118 processThumbCodeFlags(builder)
119 processX86Flags(builder)
120 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700121}
122
123func processGomaCCacheFlags(sysroot string, builder *commandBuilder) {
Tobias Boschef8f9692019-06-10 15:50:33 -0700124 gomaccUsed := processGomaCccFlags(builder)
125 if !gomaccUsed {
126 processCCacheFlag(sysroot, builder)
127 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700128}
129
Tobias Boschef8f9692019-06-10 15:50:33 -0700130func getAbsWrapperDir(env env, wrapperPath string) (string, error) {
131 if !filepath.IsAbs(wrapperPath) {
132 wrapperPath = filepath.Join(env.getwd(), wrapperPath)
133 }
134 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
135 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700136 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700137 }
138 return filepath.Dir(evaledCmdPath), nil
139}
140
Tobias Bosch900dbc92019-06-24 09:31:39 -0700141func printCompilerError(writer io.Writer, compilerErr error) {
142 if _, ok := compilerErr.(userError); ok {
143 fmt.Fprintf(writer, "%s\n", compilerErr)
144 } else {
145 fmt.Fprintf(writer,
146 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
147 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700148 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700149}