diff --git a/README.md b/README.md index ccdd214..fac8679 100644 --- a/README.md +++ b/README.md @@ -160,6 +160,7 @@ system. The currently supported options include. |`LLAMACC_LOCAL_PREPROCESS`| Run the preprocessor locally and send preprocessed source text to the cloud, instead of individual headers. Uses less total compute but much more bandwidth; this can easily saturate your uplink on large builds. | |`LLAMACC_FULL_PREPROCESS`| Run the full preprocessor locally, not just `#include` processing. Disables use of GCC-specific `-fdirectives-only`| |`LLAMACC_BUILD_ID`| Assigns an ID to the build. Used for Llama's internal tracing support. | +|`LLAMACC_FILTER_WARNINGS`| Filters the given comma-separated list of warnings out of all the compilations, e.g. `LLAMACC_FILTER_WARNINGS=missing-include-dirs,packed-not-aligned`. | It is strongly recommended that you use absolute paths if you set `LLAMACC_LOCAL_CC` and `LLAMACC_LOCAL_CXX`. Not all build systems will diff --git a/cmd/llamacc/arg_test.go b/cmd/llamacc/arg_test.go index 7a3984d..c0afe65 100644 --- a/cmd/llamacc/arg_test.go +++ b/cmd/llamacc/arg_test.go @@ -24,11 +24,13 @@ import ( func TestParseCompile(t *testing.T) { tests := []struct { + env []string argv []string out Compilation err bool }{ { + []string{}, []string{ "cc", "-MD", "-Wall", "-Werror", "-D_GNU_SOURCE", "-g", "-c", "-o", "platform/linux/linux_ptrace.o", "platform/linux/linux_ptrace.c", }, @@ -49,6 +51,29 @@ func TestParseCompile(t *testing.T) { false, }, { + []string{ + "LLAMACC_FILTER_WARNINGS=error,all", + }, + []string{ + "cc", "-MD", "-Wall", "-Werror", "-Wno-error", "-D_GNU_SOURCE", "-g", "-c", "-o", "platform/linux/linux_ptrace.o", "platform/linux/linux_ptrace.c", + }, Compilation{ + Language: "c", + PreprocessedLanguage: "cpp-output", + Input: "platform/linux/linux_ptrace.c", + Output: "platform/linux/linux_ptrace.o", + UnknownArgs: []string{"-g"}, + LocalArgs: []string{"-MD", "-D_GNU_SOURCE", "-g", "-MF", "platform/linux/linux_ptrace.d"}, + RemoteArgs: []string{"-g", "-c"}, + Flag: Flags{ + MD: true, + C: true, + MF: "platform/linux/linux_ptrace.d", + }, + }, + false, + }, + { + []string{}, []string{ "cc", "-c", "hello.c", }, @@ -65,6 +90,7 @@ func TestParseCompile(t *testing.T) { false, }, { + []string{}, []string{ "cc", "-c", "hello.c", "-o", "hello.o", }, @@ -81,6 +107,7 @@ func TestParseCompile(t *testing.T) { false, }, { + []string{}, []string{ "/usr/bin/cc", "-DBORINGSSL_DISPATCH_TEST", "-DBORINGSSL_HAVE_LIBUNWIND", "-DBORINGSSL_IMPLEMENTATION", "-I/home/nelhage/code/boringssl/third_party/googletest/include", "-I/home/nelhage/code/boringssl/crypto/../include", "-Wa,--noexecstack", "-Wa,-g", "-o", "CMakeFiles/crypto.dir/chacha/chacha-x86_64.S.o", "-c", "/home/nelhage/code/boringssl/build/crypto/chacha/chacha-x86_64.S", }, @@ -103,7 +130,8 @@ func TestParseCompile(t *testing.T) { tc := tc t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { t.Parallel() - got, err := ParseCompile(&DefaultConfig, tc.argv) + cfg := ParseConfig(tc.env) + got, err := ParseCompile(&cfg, tc.argv) // Don't compare includes or defines for now got.Includes = nil got.Defs = nil diff --git a/cmd/llamacc/args.go b/cmd/llamacc/args.go index e59af7d..1e7c82f 100644 --- a/cmd/llamacc/args.go +++ b/cmd/llamacc/args.go @@ -270,13 +270,31 @@ func ParseCompile(cfg *Config, argv []string) (Compilation, error) { args = rewriteWp(args) + specs := argSpecs + + // Append specs to remove any warning flags that we are filtering. + for _, w := range cfg.FilteredWarnings { + specs = append(specs, + argSpec{ + flag: "-W" + w, + action: func(*Compilation, string) (filterWhere, error) { return filterBoth, nil }, + hasArg: false, + }, + argSpec{ + flag: "-Wno-" + w, + action: func(*Compilation, string) (filterWhere, error) { return filterBoth, nil }, + hasArg: false, + }, + ) + } + i := 0 for i < len(args) { arg := args[i] i++ if strings.HasPrefix(arg, "-") { found := false - for _, spec := range argSpecs { + for _, spec := range specs { if !strings.HasPrefix(arg, spec.flag) { continue } diff --git a/cmd/llamacc/config.go b/cmd/llamacc/config.go index edcffe6..f2e557c 100644 --- a/cmd/llamacc/config.go +++ b/cmd/llamacc/config.go @@ -28,6 +28,10 @@ type Config struct { LocalPreprocess bool BuildID string + // FilteredWarnings is a list of warnings that we should always filter + // out of the compilation + FilteredWarnings []string + LocalCC string LocalCXX string } @@ -48,6 +52,25 @@ func BoolConfigTrue(val string) bool { } } +// StringArrayConfig splits a string configuration value using "," +// as the separator and eliding empty elements. +func StringArrayConfig(val string) []string { + if val == "" { + return nil + } + + var a []string + + for _, s := range strings.Split(val, ",") { + s = strings.TrimSpace(s) + if len(s) != 0 { + a = append(a, s) + } + } + + return a +} + func ParseConfig(env []string) Config { out := DefaultConfig for _, ev := range env { @@ -79,6 +102,8 @@ func ParseConfig(env []string) Config { out.LocalCC = val case "LOCAL_CXX": out.LocalCXX = val + case "FILTER_WARNINGS": + out.FilteredWarnings = StringArrayConfig(val) default: log.Printf("llamacc: unknown env var: %s", ev) } diff --git a/cmd/llamacc/config_test.go b/cmd/llamacc/config_test.go index 4fd8952..782a35e 100644 --- a/cmd/llamacc/config_test.go +++ b/cmd/llamacc/config_test.go @@ -29,3 +29,11 @@ func TestBoolConfigTrue(t *testing.T) { assert.False(t, BoolConfigTrue(v)) } } + +func TestStringArrayConfig(t *testing.T) { + assert.Equal(t, []string(nil), StringArrayConfig("")) + assert.Equal(t, []string{"b", "a"}, StringArrayConfig("b,a")) + assert.Equal(t, []string{"b", "a"}, StringArrayConfig("b,, ,a")) + assert.Equal(t, []string{"b", "a"}, StringArrayConfig("b ,\t a")) + assert.Equal(t, []string(nil), StringArrayConfig(",,,,")) +}