blob: 4aa91c6c88e488298c485e1e2c2924968e33016f [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 Bosch5f98f2d2019-08-15 17:17:57 -070011 "strings"
Tobias Boschef8f9692019-06-10 15:50:33 -070012)
13
Tobias Bosch900dbc92019-06-24 09:31:39 -070014func callCompiler(env env, cfg *config, inputCmd *command) int {
Tobias Bosch900dbc92019-06-24 09:31:39 -070015 var compilerErr error
Tobias Bosch5f98f2d2019-08-15 17:17:57 -070016 if !filepath.IsAbs(inputCmd.Path) && !strings.HasPrefix(inputCmd.Path, ".") {
17 if resolvedPath, err := resolveAgainstPathEnv(env, inputCmd.Path); err == nil {
18 inputCmd = &command{
19 Path: resolvedPath,
20 Args: inputCmd.Args,
21 EnvUpdates: inputCmd.EnvUpdates,
22 }
23 } else {
24 compilerErr = err
25 }
26 }
27 exitCode := 0
28 if compilerErr == nil {
29 if cfg.oldWrapperPath != "" {
30 exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd)
31 } else {
32 exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd)
33 }
Tobias Bosch900dbc92019-06-24 09:31:39 -070034 }
35 if compilerErr != nil {
36 printCompilerError(env.stderr(), compilerErr)
37 exitCode = 1
38 }
39 return exitCode
40}
41
42func callCompilerWithRunAndCompareToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
43 recordingEnv := &commandRecordingEnv{
44 env: env,
45 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070046 // Note: this won't do a real exec as recordingEnv redirects exec to run.
47 if exitCode, err = callCompilerInternal(recordingEnv, cfg, inputCmd); err != nil {
48 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070049 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070050 if err = compareToOldWrapper(env, cfg, inputCmd, recordingEnv.cmdResults, exitCode); err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -070051 return exitCode, err
52 }
53 return exitCode, nil
54}
55
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070056func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
Tobias Bosch900dbc92019-06-24 09:31:39 -070057 if err := checkUnsupportedFlags(inputCmd); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070058 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070059 }
Tobias Boschd8684172019-07-08 10:59:14 -070060 mainBuilder, err := newCommandBuilder(env, cfg, inputCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -070061 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070062 return 0, err
Tobias Boschef8f9692019-06-10 15:50:33 -070063 }
Tobias Bosch58472812019-07-11 04:24:52 -070064 processPrintConfigFlag(mainBuilder)
65 processPrintCmdlineFlag(mainBuilder)
66 env = mainBuilder.env
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070067 var compilerCmd *command
Tobias Boschd8684172019-07-08 10:59:14 -070068 clangSyntax := processClangSyntaxFlag(mainBuilder)
69 if mainBuilder.target.compilerType == clangType {
Tobias Bosch38f3c422019-07-08 11:03:26 -070070 cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
Tobias Bosch198a3c92019-07-17 04:22:34 -070071 sysroot, err := prepareClangCommand(mainBuilder)
Tobias Boschd8684172019-07-08 10:59:14 -070072 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070073 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070074 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070075 allowCCache := true
Tobias Bosch38f3c422019-07-08 11:03:26 -070076 if useClangTidy {
Tobias Bosch198a3c92019-07-17 04:22:34 -070077 allowCCache = false
78 clangCmdWithoutGomaAndCCache := mainBuilder.build()
79 if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070080 return 0, err
Tobias Bosch38f3c422019-07-08 11:03:26 -070081 }
82 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070083 processGomaCCacheFlags(sysroot, allowCCache, mainBuilder)
84 compilerCmd = mainBuilder.build()
Tobias Boschef8f9692019-06-10 15:50:33 -070085 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070086 if clangSyntax {
Tobias Bosch198a3c92019-07-17 04:22:34 -070087 allowCCache := false
88 clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
Tobias Boschd8684172019-07-08 10:59:14 -070089 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070090 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070091 }
92 exitCode, err = checkClangSyntax(env, clangCmd)
93 if err != nil || exitCode != 0 {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070094 return exitCode, err
Tobias Boschd8684172019-07-08 10:59:14 -070095 }
96 }
97 compilerCmd = calcGccCommand(mainBuilder)
Tobias Boschef8f9692019-06-10 15:50:33 -070098 }
Tobias Bosch9d609302019-07-10 06:16:04 -070099 rusageLogfileName := getRusageLogFilename(env)
Tobias Bosch9780ea92019-07-11 01:19:42 -0700100 bisectStage := getBisectStage(env)
Tobias Boschf6d9f4f2019-07-09 08:09:01 -0700101 if shouldForceDisableWError(env) {
Tobias Bosch9d609302019-07-10 06:16:04 -0700102 if rusageLogfileName != "" {
103 return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR")
104 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700105 if bisectStage != "" {
106 return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR")
107 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -0700108 return doubleBuildWithWNoError(env, cfg, compilerCmd)
109 }
Tobias Bosch9d609302019-07-10 06:16:04 -0700110 if rusageLogfileName != "" {
Tobias Bosch9780ea92019-07-11 01:19:42 -0700111 if bisectStage != "" {
112 return 0, newUserErrorf("BISECT_STAGE is meaningless with GETRUSAGE")
113 }
Tobias Bosch9d609302019-07-10 06:16:04 -0700114 return logRusage(env, rusageLogfileName, compilerCmd)
115 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700116 if bisectStage != "" {
117 compilerCmd = calcBisectCommand(env, bisectStage, compilerCmd)
118 }
Tobias Bosch9332d212019-07-10 06:23:57 -0700119 // Note: We return an exit code only if the underlying env is not
120 // really doing an exec, e.g. commandRecordingEnv.
121 return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
Tobias Boschd8684172019-07-08 10:59:14 -0700122}
123
Tobias Bosch198a3c92019-07-17 04:22:34 -0700124func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700125 sysroot = ""
126 if !builder.cfg.isHostWrapper {
127 sysroot = processSysrootFlag(builder)
128 }
Tobias Boschd8684172019-07-08 10:59:14 -0700129 builder.addPreUserArgs(builder.cfg.clangFlags...)
130 calcCommonPreUserArgs(builder)
131 if err := processClangFlags(builder); err != nil {
Tobias Bosch198a3c92019-07-17 04:22:34 -0700132 return "", err
133 }
134 return sysroot, nil
135}
136
137func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) {
138 sysroot, err := prepareClangCommand(builder)
139 if err != nil {
Tobias Boschd8684172019-07-08 10:59:14 -0700140 return nil, err
141 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700142 processGomaCCacheFlags(sysroot, allowCCache, builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700143 return builder.build(), nil
144}
145
146func calcGccCommand(builder *commandBuilder) *command {
Tobias Boschb27c8f22019-07-19 06:53:07 -0700147 sysroot := ""
148 if !builder.cfg.isHostWrapper {
149 sysroot = processSysrootFlag(builder)
150 }
Tobias Boschd8684172019-07-08 10:59:14 -0700151 builder.addPreUserArgs(builder.cfg.gccFlags...)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700152 if !builder.cfg.isHostWrapper {
153 calcCommonPreUserArgs(builder)
154 }
Tobias Boschd8684172019-07-08 10:59:14 -0700155 processGccFlags(builder)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700156 if !builder.cfg.isHostWrapper {
157 allowCCache := true
158 processGomaCCacheFlags(sysroot, allowCCache, builder)
159 }
Tobias Boschd8684172019-07-08 10:59:14 -0700160 return builder.build()
161}
162
163func calcCommonPreUserArgs(builder *commandBuilder) {
164 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700165 if !builder.cfg.isHostWrapper {
166 processPieFlags(builder)
167 processStackProtectorFlags(builder)
168 processThumbCodeFlags(builder)
169 processX86Flags(builder)
170 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700171 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700172}
173
Tobias Bosch198a3c92019-07-17 04:22:34 -0700174func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700175 gomaccUsed := false
176 if !builder.cfg.isHostWrapper {
177 gomaccUsed = processGomaCccFlags(builder)
178 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700179 if !gomaccUsed && allowCCache {
Tobias Boschef8f9692019-06-10 15:50:33 -0700180 processCCacheFlag(sysroot, builder)
181 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700182}
183
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700184func getAbsWrapperPath(env env, wrapperCmd *command) (string, error) {
Tobias Bosch58472812019-07-11 04:24:52 -0700185 wrapperPath := getAbsCmdPath(env, wrapperCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -0700186 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
187 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700188 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700189 }
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700190 return evaledCmdPath, nil
Tobias Boschef8f9692019-06-10 15:50:33 -0700191}
192
Tobias Bosch900dbc92019-06-24 09:31:39 -0700193func printCompilerError(writer io.Writer, compilerErr error) {
194 if _, ok := compilerErr.(userError); ok {
195 fmt.Fprintf(writer, "%s\n", compilerErr)
196 } else {
197 fmt.Fprintf(writer,
198 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
199 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700200 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700201}