From a3217b71723a93abb7a2aca535408ab84d81ac2f Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Fri, 28 Dec 2018 07:24:56 -0800 Subject: Extract go_merge into its own package This change is needed to support building gvisor for Fuchsia, which uses Chromium's GN build system; at the time of writing, Fuchsia's Go support does not include explicit enumeration of files, assuming instead that Go binaries are always built from all Go source files in a given package. Rather than extending Fuchsia's Go support, it is easier simply to extract a separate package here. PiperOrigin-RevId: 227133402 Change-Id: I1c64fff286d9c014b4bd1183b76023b35b60c720 --- tools/go_generics/BUILD | 8 --- tools/go_generics/defs.bzl | 2 +- tools/go_generics/go_merge/BUILD | 9 +++ tools/go_generics/go_merge/main.go | 139 +++++++++++++++++++++++++++++++++++++ tools/go_generics/merge.go | 139 ------------------------------------- 5 files changed, 149 insertions(+), 148 deletions(-) create mode 100644 tools/go_generics/go_merge/BUILD create mode 100644 tools/go_generics/go_merge/main.go delete mode 100644 tools/go_generics/merge.go diff --git a/tools/go_generics/BUILD b/tools/go_generics/BUILD index 22c2e62c3..2d97d99dc 100644 --- a/tools/go_generics/BUILD +++ b/tools/go_generics/BUILD @@ -13,14 +13,6 @@ go_binary( deps = ["//tools/go_generics/globals"], ) -go_binary( - name = "go_merge", - srcs = [ - "merge.go", - ], - visibility = ["//visibility:public"], -) - genrule( name = "go_generics_tests", srcs = glob(["generics_tests/**"]) + [":go_generics"], diff --git a/tools/go_generics/defs.bzl b/tools/go_generics/defs.bzl index 631bd11d3..999fb3426 100644 --- a/tools/go_generics/defs.bzl +++ b/tools/go_generics/defs.bzl @@ -48,7 +48,7 @@ go_template = rule( "opt_types": attr.string_list(), "consts": attr.string_list(), "opt_consts": attr.string_list(), - "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics:go_merge")), + "_tool": attr.label(executable = True, cfg = "host", default = Label("//tools/go_generics/go_merge")), }, outputs = { "out": "%{name}_template.go", diff --git a/tools/go_generics/go_merge/BUILD b/tools/go_generics/go_merge/BUILD new file mode 100644 index 000000000..a60437962 --- /dev/null +++ b/tools/go_generics/go_merge/BUILD @@ -0,0 +1,9 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_binary") + +package(licenses = ["notice"]) # Apache 2.0 + +go_binary( + name = "go_merge", + srcs = ["main.go"], + visibility = ["//visibility:public"], +) diff --git a/tools/go_generics/go_merge/main.go b/tools/go_generics/go_merge/main.go new file mode 100644 index 000000000..2f83facf8 --- /dev/null +++ b/tools/go_generics/go_merge/main.go @@ -0,0 +1,139 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "bytes" + "flag" + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "io/ioutil" + "os" + "path/filepath" + "strconv" +) + +var ( + output = flag.String("o", "", "output `file`") +) + +func fatalf(s string, args ...interface{}) { + fmt.Fprintf(os.Stderr, s, args...) + os.Exit(1) +} + +func main() { + flag.Usage = func() { + fmt.Fprintf(os.Stderr, "Usage: %s [options] [ ...]\n", os.Args[0]) + flag.PrintDefaults() + } + + flag.Parse() + if *output == "" || len(flag.Args()) == 0 { + flag.Usage() + os.Exit(1) + } + + // Load all files. + files := make(map[string]*ast.File) + fset := token.NewFileSet() + var name string + for _, fname := range flag.Args() { + f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments|parser.DeclarationErrors|parser.SpuriousErrors) + if err != nil { + fatalf("%v\n", err) + } + + files[fname] = f + if name == "" { + name = f.Name.Name + } else if name != f.Name.Name { + fatalf("Expected '%s' for package name instead of '%s'.\n", name, f.Name.Name) + } + } + + // Merge all files into one. + pkg := &ast.Package{ + Name: name, + Files: files, + } + f := ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments|ast.FilterFuncDuplicates|ast.FilterImportDuplicates) + + // Create a new declaration slice with all imports at the top, merging any + // redundant imports. + imports := make(map[string]*ast.ImportSpec) + var anonImports []*ast.ImportSpec + for _, d := range f.Decls { + if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.IMPORT { + for _, s := range g.Specs { + i := s.(*ast.ImportSpec) + p, _ := strconv.Unquote(i.Path.Value) + var n string + if i.Name == nil { + n = filepath.Base(p) + } else { + n = i.Name.Name + } + if n == "_" { + anonImports = append(anonImports, i) + } else { + if i2, ok := imports[n]; ok { + if first, second := i.Path.Value, i2.Path.Value; first != second { + fatalf("Conflicting paths for import name '%s': '%s' vs. '%s'\n", n, first, second) + } + } else { + imports[n] = i + } + } + } + } + } + newDecls := make([]ast.Decl, 0, len(f.Decls)) + if l := len(imports) + len(anonImports); l > 0 { + // Non-NoPos Lparen is needed for Go to recognize more than one spec in + // ast.GenDecl.Specs. + d := &ast.GenDecl{ + Tok: token.IMPORT, + Lparen: token.NoPos + 1, + Specs: make([]ast.Spec, 0, l), + } + for _, i := range imports { + d.Specs = append(d.Specs, i) + } + for _, i := range anonImports { + d.Specs = append(d.Specs, i) + } + newDecls = append(newDecls, d) + } + for _, d := range f.Decls { + if g, ok := d.(*ast.GenDecl); !ok || g.Tok != token.IMPORT { + newDecls = append(newDecls, d) + } + } + f.Decls = newDecls + + // Write the output file. + var buf bytes.Buffer + if err := format.Node(&buf, fset, f); err != nil { + fatalf("%v\n", err) + } + + if err := ioutil.WriteFile(*output, buf.Bytes(), 0644); err != nil { + fatalf("%v\n", err) + } +} diff --git a/tools/go_generics/merge.go b/tools/go_generics/merge.go deleted file mode 100644 index 2f83facf8..000000000 --- a/tools/go_generics/merge.go +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "bytes" - "flag" - "fmt" - "go/ast" - "go/format" - "go/parser" - "go/token" - "io/ioutil" - "os" - "path/filepath" - "strconv" -) - -var ( - output = flag.String("o", "", "output `file`") -) - -func fatalf(s string, args ...interface{}) { - fmt.Fprintf(os.Stderr, s, args...) - os.Exit(1) -} - -func main() { - flag.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage: %s [options] [ ...]\n", os.Args[0]) - flag.PrintDefaults() - } - - flag.Parse() - if *output == "" || len(flag.Args()) == 0 { - flag.Usage() - os.Exit(1) - } - - // Load all files. - files := make(map[string]*ast.File) - fset := token.NewFileSet() - var name string - for _, fname := range flag.Args() { - f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments|parser.DeclarationErrors|parser.SpuriousErrors) - if err != nil { - fatalf("%v\n", err) - } - - files[fname] = f - if name == "" { - name = f.Name.Name - } else if name != f.Name.Name { - fatalf("Expected '%s' for package name instead of '%s'.\n", name, f.Name.Name) - } - } - - // Merge all files into one. - pkg := &ast.Package{ - Name: name, - Files: files, - } - f := ast.MergePackageFiles(pkg, ast.FilterUnassociatedComments|ast.FilterFuncDuplicates|ast.FilterImportDuplicates) - - // Create a new declaration slice with all imports at the top, merging any - // redundant imports. - imports := make(map[string]*ast.ImportSpec) - var anonImports []*ast.ImportSpec - for _, d := range f.Decls { - if g, ok := d.(*ast.GenDecl); ok && g.Tok == token.IMPORT { - for _, s := range g.Specs { - i := s.(*ast.ImportSpec) - p, _ := strconv.Unquote(i.Path.Value) - var n string - if i.Name == nil { - n = filepath.Base(p) - } else { - n = i.Name.Name - } - if n == "_" { - anonImports = append(anonImports, i) - } else { - if i2, ok := imports[n]; ok { - if first, second := i.Path.Value, i2.Path.Value; first != second { - fatalf("Conflicting paths for import name '%s': '%s' vs. '%s'\n", n, first, second) - } - } else { - imports[n] = i - } - } - } - } - } - newDecls := make([]ast.Decl, 0, len(f.Decls)) - if l := len(imports) + len(anonImports); l > 0 { - // Non-NoPos Lparen is needed for Go to recognize more than one spec in - // ast.GenDecl.Specs. - d := &ast.GenDecl{ - Tok: token.IMPORT, - Lparen: token.NoPos + 1, - Specs: make([]ast.Spec, 0, l), - } - for _, i := range imports { - d.Specs = append(d.Specs, i) - } - for _, i := range anonImports { - d.Specs = append(d.Specs, i) - } - newDecls = append(newDecls, d) - } - for _, d := range f.Decls { - if g, ok := d.(*ast.GenDecl); !ok || g.Tok != token.IMPORT { - newDecls = append(newDecls, d) - } - } - f.Decls = newDecls - - // Write the output file. - var buf bytes.Buffer - if err := format.Node(&buf, fset, f); err != nil { - fatalf("%v\n", err) - } - - if err := ioutil.WriteFile(*output, buf.Bytes(), 0644); err != nil { - fatalf("%v\n", err) - } -} -- cgit v1.2.3