1package main 2 3import ( 4 "bufio" 5 "fmt" 6 "go/build/constraint" 7 "log" 8 "os" 9 "path/filepath" 10 "regexp" 11 "sort" 12 "strings" 13) 14 15var goVersionRegex = regexp.MustCompile(`^go1.(\d+)$`) 16 17// Used to update the list of tags affecting the standard library kept in 18// transitions.bzl. 19func main() { 20 if len(os.Args) < 2 { 21 log.Fatal("usage: stdlib_tags <go SDK src directory>...") 22 } 23 24 filteredTags, err := extractBuildTags(os.Args[1:]...) 25 if err != nil { 26 log.Fatal(err.Error()) 27 } 28 29 fmt.Printf("_TAG_AFFECTS_STDLIB = {\n") 30 for _, tag := range filteredTags { 31 fmt.Printf(" %q: None,\n", tag) 32 } 33 fmt.Printf("}\n") 34} 35 36func extractBuildTags(sdkPaths ...string) ([]string, error) { 37 tags := make(map[string]struct{}) 38 for _, dir := range sdkPaths { 39 err := filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error { 40 if d.IsDir() { 41 if d.Name() == "testdata" { 42 return filepath.SkipDir 43 } 44 return nil 45 } 46 if filepath.Ext(path) != ".go" { 47 return nil 48 } 49 if strings.HasSuffix(filepath.Base(path), "_test.go") { 50 return nil 51 } 52 return walkFile(path, tags) 53 }) 54 if err != nil { 55 return nil, fmt.Errorf("%s: %w", dir, err) 56 } 57 } 58 59 filteredTags := make([]string, 0, len(tags)) 60 for tag := range tags { 61 if !shouldExclude(tag) { 62 filteredTags = append(filteredTags, tag) 63 } 64 } 65 sort.Strings(filteredTags) 66 67 return filteredTags, nil 68} 69 70func shouldExclude(tag string) bool { 71 // Set via CGO_ENABLED 72 return tag == "cgo" || 73 // Set via GOARCH and GOOS 74 knownOS[tag] || knownArch[tag] || tag == "unix" || 75 // Set via GOEXPERIMENT and GOAMD64 76 strings.HasPrefix(tag, "goexperiment.") || strings.HasPrefix(tag, "amd64.") || 77 // Set implicitly 78 goVersionRegex.MatchString(tag) 79} 80 81func walkFile(path string, tags map[string]struct{}) error { 82 file, err := os.Open(path) 83 if err != nil { 84 return err 85 } 86 87 scanner := bufio.NewScanner(file) 88 // The Go SDK contains some very long lines in vendored files (minified JS). 89 scanner.Buffer(make([]byte, 0, 128*1024), 1024*1024) 90 for scanner.Scan() { 91 line := scanner.Text() 92 if !isConstraint(line) { 93 continue 94 } 95 c, err := constraint.Parse(line) 96 if err != nil { 97 continue 98 } 99 walkConstraint(c, tags) 100 } 101 102 if err = scanner.Err(); err != nil { 103 return fmt.Errorf("%s: %w", path, err) 104 } 105 return nil 106} 107 108func walkConstraint(c constraint.Expr, tags map[string]struct{}) { 109 switch c.(type) { 110 case *constraint.AndExpr: 111 walkConstraint(c.(*constraint.AndExpr).X, tags) 112 walkConstraint(c.(*constraint.AndExpr).Y, tags) 113 case *constraint.OrExpr: 114 walkConstraint(c.(*constraint.OrExpr).X, tags) 115 walkConstraint(c.(*constraint.OrExpr).Y, tags) 116 case *constraint.NotExpr: 117 walkConstraint(c.(*constraint.NotExpr).X, tags) 118 case *constraint.TagExpr: 119 tags[c.(*constraint.TagExpr).Tag] = struct{}{} 120 } 121} 122 123func isConstraint(line string) bool { 124 return constraint.IsPlusBuild(line) || constraint.IsGoBuild(line) 125} 126 127// Taken from 128// https://github.com/golang/go/blob/3d5391ed87d813110e10b954c62bf7ed578b591f/src/go/build/syslist.go 129var knownOS = map[string]bool{ 130 "aix": true, 131 "android": true, 132 "darwin": true, 133 "dragonfly": true, 134 "freebsd": true, 135 "hurd": true, 136 "illumos": true, 137 "ios": true, 138 "js": true, 139 "linux": true, 140 "nacl": true, 141 "netbsd": true, 142 "openbsd": true, 143 "plan9": true, 144 "solaris": true, 145 "windows": true, 146 "zos": true, 147} 148 149var knownArch = map[string]bool{ 150 "386": true, 151 "amd64": true, 152 "amd64p32": true, 153 "arm": true, 154 "armbe": true, 155 "arm64": true, 156 "arm64be": true, 157 "loong64": true, 158 "mips": true, 159 "mipsle": true, 160 "mips64": true, 161 "mips64le": true, 162 "mips64p32": true, 163 "mips64p32le": true, 164 "ppc": true, 165 "ppc64": true, 166 "ppc64le": true, 167 "riscv": true, 168 "riscv64": true, 169 "s390": true, 170 "s390x": true, 171 "sparc": true, 172 "sparc64": true, 173 "wasm": true, 174} 175