...

Source file src/github.com/bazelbuild/buildtools/generatetables/generate_tables.go

Documentation: github.com/bazelbuild/buildtools/generatetables

     1  /*
     2  Copyright 2016 Google LLC
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      https://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  // generateTables is a tool that generates a go file from the Build language proto file.
    18  // It generates a Go map to find the type of an attribute.
    19  
    20  package main
    21  
    22  import (
    23  	"flag"
    24  	"fmt"
    25  	"io/ioutil"
    26  	"log"
    27  	"os"
    28  	"sort"
    29  
    30  	buildpb "github.com/bazelbuild/buildtools/build_proto"
    31  	"github.com/golang/protobuf/proto"
    32  )
    33  
    34  var inputPath = flag.String("input", "", "input file")
    35  var outputPath = flag.String("output", "", "output file")
    36  
    37  // bazelBuildLanguage reads a proto file and returns a BuildLanguage object.
    38  func bazelBuildLanguage(file string) (*buildpb.BuildLanguage, error) {
    39  	data, err := ioutil.ReadFile(file)
    40  	if err != nil {
    41  		fmt.Fprintf(os.Stderr, "Cannot read %s: %s\n", file, err)
    42  		return nil, err
    43  	}
    44  
    45  	lang := &buildpb.BuildLanguage{}
    46  	if err := proto.Unmarshal(data, lang); err != nil {
    47  		return nil, err
    48  	}
    49  	return lang, nil
    50  }
    51  
    52  // generateTable returns a map that associate a type for each attribute name found in Bazel.
    53  func generateTable(rules []*buildpb.RuleDefinition) map[string]buildpb.Attribute_Discriminator {
    54  	types := make(map[string]buildpb.Attribute_Discriminator)
    55  	for _, r := range rules {
    56  		for _, attr := range r.Attribute {
    57  			types[*attr.Name] = *attr.Type
    58  		}
    59  	}
    60  
    61  	// Because of inconsistencies in bazel, we need a few exceptions.
    62  	types["resources"] = buildpb.Attribute_LABEL_LIST
    63  	types["out"] = buildpb.Attribute_STRING
    64  	types["outs"] = buildpb.Attribute_STRING_LIST
    65  	types["stamp"] = buildpb.Attribute_TRISTATE
    66  	types["strip"] = buildpb.Attribute_BOOLEAN
    67  
    68  	// Surprisingly, the name argument is missing.
    69  	types["name"] = buildpb.Attribute_STRING
    70  
    71  	// package arguments are also not listed in the proto file
    72  	types["default_hdrs_check"] = buildpb.Attribute_STRING
    73  	types["default_visibility"] = types["visibility"]
    74  	types["default_copts"] = types["copts"]
    75  	types["default_deprecation"] = types["deprecation"]
    76  	types["default_testonly"] = types["testonly"]
    77  	types["default_applicable_licenses"] = buildpb.Attribute_LABEL_LIST
    78  	types["default_package_metadata"] = buildpb.Attribute_LABEL_LIST
    79  	types["features"] = buildpb.Attribute_STRING_LIST
    80  
    81  	types["extra_srcs"] = types["srcs"]
    82  	types["pytype_deps"] = types["deps"]
    83  
    84  	// Make sure we always have this.
    85  	_, ok := types["package_metadata"]
    86  	if ! ok {
    87  		types["package_metadata"] = buildpb.Attribute_LABEL_LIST
    88  	}
    89  
    90  	return types
    91  }
    92  
    93  func main() {
    94  	flag.Parse()
    95  	if *inputPath == "" {
    96  		log.Fatal("No input file specified")
    97  	}
    98  	lang, err := bazelBuildLanguage(*inputPath)
    99  	if err != nil {
   100  		log.Fatalf("%s\n", err)
   101  	}
   102  	types := generateTable(lang.Rule)
   103  
   104  	// sort the keys to get deterministic output
   105  	keys := make([]string, 0, len(types))
   106  	for i := range types {
   107  		keys = append(keys, i)
   108  	}
   109  	sort.Strings(keys)
   110  
   111  	f, err := os.Create(*outputPath)
   112  	if err != nil {
   113  		log.Fatalf("%s\n", err)
   114  	}
   115  	defer f.Close()
   116  
   117  	// print
   118  	fmt.Fprintf(f, `// Generated file, do not edit.
   119  package lang
   120  
   121  import buildpb "github.com/bazelbuild/buildtools/build_proto"
   122  
   123  var TypeOf = map[string]buildpb.Attribute_Discriminator{
   124  `)
   125  	for _, attr := range keys {
   126  		fmt.Fprintf(f, "	\"%s\":	buildpb.Attribute_%s,\n", attr, types[attr])
   127  	}
   128  	fmt.Fprintf(f, "}\n")
   129  }
   130  

View as plain text