diff options
Diffstat (limited to 'compiler_wrapper')
-rw-r--r-- | compiler_wrapper/bisect_flag.go | 1 | ||||
-rw-r--r-- | compiler_wrapper/bisect_flag_test.go | 16 | ||||
-rw-r--r-- | compiler_wrapper/clang_syntax_flag_test.go | 27 | ||||
-rw-r--r-- | compiler_wrapper/clang_tidy_flag_test.go | 35 | ||||
-rw-r--r-- | compiler_wrapper/compiler_wrapper.go | 36 | ||||
-rw-r--r-- | compiler_wrapper/config.go | 22 | ||||
-rw-r--r-- | compiler_wrapper/config_test.go | 24 | ||||
-rw-r--r-- | compiler_wrapper/disable_werror_flag.go | 5 | ||||
-rw-r--r-- | compiler_wrapper/disable_werror_flag_test.go | 30 | ||||
-rw-r--r-- | compiler_wrapper/oldwrapper.go | 27 | ||||
-rw-r--r-- | compiler_wrapper/sanitizer_flags.go | 5 | ||||
-rw-r--r-- | compiler_wrapper/sanitizer_flags_test.go | 24 |
12 files changed, 213 insertions, 39 deletions
diff --git a/compiler_wrapper/bisect_flag.go b/compiler_wrapper/bisect_flag.go index 9cab75bd..9eb59dc4 100644 --- a/compiler_wrapper/bisect_flag.go +++ b/compiler_wrapper/bisect_flag.go @@ -21,5 +21,6 @@ func calcBisectCommand(env env, bisectStage string, compilerCmd *command) *comma bisectDir, absCompilerPath, }, compilerCmd.Args...), + EnvUpdates: compilerCmd.EnvUpdates, } } diff --git a/compiler_wrapper/bisect_flag_test.go b/compiler_wrapper/bisect_flag_test.go index 2b099912..1ccf6051 100644 --- a/compiler_wrapper/bisect_flag_test.go +++ b/compiler_wrapper/bisect_flag_test.go @@ -27,6 +27,22 @@ func TestCallBisectDriver(t *testing.T) { }) } +func TestCallBisectDriverWithCCache(t *testing.T) { + withBisectTestContext(t, func(ctx *testContext) { + ctx.cfg.useCCache = true + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) + if err := verifyPath(cmd, "/usr/bin/python2"); err != nil { + t.Error(err) + } + if err := verifyArgCount(cmd, 1, "/usr/bin/ccache"); err != nil { + t.Error(err) + } + if err := verifyEnvUpdate(cmd, "CCACHE_DIR=.*"); err != nil { + t.Error(err) + } + }) +} + func TestDefaultBisectDir(t *testing.T) { withBisectTestContext(t, func(ctx *testContext) { ctx.env = []string{ diff --git a/compiler_wrapper/clang_syntax_flag_test.go b/compiler_wrapper/clang_syntax_flag_test.go index d2661812..c30d9795 100644 --- a/compiler_wrapper/clang_syntax_flag_test.go +++ b/compiler_wrapper/clang_syntax_flag_test.go @@ -124,10 +124,35 @@ func TestUseGomaForClangSyntaxCheck(t *testing.T) { } return nil } - ctx.must(callCompiler(ctx, ctx.cfg, + cmd := ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) if ctx.cmdCount != 2 { t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) } + if err := verifyPath(cmd, gomaPath); err != nil { + t.Error(err) + } + }) +} + +func TestPartiallyOmitCCacheForClangSyntaxCheck(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.useCCache = true + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + if ctx.cmdCount == 1 { + if err := verifyPath(cmd, "usr/bin/clang"); err != nil { + return err + } + } + return nil + } + cmd := ctx.must(callCompiler(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, "-clang-syntax", mainCc))) + if ctx.cmdCount != 2 { + t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) + } + if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { + t.Error(err) + } }) } diff --git a/compiler_wrapper/clang_tidy_flag_test.go b/compiler_wrapper/clang_tidy_flag_test.go index 9c0fc928..9ca37d8f 100644 --- a/compiler_wrapper/clang_tidy_flag_test.go +++ b/compiler_wrapper/clang_tidy_flag_test.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "io" + "path" "strings" "testing" ) @@ -234,6 +235,40 @@ func TestOmitCCacheWithClangTidy(t *testing.T) { }) } +func TestPartiallyOmitGomaWithClangTidy(t *testing.T) { + withClangTidyTestContext(t, func(ctx *testContext) { + gomaPath := path.Join(ctx.tempDir, "gomacc") + // Create a file so the gomacc path is valid. + ctx.writeFile(gomaPath, "") + ctx.env = append(ctx.env, "GOMACC_PATH="+gomaPath) + + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + switch ctx.cmdCount { + case 1: + if err := verifyPath(cmd, "usr/bin/clang"); err != nil { + t.Error(err) + } + return nil + case 2: + if err := verifyPath(cmd, "usr/bin/clang-tidy"); err != nil { + return err + } + return nil + default: + return nil + } + } + cmd := ctx.must(callCompiler(ctx, ctx.cfg, + ctx.newCommand(clangX86_64, mainCc))) + if ctx.cmdCount != 3 { + t.Errorf("expected 3 calls. Got: %d", ctx.cmdCount) + } + if err := verifyPath(cmd, gomaPath); err != nil { + t.Error(err) + } + }) +} + func withClangTidyTestContext(t *testing.T, work func(ctx *testContext)) { withTestContext(t, func(ctx *testContext) { ctx.env = []string{"WITH_TIDY=1"} diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go index 314a8a71..8bee238d 100644 --- a/compiler_wrapper/compiler_wrapper.go +++ b/compiler_wrapper/compiler_wrapper.go @@ -50,19 +50,24 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int clangSyntax := processClangSyntaxFlag(mainBuilder) if mainBuilder.target.compilerType == clangType { cSrcFile, useClangTidy := processClangTidyFlags(mainBuilder) - compilerCmd, err = calcClangCommand(useClangTidy, mainBuilder) + sysroot, err := prepareClangCommand(mainBuilder) if err != nil { return 0, err } + allowCCache := true if useClangTidy { - if err := runClangTidy(env, compilerCmd, cSrcFile); err != nil { + allowCCache = false + clangCmdWithoutGomaAndCCache := mainBuilder.build() + if err := runClangTidy(env, clangCmdWithoutGomaAndCCache, cSrcFile); err != nil { return 0, err } } + processGomaCCacheFlags(sysroot, allowCCache, mainBuilder) + compilerCmd = mainBuilder.build() } else { if clangSyntax { - forceLocal := false - clangCmd, err := calcClangCommand(forceLocal, mainBuilder.clone()) + allowCCache := false + clangCmd, err := calcClangCommand(allowCCache, mainBuilder.clone()) if err != nil { return 0, err } @@ -98,16 +103,22 @@ func callCompilerInternal(env env, cfg *config, inputCmd *command) (exitCode int return wrapSubprocessErrorWithSourceLoc(compilerCmd, env.exec(compilerCmd)) } -func calcClangCommand(forceLocal bool, builder *commandBuilder) (*command, error) { - sysroot := processSysrootFlag(builder) +func prepareClangCommand(builder *commandBuilder) (sysroot string, err error) { + sysroot = processSysrootFlag(builder) builder.addPreUserArgs(builder.cfg.clangFlags...) calcCommonPreUserArgs(builder) if err := processClangFlags(builder); err != nil { - return nil, err + return "", err } - if !forceLocal { - processGomaCCacheFlags(sysroot, builder) + return sysroot, nil +} + +func calcClangCommand(allowCCache bool, builder *commandBuilder) (*command, error) { + sysroot, err := prepareClangCommand(builder) + if err != nil { + return nil, err } + processGomaCCacheFlags(sysroot, allowCCache, builder) return builder.build(), nil } @@ -116,7 +127,8 @@ func calcGccCommand(builder *commandBuilder) *command { builder.addPreUserArgs(builder.cfg.gccFlags...) calcCommonPreUserArgs(builder) processGccFlags(builder) - processGomaCCacheFlags(sysroot, builder) + allowCCache := true + processGomaCCacheFlags(sysroot, allowCCache, builder) return builder.build() } @@ -129,9 +141,9 @@ func calcCommonPreUserArgs(builder *commandBuilder) { processSanitizerFlags(builder) } -func processGomaCCacheFlags(sysroot string, builder *commandBuilder) { +func processGomaCCacheFlags(sysroot string, allowCCache bool, builder *commandBuilder) { gomaccUsed := processGomaCccFlags(builder) - if !gomaccUsed { + if !gomaccUsed && allowCCache { processCCacheFlag(sysroot, builder) } } diff --git a/compiler_wrapper/config.go b/compiler_wrapper/config.go index 5e594cc3..45e82575 100644 --- a/compiler_wrapper/config.go +++ b/compiler_wrapper/config.go @@ -68,29 +68,29 @@ func getCrosHardenedConfig(useCCache bool) *config { rootRelPath: "../../../../..", oldWrapperPath: "./sysroot_wrapper.hardened.old", commonFlags: []string{ - "-fPIE", - "-D_FORTIFY_SOURCE=2", "-fstack-protector-strong", + "-fPIE", "-pie", + "-D_FORTIFY_SOURCE=2", "-fno-omit-frame-pointer", }, gccFlags: []string{ + "-fno-reorder-blocks-and-partition", "-Wno-unused-local-typedefs", "-Wno-maybe-uninitialized", - "-fno-reorder-blocks-and-partition", }, // Temporarily disable tautological-*-compare chromium:778316. // Temporarily add no-unknown-warning-option to deal with old clang versions. // Temporarily disable Wsection since kernel gets a bunch of these. chromium:778867 // Disable "-faddrsig" since it produces object files that strip doesn't understand, chromium:915742. clangFlags: []string{ - "-Wno-tautological-unsigned-enum-zero-compare", "-Qunused-arguments", "-grecord-gcc-switches", - "-Wno-section", - "-Wno-unknown-warning-option", "-fno-addrsig", "-Wno-tautological-constant-compare", + "-Wno-tautological-unsigned-enum-zero-compare", + "-Wno-unknown-warning-option", + "-Wno-section", }, newWarningsDir: "/tmp/fatal_clang_warnings", } @@ -104,20 +104,20 @@ func getCrosNonHardenedConfig(useCCache bool) *config { oldWrapperPath: "./sysroot_wrapper.old", commonFlags: []string{}, gccFlags: []string{ - "-Wno-unused-local-typedefs", "-Wno-maybe-uninitialized", - "-Wtrampolines", + "-Wno-unused-local-typedefs", "-Wno-deprecated-declarations", + "-Wtrampolines", }, // Temporarily disable tautological-*-compare chromium:778316. // Temporarily add no-unknown-warning-option to deal with old clang versions. // Temporarily disable Wsection since kernel gets a bunch of these. chromium:778867 clangFlags: []string{ - "-Wno-unknown-warning-option", "-Qunused-arguments", - "-Wno-section", - "-Wno-tautological-unsigned-enum-zero-compare", "-Wno-tautological-constant-compare", + "-Wno-tautological-unsigned-enum-zero-compare", + "-Wno-unknown-warning-option", + "-Wno-section", }, newWarningsDir: "/tmp/fatal_clang_warnings", } diff --git a/compiler_wrapper/config_test.go b/compiler_wrapper/config_test.go index bd7aec03..5578baf0 100644 --- a/compiler_wrapper/config_test.go +++ b/compiler_wrapper/config_test.go @@ -13,9 +13,9 @@ func TestFullHardeningConfigAndGcc(t *testing.T) { if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } - if err := verifyArgOrder(cmd, gccX86_64+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-unused-local-typedefs", - "-Wno-maybe-uninitialized", "-fno-reorder-blocks-and-partition", "-fPIE", "-D_FORTIFY_SOURCE=2", "-fstack-protector-strong", - "-pie", "-fno-omit-frame-pointer", "main.cc", "-mno-movbe"); err != nil { + if err := verifyArgOrder(cmd, gccX86_64+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", "-fno-reorder-blocks-and-partition", + "-Wno-unused-local-typedefs", "-Wno-maybe-uninitialized", "-fstack-protector-strong", "-fPIE", "-pie", "-D_FORTIFY_SOURCE=2", + "-fno-omit-frame-pointer", "main.cc", "-mno-movbe"); err != nil { t.Error(err) } }) @@ -34,10 +34,10 @@ func TestFullHardeningConfigAndClang(t *testing.T) { t.Error(err) } binPath, err := filepath.Rel(ctx.tempDir, "/bin") - if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-tautological-unsigned-enum-zero-compare", - "-Qunused-arguments", "-grecord-gcc-switches", "-Wno-section", "-Wno-unknown-warning-option", "-fno-addrsig", - "-Wno-tautological-constant-compare", "-fPIE", "-D_FORTIFY_SOURCE=2", "-fstack-protector-strong", "-pie", - "-fno-omit-frame-pointer", "main.cc", "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil { + if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Qunused-arguments", "-grecord-gcc-switches", + "-fno-addrsig", "-Wno-tautological-constant-compare", "-Wno-tautological-unsigned-enum-zero-compare", "-Wno-unknown-warning-option", + "-Wno-section", "-fstack-protector-strong", "-fPIE", "-pie", "-D_FORTIFY_SOURCE=2", "-fno-omit-frame-pointer", "main.cc", + "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil { t.Error(err) } }) @@ -52,8 +52,8 @@ func TestNonHardeningConfigAndGcc(t *testing.T) { t.Error(err) } if err := verifyArgOrder(cmd, gccX86_64+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", - "-Wno-unused-local-typedefs", "-Wno-maybe-uninitialized", "-Wtrampolines", - "-Wno-deprecated-declarations", "main.cc", "-mno-movbe"); err != nil { + "-Wno-maybe-uninitialized", "-Wno-unused-local-typedefs", "-Wno-deprecated-declarations", + "-Wtrampolines", "main.cc", "-mno-movbe"); err != nil { t.Error(err) } }) @@ -72,9 +72,9 @@ func TestNonHardeningConfigAndClang(t *testing.T) { t.Error(err) } binPath, err := filepath.Rel(ctx.tempDir, "/bin") - if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-unknown-warning-option", - "-Qunused-arguments", "-Wno-section", "-Wno-tautological-unsigned-enum-zero-compare", - "-Wno-tautological-constant-compare", "main.cc", "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil { + if err := verifyArgOrder(cmd, clangPath, "--sysroot=/usr/x86_64-cros-linux-gnu", "-Qunused-arguments", + "-Wno-tautological-constant-compare", "-Wno-tautological-unsigned-enum-zero-compare", + "-Wno-unknown-warning-option", "-Wno-section", "main.cc", "-B"+binPath, "-target", "x86_64-cros-linux-gnu"); err != nil { t.Error(err) } }) diff --git a/compiler_wrapper/disable_werror_flag.go b/compiler_wrapper/disable_werror_flag.go index e4037bad..33bb725b 100644 --- a/compiler_wrapper/disable_werror_flag.go +++ b/compiler_wrapper/disable_werror_flag.go @@ -15,6 +15,11 @@ func shouldForceDisableWError(env env) bool { func doubleBuildWithWNoError(env env, cfg *config, originalCmd *command) (exitCode int, err error) { originalStdoutBuffer := &bytes.Buffer{} originalStderrBuffer := &bytes.Buffer{} + // TODO: This is a bug in the old wrapper that it drops the ccache path + // during double build. Fix this once we don't compare to the old wrapper anymore. + if originalCmd.Path == "/usr/bin/ccache" { + originalCmd.Path = "ccache" + } originalExitCode, err := wrapSubprocessErrorWithSourceLoc(originalCmd, env.run(originalCmd, originalStdoutBuffer, originalStderrBuffer)) if err != nil { diff --git a/compiler_wrapper/disable_werror_flag_test.go b/compiler_wrapper/disable_werror_flag_test.go index affd8875..7ab938e3 100644 --- a/compiler_wrapper/disable_werror_flag_test.go +++ b/compiler_wrapper/disable_werror_flag_test.go @@ -66,6 +66,36 @@ func TestDoubleBuildWithWNoErrorFlag(t *testing.T) { }) } +func TestDoubleBuildWithWNoErrorAndCCache(t *testing.T) { + withForceDisableWErrorTestContext(t, func(ctx *testContext) { + ctx.cfg.useCCache = true + ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { + switch ctx.cmdCount { + case 1: + // TODO: This is a bug in the old wrapper that it drops the ccache path + // during double build. Fix this once we don't compare to the old wrapper anymore. + if err := verifyPath(cmd, "ccache"); err != nil { + return err + } + fmt.Fprint(stderr, "-Werror originalerror") + return newExitCodeError(1) + case 2: + if err := verifyPath(cmd, "ccache"); err != nil { + return err + } + return nil + default: + t.Fatalf("unexpected command: %#v", cmd) + return nil + } + } + ctx.must(callCompiler(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc))) + if ctx.cmdCount != 2 { + t.Errorf("expected 2 calls. Got: %d", ctx.cmdCount) + } + }) +} + func TestForwardStdoutAndStderrWhenDoubleBuildSucceeds(t *testing.T) { withForceDisableWErrorTestContext(t, func(ctx *testContext) { ctx.cmdMock = func(cmd *command, stdout io.Writer, stderr io.Writer) error { diff --git a/compiler_wrapper/oldwrapper.go b/compiler_wrapper/oldwrapper.go index 315e6ea8..a6324400 100644 --- a/compiler_wrapper/oldwrapper.go +++ b/compiler_wrapper/oldwrapper.go @@ -183,13 +183,15 @@ func newOldWrapperConfig(env env, cfg *config, inputCmd *command) (*oldWrapperCo return nil, wrapErrorwithSourceLocf(err, "failed to read old wrapper") } oldWrapperContent := string(oldWrapperContentBytes) + oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "from __future__ import print_function", "") // Disable the original call to main() oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "__name__", "'none'") + // Replace sets with lists to make our comparisons deterministic + oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "set(", "ListSet(") // Inject the value of cfg.useCCache if !cfg.useCCache { oldWrapperContent = regexp.MustCompile(`True\s+#\s+@CCACHE_DEFAULT@`).ReplaceAllString(oldWrapperContent, "False #") } - return &oldWrapperConfig{ CmdPath: inputCmd.Path, OldWrapperContent: oldWrapperContent, @@ -207,7 +209,28 @@ func callOldWrapper(env env, cfg *oldWrapperConfig, inputCmd *command, filepatte } defer os.Remove(mockFile.Name()) - const mockTemplate = `{{.OldWrapperContent}} + const mockTemplate = ` +from __future__ import print_function + +class ListSet: + def __init__(self, values): + self.values = list(values) + def __contains__(self, key): + return self.values.__contains__(key) + def __iter__(self): + return self.values.__iter__() + def __nonzero__(self): + return len(self.values) > 0 + def add(self, value): + if value not in self.values: + self.values.append(value) + def discard(self, value): + if value in self.values: + self.values.remove(value) + def intersection(self, values): + return ListSet([value for value in self.values if value in values]) + +{{.OldWrapperContent}} import subprocess init_env = os.environ.copy() diff --git a/compiler_wrapper/sanitizer_flags.go b/compiler_wrapper/sanitizer_flags.go index 1823dcb1..7e513803 100644 --- a/compiler_wrapper/sanitizer_flags.go +++ b/compiler_wrapper/sanitizer_flags.go @@ -24,7 +24,10 @@ func processSanitizerFlags(builder *commandBuilder) { } builder.transformArgs(func(arg builderArg) string { - if unsupportedSanitizerFlags[arg.value] { + // TODO: This is a bug in the old wrapper to not filter + // non user args for gcc. Fix this once we don't compare to the old wrapper anymore. + if (builder.target.compilerType != gccType || arg.fromUser) && + unsupportedSanitizerFlags[arg.value] { return "" } return arg.value diff --git a/compiler_wrapper/sanitizer_flags_test.go b/compiler_wrapper/sanitizer_flags_test.go index 2b348779..091af25a 100644 --- a/compiler_wrapper/sanitizer_flags_test.go +++ b/compiler_wrapper/sanitizer_flags_test.go @@ -32,6 +32,30 @@ func TestFilterUnsupportedSanitizerFlagsIfSanitizeGiven(t *testing.T) { }) } +func TestFilterUnsupportedDefaultSanitizerFlagsIfSanitizeGivenForClang(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.commonFlags = []string{"-D_FORTIFY_SOURCE=1"} + cmd := ctx.must(callCompiler(ctx, ctx.cfg, + ctx.newCommand(clangX86_64, "-fsanitize=kernel-address", mainCc))) + if err := verifyArgCount(cmd, 0, "-D_FORTIFY_SOURCE=1"); err != nil { + t.Error(err) + } + }) +} + +func TestKeepUnsupportedDefaultSanitizerFlagsIfSanitizeGivenForGcc(t *testing.T) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.commonFlags = []string{"-D_FORTIFY_SOURCE=1"} + cmd := ctx.must(callCompiler(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, "-fsanitize=kernel-address", mainCc))) + if err := verifyArgCount(cmd, 1, "-D_FORTIFY_SOURCE=1"); err != nil { + t.Error(err) + } + }) +} + +// TODO: This is a bug in the old wrapper to not filter +// non user args for gcc. Fix this once we don't compare to the old wrapper anymore. func TestKeepSanitizerFlagsIfNoSanitizeGiven(t *testing.T) { withTestContext(t, func(ctx *testContext) { cmd := ctx.must(callCompiler(ctx, ctx.cfg, |