blob: ad66f990273691cbff2daf172f979146d2953800 [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 Boscha50a9c12019-08-16 11:47:00 -07008 "bytes"
Tobias Bosch900dbc92019-06-24 09:31:39 -07009 "fmt"
10 "io"
Tobias Boschef8f9692019-06-10 15:50:33 -070011 "path/filepath"
Tobias Bosch5f98f2d2019-08-15 17:17:57 -070012 "strings"
Tobias Boschef8f9692019-06-10 15:50:33 -070013)
14
Tobias Bosch900dbc92019-06-24 09:31:39 -070015func callCompiler(env env, cfg *config, inputCmd *command) int {
Tobias Bosch900dbc92019-06-24 09:31:39 -070016 var compilerErr error
Tobias Bosch5f98f2d2019-08-15 17:17:57 -070017 if !filepath.IsAbs(inputCmd.Path) && !strings.HasPrefix(inputCmd.Path, ".") {
18 if resolvedPath, err := resolveAgainstPathEnv(env, inputCmd.Path); err == nil {
19 inputCmd = &command{
20 Path: resolvedPath,
21 Args: inputCmd.Args,
22 EnvUpdates: inputCmd.EnvUpdates,
23 }
24 } else {
25 compilerErr = err
26 }
27 }
28 exitCode := 0
29 if compilerErr == nil {
30 if cfg.oldWrapperPath != "" {
31 exitCode, compilerErr = callCompilerWithRunAndCompareToOldWrapper(env, cfg, inputCmd)
32 } else {
33 exitCode, compilerErr = callCompilerInternal(env, cfg, inputCmd)
34 }
Tobias Bosch900dbc92019-06-24 09:31:39 -070035 }
36 if compilerErr != nil {
37 printCompilerError(env.stderr(), compilerErr)
38 exitCode = 1
39 }
40 return exitCode
41}
42
43func callCompilerWithRunAndCompareToOldWrapper(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
Tobias Boscha50a9c12019-08-16 11:47:00 -070044 stdinBuffer := &bytes.Buffer{}
Tobias Bosch900dbc92019-06-24 09:31:39 -070045 recordingEnv := &commandRecordingEnv{
Tobias Boscha50a9c12019-08-16 11:47:00 -070046 env: env,
47 stdinReader: io.TeeReader(env.stdin(), stdinBuffer),
Tobias Bosch900dbc92019-06-24 09:31:39 -070048 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070049 // Note: this won't do a real exec as recordingEnv redirects exec to run.
50 if exitCode, err = callCompilerInternal(recordingEnv, cfg, inputCmd); err != nil {
51 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070052 }
Tobias Boscha50a9c12019-08-16 11:47:00 -070053 if err = compareToOldWrapper(env, cfg, inputCmd, stdinBuffer.Bytes(), recordingEnv.cmdResults, exitCode); err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -070054 return exitCode, err
55 }
56 return exitCode, nil
57}
58
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070059func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int, err error) {
Tobias Bosch900dbc92019-06-24 09:31:39 -070060 if err := checkUnsupportedFlags(inputCmd); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070061 return 0, err
Tobias Bosch900dbc92019-06-24 09:31:39 -070062 }
Tobias Boschd8684172019-07-08 10:59:14 -070063 mainBuilder, err := newCommandBuilder(env, cfg, inputCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -070064 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070065 return 0, err
Tobias Boschef8f9692019-06-10 15:50:33 -070066 }
Tobias Bosch58472812019-07-11 04:24:52 -070067 processPrintConfigFlag(mainBuilder)
68 processPrintCmdlineFlag(mainBuilder)
69 env = mainBuilder.env
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070070 var compilerCmd *command
Tobias Boschd8684172019-07-08 10:59:14 -070071 clangSyntax := processClangSyntaxFlag(mainBuilder)
72 if mainBuilder.target.compilerType == clangType {
Tobias Bosch38f3c422019-07-08 11:03:26 -070073 cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder)
Tobias Bosch198a3c92019-07-17 04:22:34 -070074 sysroot, err := prepareClangCommand(mainBuilder)
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 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070078 allowCCache := true
Tobias Bosch38f3c422019-07-08 11:03:26 -070079 if useClangTidy {
Tobias Bosch198a3c92019-07-17 04:22:34 -070080 allowCCache = false
81 clangCmdWithoutGomaAndCCache := mainBuilder.build()
82 if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070083 return 0, err
Tobias Bosch38f3c422019-07-08 11:03:26 -070084 }
85 }
Tobias Bosch198a3c92019-07-17 04:22:34 -070086 processGomaCCacheFlags(sysroot, allowCCache, mainBuilder)
87 compilerCmd = mainBuilder.build()
Tobias Boschef8f9692019-06-10 15:50:33 -070088 } else {
Tobias Boschd8684172019-07-08 10:59:14 -070089 if clangSyntax {
Tobias Bosch198a3c92019-07-17 04:22:34 -070090 allowCCache := false
91 clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone())
Tobias Boschd8684172019-07-08 10:59:14 -070092 if err != nil {
Tobias Boschf6d9f4f2019-07-09 08:09:01 -070093 return 0, err
Tobias Boschd8684172019-07-08 10:59:14 -070094 }
Tobias Boscha50a9c12019-08-16 11:47:00 -070095 gccCmd := calcGccCommand(mainBuilder)
96 return checkClangSyntax(env, clangCmd, gccCmd)
Tobias Boschd8684172019-07-08 10:59:14 -070097 }
98 compilerCmd = calcGccCommand(mainBuilder)
Tobias Boschef8f9692019-06-10 15:50:33 -070099 }
Tobias Bosch9d609302019-07-10 06:16:04 -0700100 rusageLogfileName := getRusageLogFilename(env)
Tobias Bosch9780ea92019-07-11 01:19:42 -0700101 bisectStage := getBisectStage(env)
Tobias Boschf6d9f4f2019-07-09 08:09:01 -0700102 if shouldForceDisableWError(env) {
Tobias Bosch9d609302019-07-10 06:16:04 -0700103 if rusageLogfileName != "" {
104 return 0, newUserErrorf("GETRUSAGE is meaningless with FORCE_DISABLE_WERROR")
105 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700106 if bisectStage != "" {
107 return 0, newUserErrorf("BISECT_STAGE is meaningless with FORCE_DISABLE_WERROR")
108 }
Tobias Boschf6d9f4f2019-07-09 08:09:01 -0700109 return doubleBuildWithWNoError(env, cfg, compilerCmd)
110 }
Tobias Bosch9d609302019-07-10 06:16:04 -0700111 if rusageLogfileName != "" {
Tobias Bosch9780ea92019-07-11 01:19:42 -0700112 if bisectStage != "" {
113 return 0, newUserErrorf("BISECT_STAGE is meaningless with GETRUSAGE")
114 }
Tobias Bosch9d609302019-07-10 06:16:04 -0700115 return logRusage(env, rusageLogfileName, compilerCmd)
116 }
Tobias Bosch9780ea92019-07-11 01:19:42 -0700117 if bisectStage != "" {
118 compilerCmd = calcBisectCommand(env, bisectStage, compilerCmd)
119 }
Tobias Bosch9332d212019-07-10 06:23:57 -0700120 // Note: We return an exit code only if the underlying env is not
121 // really doing an exec, e.g. commandRecordingEnv.
122 return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
Tobias Boschd8684172019-07-08 10:59:14 -0700123}
124
Tobias Bosch198a3c92019-07-17 04:22:34 -0700125func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700126 sysroot = ""
127 if !builder.cfg.isHostWrapper {
128 sysroot = processSysrootFlag(builder)
129 }
Tobias Boschd8684172019-07-08 10:59:14 -0700130 builder.addPreUserArgs(builder.cfg.clangFlags...)
131 calcCommonPreUserArgs(builder)
132 if err := processClangFlags(builder); err != nil {
Tobias Bosch198a3c92019-07-17 04:22:34 -0700133 return "", err
134 }
135 return sysroot, nil
136}
137
138func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) {
139 sysroot, err := prepareClangCommand(builder)
140 if err != nil {
Tobias Boschd8684172019-07-08 10:59:14 -0700141 return nil, err
142 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700143 processGomaCCacheFlags(sysroot, allowCCache, builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700144 return builder.build(), nil
145}
146
147func calcGccCommand(builder *commandBuilder) *command {
Tobias Boschb27c8f22019-07-19 06:53:07 -0700148 sysroot := ""
149 if !builder.cfg.isHostWrapper {
150 sysroot = processSysrootFlag(builder)
151 }
Tobias Boschd8684172019-07-08 10:59:14 -0700152 builder.addPreUserArgs(builder.cfg.gccFlags...)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700153 if !builder.cfg.isHostWrapper {
154 calcCommonPreUserArgs(builder)
155 }
Tobias Boschd8684172019-07-08 10:59:14 -0700156 processGccFlags(builder)
Tobias Boschb27c8f22019-07-19 06:53:07 -0700157 if !builder.cfg.isHostWrapper {
158 allowCCache := true
159 processGomaCCacheFlags(sysroot, allowCCache, builder)
160 }
Tobias Boschd8684172019-07-08 10:59:14 -0700161 return builder.build()
162}
163
164func calcCommonPreUserArgs(builder *commandBuilder) {
165 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700166 if !builder.cfg.isHostWrapper {
167 processPieFlags(builder)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700168 processThumbCodeFlags(builder)
Tobias Bosch1cd5f842019-08-20 10:05:33 -0700169 processStackProtectorFlags(builder)
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700170 processX86Flags(builder)
171 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700172 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700173}
174
Tobias Bosch198a3c92019-07-17 04:22:34 -0700175func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) {
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700176 gomaccUsed := false
177 if !builder.cfg.isHostWrapper {
178 gomaccUsed = processGomaCccFlags(builder)
179 }
Tobias Bosch198a3c92019-07-17 04:22:34 -0700180 if !gomaccUsed && allowCCache {
Tobias Boschef8f9692019-06-10 15:50:33 -0700181 processCCacheFlag(sysroot, builder)
182 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700183}
184
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700185func getAbsWrapperPath(env env, wrapperCmd *command) (string, error) {
Tobias Bosch58472812019-07-11 04:24:52 -0700186 wrapperPath := getAbsCmdPath(env, wrapperCmd)
Tobias Boschef8f9692019-06-10 15:50:33 -0700187 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
188 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700189 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700190 }
Tobias Bosch31dec2c2019-07-18 07:34:03 -0700191 return evaledCmdPath, nil
Tobias Boschef8f9692019-06-10 15:50:33 -0700192}
193
Tobias Bosch900dbc92019-06-24 09:31:39 -0700194func printCompilerError(writer io.Writer, compilerErr error) {
195 if _, ok := compilerErr.(userError); ok {
196 fmt.Fprintf(writer, "%s\n", compilerErr)
197 } else {
198 fmt.Fprintf(writer,
199 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
200 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700201 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700202}