diff options
author | Tobias Bosch <tbosch@google.com> | 2019-06-20 17:47:19 -0700 |
---|---|---|
committer | Tobias Bosch <tbosch@google.com> | 2019-06-25 14:47:26 +0000 |
commit | aa31116c1d7c2491245604f0564e0693f22dfd71 (patch) | |
tree | 4fd8fb92a9a459bb718f8d0c943a05632defbd08 /compiler_wrapper | |
parent | b9992bba3b4e752f10410c624a500762d090fa2b (diff) | |
download | toolchain-utils-aa31116c1d7c2491245604f0564e0693f22dfd71.tar.gz |
Allow to pass in the use_ccache via go build.
Removes usage of go build tags in favor of passing in
configuration via -ldflags -X ...
BUG=chromium:773875
TEST=unit test
Change-Id: I4e8a58e1679b2858e9d4620d6b9c7a35ad08a6ee
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/1670987
Reviewed-by: George Burgess <gbiv@chromium.org>
Tested-by: Tobias Bosch <tbosch@google.com>
Diffstat (limited to 'compiler_wrapper')
-rwxr-xr-x | compiler_wrapper/build | 35 | ||||
-rwxr-xr-x | compiler_wrapper/build_cros_hardened_wrapper.sh | 5 | ||||
-rwxr-xr-x | compiler_wrapper/build_cros_nonhardened_wrapper.sh | 5 | ||||
-rw-r--r-- | compiler_wrapper/ccache_flag.go | 2 | ||||
-rw-r--r-- | compiler_wrapper/ccache_flag_test.go | 49 | ||||
-rw-r--r-- | compiler_wrapper/command.go | 4 | ||||
-rw-r--r-- | compiler_wrapper/compiler_wrapper.go | 2 | ||||
-rw-r--r-- | compiler_wrapper/config.go | 146 | ||||
-rw-r--r-- | compiler_wrapper/config_test.go | 101 | ||||
-rw-r--r-- | compiler_wrapper/cros_hardened_config.go | 7 | ||||
-rw-r--r-- | compiler_wrapper/cros_nonhardened_config.go | 7 | ||||
-rw-r--r-- | compiler_wrapper/gcc_flags_test.go | 10 | ||||
-rw-r--r-- | compiler_wrapper/gomacc_flag_test.go | 10 | ||||
-rw-r--r-- | compiler_wrapper/main.go | 21 | ||||
-rw-r--r-- | compiler_wrapper/oldwrapper.go | 52 | ||||
-rw-r--r-- | compiler_wrapper/sysroot_flag_test.go | 4 |
16 files changed, 310 insertions, 150 deletions
diff --git a/compiler_wrapper/build b/compiler_wrapper/build new file mode 100755 index 00000000..9365b738 --- /dev/null +++ b/compiler_wrapper/build @@ -0,0 +1,35 @@ +#!/usr/bin/env python2 +# -*- coding: utf-8 -*- +# Copyright 2019 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""Build script that wraps go build and sets the correct linker variables.""" + +from __future__ import print_function + +import argparse +import os +import os.path +import subprocess +import sys + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--config", required=True, + choices=['cros.hardened', 'cros.nonhardened'], type=str) + parser.add_argument("--use_ccache", required=True, + choices=['true', 'false'], type=str) + return parser.parse_known_args() + +def calc_go_args(parsed_args, rest_args): + src_dir = os.path.dirname(sys.argv[0]) + ldFlags = ['-X', 'main.ConfigName=' + parsed_args.config, + '-X', 'main.UseCCache='+parsed_args.use_ccache] + return (['go', 'build', '-ldflags', ' '.join(ldFlags)] + + rest_args + [src_dir]) + +def main(): + sys.exit(subprocess.call(calc_go_args(*parse_args()))) + +if __name__ == '__main__': + main() diff --git a/compiler_wrapper/build_cros_hardened_wrapper.sh b/compiler_wrapper/build_cros_hardened_wrapper.sh deleted file mode 100755 index 82d9e14c..00000000 --- a/compiler_wrapper/build_cros_hardened_wrapper.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -eu -# Copyright 2019 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -go build -tags "cros hardened" "$@" diff --git a/compiler_wrapper/build_cros_nonhardened_wrapper.sh b/compiler_wrapper/build_cros_nonhardened_wrapper.sh deleted file mode 100755 index 94e591fc..00000000 --- a/compiler_wrapper/build_cros_nonhardened_wrapper.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash -eu -# Copyright 2019 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -go build -tags "cros nonhardened" "$@" diff --git a/compiler_wrapper/ccache_flag.go b/compiler_wrapper/ccache_flag.go index 13ee234d..95dd296a 100644 --- a/compiler_wrapper/ccache_flag.go +++ b/compiler_wrapper/ccache_flag.go @@ -15,7 +15,7 @@ func processCCacheFlag(sysroot string, builder *commandBuilder) { return arg.Value }) - if useCCache { + if builder.cfg.useCCache && useCCache { // We need to get ccache to make relative paths from within the // sysroot. This lets us share cached files across boards (if // all other things are equal of course like CFLAGS) as well as diff --git a/compiler_wrapper/ccache_flag_test.go b/compiler_wrapper/ccache_flag_test.go index 15fc3177..b46ab388 100644 --- a/compiler_wrapper/ccache_flag_test.go +++ b/compiler_wrapper/ccache_flag_test.go @@ -4,24 +4,34 @@ import ( "testing" ) -func TestCallCCache(t *testing.T) { - withTestContext(t, func(ctx *testContext) { - wrapperCmd := ctx.newCommand(gccX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) +func TestCallCCacheGivenConfig(t *testing.T) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } - if err := verifyArgOrder(cmd, wrapperCmd.path+".real", mainCc); err != nil { + if err := verifyArgOrder(cmd, gccX86_64+".real", mainCc); err != nil { t.Error(err) } }) } -func TestNotCallCCacheIfNoCCacheArgGiven(t *testing.T) { +func TestNotCallCCacheGivenConfig(t *testing.T) { withTestContext(t, func(ctx *testContext) { - wrapperCmd := ctx.newCommand(gccX86_64, "-noccache", mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) - if err := verifyPath(cmd, wrapperCmd.path+".real"); err != nil { + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) + if err := verifyPath(cmd, gccX86_64+".real"); err != nil { + t.Error(err) + } + }) +} + +func TestNotCallCCacheGivenConfigAndNoCCacheArg(t *testing.T) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, "-noccache", mainCc))) + if err := verifyPath(cmd, gccX86_64+".real"); err != nil { t.Error(err) } if err := verifyArgCount(cmd, 0, "-noccache"); err != nil { @@ -31,7 +41,7 @@ func TestNotCallCCacheIfNoCCacheArgGiven(t *testing.T) { } func TestSetCacheDir(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyEnvUpdate(cmd, "CCACHE_DIR=/var/cache/distfiles/ccache"); err != nil { @@ -41,7 +51,7 @@ func TestSetCacheDir(t *testing.T) { } func TestSetCacheBaseDirToSysroot(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyEnvUpdate(cmd, @@ -52,7 +62,7 @@ func TestSetCacheBaseDirToSysroot(t *testing.T) { } func TestSetCacheUmask(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyEnvUpdate(cmd, "CCACHE_UMASK=002"); err != nil { @@ -62,7 +72,7 @@ func TestSetCacheUmask(t *testing.T) { } func TestUpdateSandboxRewrite(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyNoEnvUpdate(cmd, "SANDBOX_WRITE"); err != nil { @@ -80,7 +90,7 @@ func TestUpdateSandboxRewrite(t *testing.T) { } func TestClearCacheDisable(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyNoEnvUpdate(cmd, "SANDBOX_WRITE"); err != nil { @@ -97,7 +107,7 @@ func TestClearCacheDisable(t *testing.T) { } func TestAddCCacheCpp2FlagForClang(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(clangX86_64, mainCc))) if err := verifyEnvUpdate(cmd, "CCACHE_CPP2=yes"); err != nil { @@ -107,7 +117,7 @@ func TestAddCCacheCpp2FlagForClang(t *testing.T) { } func TestOmitCCacheCpp2FlagForGcc(t *testing.T) { - withTestContext(t, func(ctx *testContext) { + withCCacheEnabledTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) if err := verifyNoEnvUpdate(cmd, "CCACHE_CPP2"); err != nil { @@ -115,3 +125,10 @@ func TestOmitCCacheCpp2FlagForGcc(t *testing.T) { } }) } + +func withCCacheEnabledTestContext(t *testing.T, work func(ctx *testContext)) { + withTestContext(t, func(ctx *testContext) { + ctx.cfg.useCCache = true + work(ctx) + }) +} diff --git a/compiler_wrapper/command.go b/compiler_wrapper/command.go index c73acb86..618a1323 100644 --- a/compiler_wrapper/command.go +++ b/compiler_wrapper/command.go @@ -60,7 +60,7 @@ func (actual *command) verifySimilarTo(expected *command) error { return nil } -func newCommandBuilder(env env, cmd *command) (*commandBuilder, error) { +func newCommandBuilder(env env, cfg *config, cmd *command) (*commandBuilder, error) { basename := filepath.Base(cmd.path) nameParts := strings.Split(basename, "-") if len(nameParts) != 5 { @@ -83,6 +83,7 @@ func newCommandBuilder(env env, cmd *command) (*commandBuilder, error) { path: cmd.path, args: createBuilderArgs( /*fromUser=*/ true, cmd.args), env: env, + cfg: cfg, target: builderTarget{ target: strings.Join(nameParts[:4], "-"), arch: nameParts[0], @@ -101,6 +102,7 @@ type commandBuilder struct { args []builderArg envUpdates []string env env + cfg *config } type builderArg struct { diff --git a/compiler_wrapper/compiler_wrapper.go b/compiler_wrapper/compiler_wrapper.go index 72e1749c..6034fb0f 100644 --- a/compiler_wrapper/compiler_wrapper.go +++ b/compiler_wrapper/compiler_wrapper.go @@ -15,7 +15,7 @@ func calcCompilerCommand(env env, cfg *config, wrapperCmd *command) (*command, e if err := checkUnsupportedFlags(wrapperCmd); err != nil { return nil, err } - builder, err := newCommandBuilder(env, wrapperCmd) + builder, err := newCommandBuilder(env, cfg, wrapperCmd) if err != nil { return nil, err } diff --git a/compiler_wrapper/config.go b/compiler_wrapper/config.go index 909edf0a..1e78fbef 100644 --- a/compiler_wrapper/config.go +++ b/compiler_wrapper/config.go @@ -1,6 +1,13 @@ package main +import ( + "fmt" + "strconv" +) + type config struct { + // Whether to use ccache. + useCCache bool // Flags to add to gcc and clang. commonFlags []string // Flags to add to gcc only. @@ -14,57 +21,98 @@ type config struct { overrideOldWrapperConfig bool } +// UseCCache can be set via a linker flag. +// Value will be passed to strconv.ParseBool. +// E.g. go build -ldflags '-X config.UseCCache=true'. +var UseCCache = "unknown" + +// ConfigName can be set via a linker flag. +// Value has to be one of: +// - "cros.hardened" +// - "cros.nonhardened" +var ConfigName = "unknown" + +// Returns the configuration matching the UseCCache and ConfigName. +func getRealConfig() (*config, error) { + useCCache, err := strconv.ParseBool(UseCCache) + if err != nil { + return nil, fmt.Errorf("Parse error for UseCCache: %s", err) + } + config, err := getConfig(useCCache, ConfigName) + if err != nil { + return nil, err + } + return config, nil +} + +func getConfig(useCCache bool, configName string) (*config, error) { + switch configName { + case "cros.hardened": + return getCrosHardenedConfig(useCCache), nil + case "cros.nonhardened": + return getCrosNonHardenedConfig(useCCache), nil + default: + return nil, fmt.Errorf("Unknown config name: %s", configName) + } +} + // Full hardening. -// Temporarily disable function splitting because of chromium:434751. -var crosHardenedConfig = config{ - rootRelPath: "../../../../..", - oldWrapperPath: "./sysroot_wrapper.hardened.old", - commonFlags: []string{ - "-fPIE", - "-D_FORTIFY_SOURCE=2", - "-fstack-protector-strong", - "-pie", - "-fno-omit-frame-pointer", - }, - gccFlags: []string{ - "-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", - }, +func getCrosHardenedConfig(useCCache bool) *config { + // Temporarily disable function splitting because of chromium:434751. + return &config{ + useCCache: useCCache, + rootRelPath: "../../../../..", + oldWrapperPath: "./sysroot_wrapper.hardened.old", + commonFlags: []string{ + "-fPIE", + "-D_FORTIFY_SOURCE=2", + "-fstack-protector-strong", + "-pie", + "-fno-omit-frame-pointer", + }, + gccFlags: []string{ + "-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", + }, + } } // Flags to be added to non-hardened toolchain. -var crosNonHardenedConfig = config{ - rootRelPath: "../../../../..", - oldWrapperPath: "./sysroot_wrapper.old", - commonFlags: []string{}, - gccFlags: []string{ - "-Wno-unused-local-typedefs", - "-Wno-maybe-uninitialized", - "-Wtrampolines", - "-Wno-deprecated-declarations", - }, - // 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", - }, +func getCrosNonHardenedConfig(useCCache bool) *config { + return &config{ + useCCache: useCCache, + rootRelPath: "../../../../..", + oldWrapperPath: "./sysroot_wrapper.old", + commonFlags: []string{}, + gccFlags: []string{ + "-Wno-unused-local-typedefs", + "-Wno-maybe-uninitialized", + "-Wtrampolines", + "-Wno-deprecated-declarations", + }, + // 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", + }, + } } diff --git a/compiler_wrapper/config_test.go b/compiler_wrapper/config_test.go index 9a75acbd..0dcd58dc 100644 --- a/compiler_wrapper/config_test.go +++ b/compiler_wrapper/config_test.go @@ -8,12 +8,12 @@ import ( func TestFullHardeningConfigAndGcc(t *testing.T) { withTestContext(t, func(ctx *testContext) { initFullHardeningConfig(ctx) - wrapperCmd := ctx.newCommand(gccX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } - if err := verifyArgOrder(cmd, wrapperCmd.path+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", "-Wno-unused-local-typedefs", + 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 { t.Error(err) @@ -24,8 +24,8 @@ func TestFullHardeningConfigAndGcc(t *testing.T) { func TestFullHardeningConfigAndClang(t *testing.T) { withTestContext(t, func(ctx *testContext) { initFullHardeningConfig(ctx) - wrapperCmd := ctx.newCommand(clangX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(clangX86_64, mainCc))) if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } @@ -46,12 +46,12 @@ func TestFullHardeningConfigAndClang(t *testing.T) { func TestNonHardeningConfigAndGcc(t *testing.T) { withTestContext(t, func(ctx *testContext) { initNonHardeningConfig(ctx) - wrapperCmd := ctx.newCommand(gccX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } - if err := verifyArgOrder(cmd, wrapperCmd.path+".real", "--sysroot=/usr/x86_64-cros-linux-gnu", + 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 { t.Error(err) @@ -62,8 +62,8 @@ func TestNonHardeningConfigAndGcc(t *testing.T) { func TestNonHardeningConfigAndClang(t *testing.T) { withTestContext(t, func(ctx *testContext) { initNonHardeningConfig(ctx) - wrapperCmd := ctx.newCommand(clangX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(clangX86_64, mainCc))) if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { t.Error(err) } @@ -80,12 +80,89 @@ func TestNonHardeningConfigAndClang(t *testing.T) { }) } +func TestRealConfigWithUseCCacheFlag(t *testing.T) { + resetGlobals() + defer resetGlobals() + ConfigName = "cros.hardened" + + UseCCache = "false" + cfg, err := getRealConfig() + if err != nil { + t.Fatal(err) + } + if cfg.useCCache { + t.Fatal("UseCCache: Expected false got true") + } + + UseCCache = "true" + cfg, err = getRealConfig() + if err != nil { + t.Fatal(err) + } + if !cfg.useCCache { + t.Fatal("UseCCache: Expected true got false") + } + + UseCCache = "invalid" + _, err = getRealConfig() + if err == nil { + t.Fatalf("UseCCache: Expected an error, got none") + } +} + +func TestRealConfigWithConfigNameFlag(t *testing.T) { + resetGlobals() + defer resetGlobals() + UseCCache = "false" + + ConfigName = "cros.hardened" + cfg, err := getRealConfig() + if err != nil { + t.Fatal(err) + } + if !isHardened(cfg) { + t.Fatal("ConfigName: Expected hardened config got non hardened") + } + + ConfigName = "cros.nonhardened" + cfg, err = getRealConfig() + if err != nil { + t.Fatal(err) + } + if isHardened(cfg) { + t.Fatal("ConfigName: Expected non hardened config got hardened") + } + + ConfigName = "invalid" + _, err = getRealConfig() + if err == nil { + t.Fatalf("ConfigName: Expected an error, got none") + } +} + +func isHardened(cfg *config) bool { + for _, arg := range cfg.commonFlags { + if arg == "-pie" { + return true + } + } + return false +} + func initFullHardeningConfig(ctx *testContext) { - *ctx.cfg = crosHardenedConfig + useCCache := true + *ctx.cfg = *getCrosHardenedConfig(useCCache) ctx.setOldWrapperPath(oldHardenedWrapperPathForTest) } func initNonHardeningConfig(ctx *testContext) { - *ctx.cfg = crosNonHardenedConfig + useCCache := true + *ctx.cfg = *getCrosNonHardenedConfig(useCCache) ctx.setOldWrapperPath(oldNonHardenedWrapperPathForTest) } + +func resetGlobals() { + // Set all global variables to a defined state. + ConfigName = "unknown" + UseCCache = "unknown" +} diff --git a/compiler_wrapper/cros_hardened_config.go b/compiler_wrapper/cros_hardened_config.go deleted file mode 100644 index 0ab8ab40..00000000 --- a/compiler_wrapper/cros_hardened_config.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build cros,hardened - -package main - -func getRealConfig() *config { - return &crosHardenedConfig -} diff --git a/compiler_wrapper/cros_nonhardened_config.go b/compiler_wrapper/cros_nonhardened_config.go deleted file mode 100644 index 9106a4da..00000000 --- a/compiler_wrapper/cros_nonhardened_config.go +++ /dev/null @@ -1,7 +0,0 @@ -// +build cros,nonhardened - -package main - -func getRealConfig() *config { - return &crosNonHardenedConfig -} diff --git a/compiler_wrapper/gcc_flags_test.go b/compiler_wrapper/gcc_flags_test.go index 12119f0b..9e34216d 100644 --- a/compiler_wrapper/gcc_flags_test.go +++ b/compiler_wrapper/gcc_flags_test.go @@ -6,9 +6,9 @@ import ( func TestCallRealGcc(t *testing.T) { withTestContext(t, func(ctx *testContext) { - wrapperCmd := ctx.newCommand(gccX86_64, "-noccache", mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) - if err := verifyPath(cmd, wrapperCmd.path+".real"); err != nil { + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) + if err := verifyPath(cmd, gccX86_64+".real"); err != nil { t.Error(err) } }) @@ -16,8 +16,8 @@ func TestCallRealGcc(t *testing.T) { func TestCallRealGPlusPlus(t *testing.T) { withTestContext(t, func(ctx *testContext) { - wrapperCmd := ctx.newCommand("./x86_64-cros-linux-gnu-g++", "-noccache", mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand("./x86_64-cros-linux-gnu-g++", mainCc))) if err := verifyPath(cmd, "\\./x86_64-cros-linux-gnu-g\\+\\+\\.real"); err != nil { t.Error(err) } diff --git a/compiler_wrapper/gomacc_flag_test.go b/compiler_wrapper/gomacc_flag_test.go index 1372df22..5e8d66c9 100644 --- a/compiler_wrapper/gomacc_flag_test.go +++ b/compiler_wrapper/gomacc_flag_test.go @@ -11,12 +11,12 @@ func TestCallGomaccIfEnvIsGivenAndValid(t *testing.T) { // Create a file so the gomacc path is valid. ctx.writeFile(gomaPath, "") ctx.env = []string{"GOMACC_PATH=" + gomaPath} - wrapperCmd := ctx.newCommand(gccX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) if err := verifyPath(cmd, gomaPath); err != nil { t.Error(err) } - if err := verifyArgOrder(cmd, wrapperCmd.path+".real", mainCc); err != nil { + if err := verifyArgOrder(cmd, gccX86_64+".real", mainCc); err != nil { t.Error(err) } }) @@ -29,7 +29,7 @@ func TestOmitGomaccIfEnvIsGivenButInvalid(t *testing.T) { ctx.env = []string{"GOMACC_PATH=" + gomaPath} cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) - if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { + if err := verifyPath(cmd, gccX86_64+".real"); err != nil { t.Error(err) } }) @@ -39,7 +39,7 @@ func TestOmitGomaccByDefault(t *testing.T) { withTestContext(t, func(ctx *testContext) { cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, ctx.newCommand(gccX86_64, mainCc))) - if err := verifyPath(cmd, "/usr/bin/ccache"); err != nil { + if err := verifyPath(cmd, gccX86_64+".real"); err != nil { t.Error(err) } }) diff --git a/compiler_wrapper/main.go b/compiler_wrapper/main.go index 5323a301..9e131329 100644 --- a/compiler_wrapper/main.go +++ b/compiler_wrapper/main.go @@ -1,13 +1,11 @@ -// +build cros - -// This binary uses the following build tags: -// - cros: Whether the wrapper should be built for ChromeOS -// - nonhardened: For a non-hardened set of compiler flags -// - hardened: For a hardened set of compiler flags +// This binary requires the following linker variables: +// - main.UseCCache: Whether to use ccache. +// - main.ConfigName: Name of the configuration to use. +// See config.go for the supported values. // -// There is a bash script for every meaningful combination. -// E.g. ./build_cros_hardened_wrapper.sh will build the ChromeOS -// hardened compiler wrapper. +// The script ./build simplifies the call to `go build`. +// E.g. ./build --use_ccache=true --config=cros.hardened will build a +// binary that uses the ccache for ChromeOS with hardened flags. // // Test arguments: // - crosroot: Specifies the ChromeOS toolchain root directory (aka chroot). @@ -33,7 +31,10 @@ func main() { if err != nil { log.Fatal(err) } - cfg := getRealConfig() + cfg, err := getRealConfig() + if err != nil { + log.Fatal(err) + } if shouldForwardToOldWrapper(env, wrapperCmd) { err := forwardToOldWrapper(env, cfg, wrapperCmd) if err != nil { diff --git a/compiler_wrapper/oldwrapper.go b/compiler_wrapper/oldwrapper.go index bc9d5eac..46077731 100644 --- a/compiler_wrapper/oldwrapper.go +++ b/compiler_wrapper/oldwrapper.go @@ -8,6 +8,7 @@ import ( "os" "os/exec" "path/filepath" + "regexp" "strings" "text/template" ) @@ -101,19 +102,31 @@ func writeOldWrapperMock(writer io.Writer, env env, cfg *config, wrapperCmd *com } absOldWrapperPath = filepath.Join(absWrapperDir, cfg.oldWrapperPath) } + oldWrapperContentBytes, err := ioutil.ReadFile(absOldWrapperPath) + if err != nil { + return err + } + oldWrapperContent := string(oldWrapperContentBytes) + // Disable the original call to main() + oldWrapperContent = strings.ReplaceAll(oldWrapperContent, "__name__", "'none'") + // Inject the value of cfg.useCCache + if !cfg.useCCache { + oldWrapperContent = regexp.MustCompile(`True\s+#\s+@CCACHE_DEFAULT@`).ReplaceAllString(oldWrapperContent, "False #") + } + // Note: Fieldnames need to be upper case so that they can be read via reflection. mockData := struct { - CmdPath string - WrapperPath string - RootRelPath string - MockForks bool - OverwriteConfig bool - CommonFlags []string - GccFlags []string - ClangFlags []string + CmdPath string + OldWrapperContent string + RootRelPath string + MockForks bool + OverwriteConfig bool + CommonFlags []string + GccFlags []string + ClangFlags []string }{ wrapperCmd.path, - absOldWrapperPath, + oldWrapperContent, cfg.rootRelPath, mockForks, cfg.overrideOldWrapperConfig, @@ -122,11 +135,7 @@ func writeOldWrapperMock(writer io.Writer, env env, cfg *config, wrapperCmd *com cfg.clangFlags, } - const mockTemplate = `from __future__ import print_function -import imp -import os -import sys - + const mockTemplate = `{{.OldWrapperContent}} {{if .MockForks}} init_env = os.environ.copy() @@ -144,20 +153,15 @@ os.execv = execv_mock sys.argv[0] = '{{.CmdPath}}' -# Equivalent to "import wrapper", but does not need a ".py" suffix. -# Also avoids writing '.pyc' files -sys.dont_write_bytecode = True -wrapper = imp.load_source('wrapper', '{{.WrapperPath}}') - -wrapper.ROOT_REL_PATH = '{{.RootRelPath}}' +ROOT_REL_PATH = '{{.RootRelPath}}' {{if .OverwriteConfig}} -wrapper.FLAGS_TO_ADD=set([{{range .CommonFlags}}'{{.}}',{{end}}]) -wrapper.GCC_FLAGS_TO_ADD=set([{{range .GccFlags}}'{{.}}',{{end}}]) -wrapper.CLANG_FLAGS_TO_ADD=set([{{range .ClangFlags}}'{{.}}',{{end}}]) +FLAGS_TO_ADD=set([{{range .CommonFlags}}'{{.}}',{{end}}]) +GCC_FLAGS_TO_ADD=set([{{range .GccFlags}}'{{.}}',{{end}}]) +CLANG_FLAGS_TO_ADD=set([{{range .ClangFlags}}'{{.}}',{{end}}]) {{end}} -wrapper.main() +sys.exit(main()) ` tmpl, err := template.New("mock").Parse(mockTemplate) diff --git a/compiler_wrapper/sysroot_flag_test.go b/compiler_wrapper/sysroot_flag_test.go index dd726291..93d995d9 100644 --- a/compiler_wrapper/sysroot_flag_test.go +++ b/compiler_wrapper/sysroot_flag_test.go @@ -37,8 +37,8 @@ func TestSetSysrootFlagFromEnv(t *testing.T) { func TestSetSysrootRelativeToWrapperPath(t *testing.T) { withTestContext(t, func(ctx *testContext) { ctx.cfg.rootRelPath = "somepath" - wrapperCmd := ctx.newCommand(gccX86_64, mainCc) - cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, wrapperCmd)) + cmd := ctx.must(calcCompilerCommandAndCompareToOld(ctx, ctx.cfg, + ctx.newCommand(gccX86_64, mainCc))) if err := verifyArgOrder(cmd, "--sysroot="+ctx.tempDir+"/somepath/usr/x86_64-cros-linux-gnu", mainCc); err != nil { t.Error(err) |