blob: 8bee238d70a6b8ba45c2e378b2aced8ee000b2d1 [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
Tobias Bosch9780ea92019-07-11 01:19:42 -070012 if cfg.oldWrapperPath != "" {
Tobias Bosch900dbc92019-06-24 09:31:39 -070013 exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd)
14 } else {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070015 exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd)
Tobias Bosch900dbc92019-06-24 09:31:39 -070016 }
17 if compilerErr != nil {
18 printCompilerError(env.stderr(), compilerErr)
19 exitCode = 1
20 }
21 return exitCode
22}
23
24func callCompilerWithRunAndCompareToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
25 recordingEnv := &commandRecordingEnv{
26 env: env,
27 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070028 // Note: this won't do a real exec as recordingEnv redirects exec to run.
29 if exitCode, err = callCompilerInternal(recordingEnv, cfg, inputCmd); err != nil {
30 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070031 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070032 if err = compareToOldWrapper(env, cfg, inputCmd, recordingEnv.cmdResults, exitCode); err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -070033 return exitCode, err
34 }
35 return exitCode, nil
36}
37
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070038func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
Tobias Bosch900dbc92019-06-24 09:31:39 -070039 if err := checkUnsupportedFlags(inputCmd); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070040 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070041 }
Tobias Boschd8684172019-07-08 10:59:14 -070042 mainBuilder, err := newCommandBuilder(env, cfg, inputCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -070043 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070044 return 0, err
Tobias Boschef8f9692019-06-10 15:50:33 -070045 }
Tobias Bosch58472812019-07-11 04:24:52 -070046 processPrintConfigFlag(mainBuilder)
47 processPrintCmdlineFlag(mainBuilder)
48 env = mainBuilder.env
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070049 var compilerCmd *command
Tobias Boschd8684172019-07-08 10:59:14 -070050 clangSyntax := processClangSyntaxFlag(mainBuilder)
51 if mainBuilder.target.compilerType == clangType {
Tobias Bosch38f3c422019-07-08 11:03:26 -070052 cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
Tobias Bosch198a3c92019-07-17 04:22:34 -070053 sysroot, err := prepareClangCommand(mainBuilder)
Tobias Boschd8684172019-07-08 10:59:14 -070054 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070055 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070056 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070057 allowCCache := true
Tobias Bosch38f3c422019-07-08 11:03:26 -070058 if useClangTidy {
Tobias Bosch198a3c92019-07-17 04:22:34 -070059 allowCCache = false
60 clangCmdWithoutGomaAndCCache := mainBuilder.build()
61 if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070062 return 0, err
Tobias Bosch38f3c422019-07-08 11:03:26 -070063 }
64 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070065 processGomaCCacheFlags(sysroot, allowCCache, mainBuilder)
66 compilerCmd = mainBuilder.build()
Tobias Boschef8f9692019-06-10 15:50:33 -070067 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070068 if clangSyntax {
Tobias Bosch198a3c92019-07-17 04:22:34 -070069 allowCCache := false
70 clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
Tobias Boschd8684172019-07-08 10:59:14 -070071 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070072 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070073 }
74 exitCode, err = checkClangSyntax(env, clangCmd)
75 if err != nil || exitCode != 0 {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070076 return exitCode, err
Tobias Boschd8684172019-07-08 10:59:14 -070077 }
78 }
79 compilerCmd = calcGccCommand(mainBuilder)
Tobias Boschef8f9692019-06-10 15:50:33 -070080 }
Tobias Bosch9d609302019-07-10 06:16:04 -070081 rusageLogfileName := getRusageLogFilename(env)
Tobias Bosch9780ea92019-07-11 01:19:42 -070082 bisectStage := getBisectStage(env)
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070083 if shouldForceDisableWError(env) {
Tobias Bosch9d609302019-07-10 06:16:04 -070084 if rusageLogfileName != "" {
85 return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR")
86 }
Tobias Bosch9780ea92019-07-11 01:19:42 -070087 if bisectStage != "" {
88 return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR")
89 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070090 return doubleBuildWithWNoError(env, cfg, compilerCmd)
91 }
Tobias Bosch9d609302019-07-10 06:16:04 -070092 if rusageLogfileName != "" {
Tobias Bosch9780ea92019-07-11 01:19:42 -070093 if bisectStage != "" {
94 return 0, newUserErrorf("BISECT_STAGE is meaningless with GETRUSAGE")
95 }
Tobias Bosch9d609302019-07-10 06:16:04 -070096 return logRusage(env, rusageLogfileName, compilerCmd)
97 }
Tobias Bosch9780ea92019-07-11 01:19:42 -070098 if bisectStage != "" {
99 compilerCmd = calcBisectCommand(env, bisectStage, compilerCmd)
100 }
Tobias Bosch9332d212019-07-10 06:23:57 -0700101 // Note: We return an exit code only if the underlying env is not
102 // really doing an exec, e.g. commandRecordingEnv.
103 return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
Tobias Boschd8684172019-07-08 10:59:14 -0700104}
105
Tobias Bosch198a3c92019-07-17 04:22:34 -0700106func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) {
107 sysroot = processSysrootFlag(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700108 builder.addPreUserArgs(builder.cfg.clangFlags...)
109 calcCommonPreUserArgs(builder)
110 if err := processClangFlags(builder); err != nil {
Tobias Bosch198a3c92019-07-17 04:22:34 -0700111 return "", err
112 }
113 return sysroot, nil
114}
115
116func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) {
117 sysroot, err := prepareClangCommand(builder)
118 if err != nil {
Tobias Boschd8684172019-07-08 10:59:14 -0700119 return nil, err
120 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700121 processGomaCCacheFlags(sysroot, allowCCache, builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700122 return builder.build(), nil
123}
124
125func calcGccCommand(builder *commandBuilder) *command {
126 sysroot := processSysrootFlag(builder)
127 builder.addPreUserArgs(builder.cfg.gccFlags...)
128 calcCommonPreUserArgs(builder)
129 processGccFlags(builder)
Tobias Bosch198a3c92019-07-17 04:22:34 -0700130 allowCCache := true
131 processGomaCCacheFlags(sysroot, allowCCache, builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700132 return builder.build()
133}
134
135func calcCommonPreUserArgs(builder *commandBuilder) {
136 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Boschef8f9692019-06-10 15:50:33 -0700137 processPieFlags(builder)
138 processStackProtectorFlags(builder)
139 processThumbCodeFlags(builder)
140 processX86Flags(builder)
141 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700142}
143
Tobias Bosch198a3c92019-07-17 04:22:34 -0700144func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) {
Tobias Boschef8f9692019-06-10 15:50:33 -0700145 gomaccUsed := processGomaCccFlags(builder)
Tobias Bosch198a3c92019-07-17 04:22:34 -0700146 if !gomaccUsed && allowCCache {
Tobias Boschef8f9692019-06-10 15:50:33 -0700147 processCCacheFlag(sysroot, builder)
148 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700149}
150
Tobias Bosch58472812019-07-11 04:24:52 -0700151func getAbsWrapperDir(env env, wrapperCmd *command) (string, error) {
152 wrapperPath := getAbsCmdPath(env, wrapperCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -0700153 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
154 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700155 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700156 }
157 return filepath.Dir(evaledCmdPath), nil
158}
159
Tobias Bosch900dbc92019-06-24 09:31:39 -0700160func printCompilerError(writer io.Writer, compilerErr error) {
161 if _, ok := compilerErr.(userError); ok {
162 fmt.Fprintf(writer, "%s\n", compilerErr)
163 } else {
164 fmt.Fprintf(writer,
165 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
166 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700167 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700168}