blob: 521846c976bef516f49ea26ffd580ee919e6eafd [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 (
Tobias Bosch900dbc92019-06-24 09:31:39 -07008 "fmt"
9 "io"
Tobias Boschef8f9692019-06-10 15:50:33 -070010 "path/filepath"
Tobias Boschef8f9692019-06-10 15:50:33 -070011)
12
Tobias Bosch900dbc92019-06-24 09:31:39 -070013func callCompiler(env env, cfg *config, inputCmd *command) int {
14 exitCode := 0
15 var compilerErr error
Tobias Bosch9780ea92019-07-11 01:19:42 -070016 if cfg.oldWrapperPath != "" {
Tobias Bosch900dbc92019-06-24 09:31:39 -070017 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 Bosch58472812019-07-11 04:24:52 -070050 processPrintConfigFlag(mainBuilder)
51 processPrintCmdlineFlag(mainBuilder)
52 env = mainBuilder.env
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070053 var compilerCmd *command
Tobias Boschd8684172019-07-08 10:59:14 -070054 clangSyntax := processClangSyntaxFlag(mainBuilder)
55 if mainBuilder.target.compilerType == clangType {
Tobias Bosch38f3c422019-07-08 11:03:26 -070056 cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
Tobias Bosch198a3c92019-07-17 04:22:34 -070057 sysroot, err := prepareClangCommand(mainBuilder)
Tobias Boschd8684172019-07-08 10:59:14 -070058 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070059 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070060 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070061 allowCCache := true
Tobias Bosch38f3c422019-07-08 11:03:26 -070062 if useClangTidy {
Tobias Bosch198a3c92019-07-17 04:22:34 -070063 allowCCache = false
64 clangCmdWithoutGomaAndCCache := mainBuilder.build()
65 if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070066 return 0, err
Tobias Bosch38f3c422019-07-08 11:03:26 -070067 }
68 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070069 processGomaCCacheFlags(sysroot, allowCCache, mainBuilder)
70 compilerCmd = mainBuilder.build()
Tobias Boschef8f9692019-06-10 15:50:33 -070071 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070072 if clangSyntax {
Tobias Bosch198a3c92019-07-17 04:22:34 -070073 allowCCache := false
74 clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
Tobias Boschd8684172019-07-08 10:59:14 -070075 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070076 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070077 }
78 exitCode, err = checkClangSyntax(env, clangCmd)
79 if err != nil || exitCode != 0 {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070080 return exitCode, err
Tobias Boschd8684172019-07-08 10:59:14 -070081 }
82 }
83 compilerCmd = calcGccCommand(mainBuilder)
Tobias Boschef8f9692019-06-10 15:50:33 -070084 }
Tobias Bosch9d609302019-07-10 06:16:04 -070085 rusageLogfileName := getRusageLogFilename(env)
Tobias Bosch9780ea92019-07-11 01:19:42 -070086 bisectStage := getBisectStage(env)
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070087 if shouldForceDisableWError(env) {
Tobias Bosch9d609302019-07-10 06:16:04 -070088 if rusageLogfileName != "" {
89 return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR")
90 }
Tobias Bosch9780ea92019-07-11 01:19:42 -070091 if bisectStage != "" {
92 return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR")
93 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070094 return doubleBuildWithWNoError(env, cfg, compilerCmd)
95 }
Tobias Bosch9d609302019-07-10 06:16:04 -070096 if rusageLogfileName != "" {
Tobias Bosch9780ea92019-07-11 01:19:42 -070097 if bisectStage != "" {
98 return 0, newUserErrorf("BISECT_STAGE is meaningless with GETRUSAGE")
99 }
Tobias Bosch9d609302019-07-10 06:16:04 -0700100 return logRusage(env, rusageLogfileName, compilerCmd)
101 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700102 if bisectStage != "" {
103 compilerCmd = calcBisectCommand(env, bisectStage, compilerCmd)
104 }
Tobias Bosch9332d212019-07-10 06:23:57 -0700105 // Note: We return an exit code only if the underlying env is not
106 // really doing an exec, e.g. commandRecordingEnv.
107 return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
Tobias Boschd8684172019-07-08 10:59:14 -0700108}
109
Tobias Bosch198a3c92019-07-17 04:22:34 -0700110func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700111 sysroot = ""
112 if !builder.cfg.isHostWrapper {
113 sysroot = processSysrootFlag(builder)
114 }
Tobias Boschd8684172019-07-08 10:59:14 -0700115 builder.addPreUserArgs(builder.cfg.clangFlags...)
116 calcCommonPreUserArgs(builder)
117 if err := processClangFlags(builder); err != nil {
Tobias Bosch198a3c92019-07-17 04:22:34 -0700118 return "", err
119 }
120 return sysroot, nil
121}
122
123func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) {
124 sysroot, err := prepareClangCommand(builder)
125 if err != nil {
Tobias Boschd8684172019-07-08 10:59:14 -0700126 return nil, err
127 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700128 processGomaCCacheFlags(sysroot, allowCCache, builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700129 return builder.build(), nil
130}
131
132func calcGccCommand(builder *commandBuilder) *command {
Tobias Boschb27c8f22019-07-19 06:53:07 -0700133 sysroot := ""
134 if !builder.cfg.isHostWrapper {
135 sysroot = processSysrootFlag(builder)
136 }
Tobias Boschd8684172019-07-08 10:59:14 -0700137 builder.addPreUserArgs(builder.cfg.gccFlags...)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700138 if !builder.cfg.isHostWrapper {
139 calcCommonPreUserArgs(builder)
140 }
Tobias Boschd8684172019-07-08 10:59:14 -0700141 processGccFlags(builder)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700142 if !builder.cfg.isHostWrapper {
143 allowCCache := true
144 processGomaCCacheFlags(sysroot, allowCCache, builder)
145 }
Tobias Boschd8684172019-07-08 10:59:14 -0700146 return builder.build()
147}
148
149func calcCommonPreUserArgs(builder *commandBuilder) {
150 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700151 if !builder.cfg.isHostWrapper {
152 processPieFlags(builder)
153 processStackProtectorFlags(builder)
154 processThumbCodeFlags(builder)
155 processX86Flags(builder)
156 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700157 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700158}
159
Tobias Bosch198a3c92019-07-17 04:22:34 -0700160func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700161 gomaccUsed := false
162 if !builder.cfg.isHostWrapper {
163 gomaccUsed = processGomaCccFlags(builder)
164 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700165 if !gomaccUsed && allowCCache {
Tobias Boschef8f9692019-06-10 15:50:33 -0700166 processCCacheFlag(sysroot, builder)
167 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700168}
169
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700170func getAbsWrapperPath(env env, wrapperCmd *command) (string, error) {
Tobias Bosch58472812019-07-11 04:24:52 -0700171 wrapperPath := getAbsCmdPath(env, wrapperCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -0700172 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
173 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700174 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700175 }
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700176 return evaledCmdPath, nil
Tobias Boschef8f9692019-06-10 15:50:33 -0700177}
178
Tobias Bosch900dbc92019-06-24 09:31:39 -0700179func printCompilerError(writer io.Writer, compilerErr error) {
180 if _, ok := compilerErr.(userError); ok {
181 fmt.Fprintf(writer, "%s\n", compilerErr)
182 } else {
183 fmt.Fprintf(writer,
184 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
185 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700186 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700187}