blob: e24faef3f47eb923770825d3bc26cf3645c068c5 [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 Boschf6d9f4f2019-07-09 08:09:01 -070077 if shouldForceDisableWError(env) {
78 return doubleBuildWithWNoError(env, cfg, compilerCmd)
79 }
Tobias Bosch9332d212019-07-10 06:23:57 -070080 // Note: We return an exit code only if the underlying env is not
81 // really doing an exec, e.g. commandRecordingEnv.
82 return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd))
Tobias Boschd8684172019-07-08 10:59:14 -070083}
84
Tobias Bosch38f3c422019-07-08 11:03:26 -070085func calcClangCommand(forceLocal bool, builder *commandBuilder) (*command, error) {
Tobias Boschd8684172019-07-08 10:59:14 -070086 sysroot := processSysrootFlag(builder)
87 builder.addPreUserArgs(builder.cfg.clangFlags...)
88 calcCommonPreUserArgs(builder)
89 if err := processClangFlags(builder); err != nil {
90 return nil, err
91 }
Tobias Bosch38f3c422019-07-08 11:03:26 -070092 if !forceLocal {
93 processGomaCCacheFlags(sysroot, builder)
94 }
Tobias Boschd8684172019-07-08 10:59:14 -070095 return builder.build(), nil
96}
97
98func calcGccCommand(builder *commandBuilder) *command {
99 sysroot := processSysrootFlag(builder)
100 builder.addPreUserArgs(builder.cfg.gccFlags...)
101 calcCommonPreUserArgs(builder)
102 processGccFlags(builder)
103 processGomaCCacheFlags(sysroot, builder)
104 return builder.build()
105}
106
107func calcCommonPreUserArgs(builder *commandBuilder) {
108 builder.addPreUserArgs(builder.cfg.commonFlags...)
Tobias Boschef8f9692019-06-10 15:50:33 -0700109 processPieFlags(builder)
110 processStackProtectorFlags(builder)
111 processThumbCodeFlags(builder)
112 processX86Flags(builder)
113 processSanitizerFlags(builder)
Tobias Boschd8684172019-07-08 10:59:14 -0700114}
115
116func processGomaCCacheFlags(sysroot string, builder *commandBuilder) {
Tobias Boschef8f9692019-06-10 15:50:33 -0700117 gomaccUsed := processGomaCccFlags(builder)
118 if !gomaccUsed {
119 processCCacheFlag(sysroot, builder)
120 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700121}
122
Tobias Boschef8f9692019-06-10 15:50:33 -0700123func getAbsWrapperDir(env env, wrapperPath string) (string, error) {
124 if !filepath.IsAbs(wrapperPath) {
125 wrapperPath = filepath.Join(env.getwd(), wrapperPath)
126 }
127 evaledCmdPath, err := filepath.EvalSymlinks(wrapperPath)
128 if err != nil {
Tobias Bosch900dbc92019-06-24 09:31:39 -0700129 return "", wrapErrorwithSourceLocf(err, "failed to evaluate symlinks for %s", wrapperPath)
Tobias Boschef8f9692019-06-10 15:50:33 -0700130 }
131 return filepath.Dir(evaledCmdPath), nil
132}
133
Tobias Bosch900dbc92019-06-24 09:31:39 -0700134func printCompilerError(writer io.Writer, compilerErr error) {
135 if _, ok := compilerErr.(userError); ok {
136 fmt.Fprintf(writer, "%s\n", compilerErr)
137 } else {
138 fmt.Fprintf(writer,
139 "Internal error. Please report to chromeos-toolchain@google.com.\n%s\n",
140 compilerErr)
Tobias Boschef8f9692019-06-10 15:50:33 -0700141 }
Tobias Boschef8f9692019-06-10 15:50:33 -0700142}