xref: /aosp_15_r20/external/swiftshader/tests/check_build_files/main.go (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker//
3*03ce13f7SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker//
7*03ce13f7SAndroid Build Coastguard Worker//    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker//
9*03ce13f7SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker// limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker
15*03ce13f7SAndroid Build Coastguard Worker// check_build_files scans all the .bp, .gn and .bazel files for source
16*03ce13f7SAndroid Build Coastguard Worker// references to non-existent files.
17*03ce13f7SAndroid Build Coastguard Worker
18*03ce13f7SAndroid Build Coastguard Workerpackage main
19*03ce13f7SAndroid Build Coastguard Worker
20*03ce13f7SAndroid Build Coastguard Workerimport (
21*03ce13f7SAndroid Build Coastguard Worker	"flag"
22*03ce13f7SAndroid Build Coastguard Worker	"fmt"
23*03ce13f7SAndroid Build Coastguard Worker	"io/ioutil"
24*03ce13f7SAndroid Build Coastguard Worker	"os"
25*03ce13f7SAndroid Build Coastguard Worker	"path/filepath"
26*03ce13f7SAndroid Build Coastguard Worker	"regexp"
27*03ce13f7SAndroid Build Coastguard Worker	"strings"
28*03ce13f7SAndroid Build Coastguard Worker)
29*03ce13f7SAndroid Build Coastguard Worker
30*03ce13f7SAndroid Build Coastguard Workerfunc cwd() string {
31*03ce13f7SAndroid Build Coastguard Worker	wd, err := os.Getwd()
32*03ce13f7SAndroid Build Coastguard Worker	if err != nil {
33*03ce13f7SAndroid Build Coastguard Worker		return ""
34*03ce13f7SAndroid Build Coastguard Worker	}
35*03ce13f7SAndroid Build Coastguard Worker	return wd
36*03ce13f7SAndroid Build Coastguard Worker}
37*03ce13f7SAndroid Build Coastguard Worker
38*03ce13f7SAndroid Build Coastguard Workervar root = flag.String("root", cwd(), "root project directory")
39*03ce13f7SAndroid Build Coastguard Worker
40*03ce13f7SAndroid Build Coastguard Workerfunc main() {
41*03ce13f7SAndroid Build Coastguard Worker	flag.Parse()
42*03ce13f7SAndroid Build Coastguard Worker
43*03ce13f7SAndroid Build Coastguard Worker	if err := run(); err != nil {
44*03ce13f7SAndroid Build Coastguard Worker		fmt.Fprintf(os.Stderr, "%v", err)
45*03ce13f7SAndroid Build Coastguard Worker		os.Exit(1)
46*03ce13f7SAndroid Build Coastguard Worker	}
47*03ce13f7SAndroid Build Coastguard Worker	fmt.Printf("Build file check completed with no errors\n")
48*03ce13f7SAndroid Build Coastguard Worker}
49*03ce13f7SAndroid Build Coastguard Worker
50*03ce13f7SAndroid Build Coastguard Workerfunc run() error {
51*03ce13f7SAndroid Build Coastguard Worker	wd := *root
52*03ce13f7SAndroid Build Coastguard Worker
53*03ce13f7SAndroid Build Coastguard Worker	errs := []error{}
54*03ce13f7SAndroid Build Coastguard Worker
55*03ce13f7SAndroid Build Coastguard Worker	filepath.Walk(wd, func(path string, info os.FileInfo, err error) error {
56*03ce13f7SAndroid Build Coastguard Worker		if err != nil {
57*03ce13f7SAndroid Build Coastguard Worker			return err
58*03ce13f7SAndroid Build Coastguard Worker		}
59*03ce13f7SAndroid Build Coastguard Worker
60*03ce13f7SAndroid Build Coastguard Worker		rel, err := filepath.Rel(wd, path)
61*03ce13f7SAndroid Build Coastguard Worker		if err != nil {
62*03ce13f7SAndroid Build Coastguard Worker			return filepath.SkipDir
63*03ce13f7SAndroid Build Coastguard Worker		}
64*03ce13f7SAndroid Build Coastguard Worker
65*03ce13f7SAndroid Build Coastguard Worker		switch rel {
66*03ce13f7SAndroid Build Coastguard Worker		case ".git", "cache", "build", "out", "third_party":
67*03ce13f7SAndroid Build Coastguard Worker			return filepath.SkipDir
68*03ce13f7SAndroid Build Coastguard Worker		}
69*03ce13f7SAndroid Build Coastguard Worker
70*03ce13f7SAndroid Build Coastguard Worker		if info.IsDir() {
71*03ce13f7SAndroid Build Coastguard Worker			return nil
72*03ce13f7SAndroid Build Coastguard Worker		}
73*03ce13f7SAndroid Build Coastguard Worker
74*03ce13f7SAndroid Build Coastguard Worker		content, err := ioutil.ReadFile(path)
75*03ce13f7SAndroid Build Coastguard Worker		if err != nil {
76*03ce13f7SAndroid Build Coastguard Worker			errs = append(errs, err)
77*03ce13f7SAndroid Build Coastguard Worker			return nil // Continue walking files
78*03ce13f7SAndroid Build Coastguard Worker		}
79*03ce13f7SAndroid Build Coastguard Worker
80*03ce13f7SAndroid Build Coastguard Worker		switch filepath.Ext(path) {
81*03ce13f7SAndroid Build Coastguard Worker		case ".bp":
82*03ce13f7SAndroid Build Coastguard Worker			errs = append(errs, checkBlueprint(path, string(content))...)
83*03ce13f7SAndroid Build Coastguard Worker		case ".gn":
84*03ce13f7SAndroid Build Coastguard Worker			errs = append(errs, checkGn(path, string(content))...)
85*03ce13f7SAndroid Build Coastguard Worker		case ".bazel":
86*03ce13f7SAndroid Build Coastguard Worker			errs = append(errs, checkBazel(path, string(content))...)
87*03ce13f7SAndroid Build Coastguard Worker		}
88*03ce13f7SAndroid Build Coastguard Worker
89*03ce13f7SAndroid Build Coastguard Worker		return nil
90*03ce13f7SAndroid Build Coastguard Worker	})
91*03ce13f7SAndroid Build Coastguard Worker
92*03ce13f7SAndroid Build Coastguard Worker	sb := strings.Builder{}
93*03ce13f7SAndroid Build Coastguard Worker	for _, err := range errs {
94*03ce13f7SAndroid Build Coastguard Worker		sb.WriteString(err.Error())
95*03ce13f7SAndroid Build Coastguard Worker		sb.WriteString("\n")
96*03ce13f7SAndroid Build Coastguard Worker	}
97*03ce13f7SAndroid Build Coastguard Worker	if sb.Len() > 0 {
98*03ce13f7SAndroid Build Coastguard Worker		return fmt.Errorf("%v", sb.String())
99*03ce13f7SAndroid Build Coastguard Worker	}
100*03ce13f7SAndroid Build Coastguard Worker	return nil
101*03ce13f7SAndroid Build Coastguard Worker}
102*03ce13f7SAndroid Build Coastguard Worker
103*03ce13f7SAndroid Build Coastguard Workervar (
104*03ce13f7SAndroid Build Coastguard Worker	reSources = regexp.MustCompile(`sources\s*=\s*\[([^\]]*)\]`)
105*03ce13f7SAndroid Build Coastguard Worker	reSrc     = regexp.MustCompile(`srcs\s*[:=]\s*\[([^\]]*)\]`)
106*03ce13f7SAndroid Build Coastguard Worker	reQuoted  = regexp.MustCompile(`"([^\"]*)"`)
107*03ce13f7SAndroid Build Coastguard Worker)
108*03ce13f7SAndroid Build Coastguard Worker
109*03ce13f7SAndroid Build Coastguard Workerfunc checkBlueprint(path, content string) []error {
110*03ce13f7SAndroid Build Coastguard Worker	errs := []error{}
111*03ce13f7SAndroid Build Coastguard Worker	for _, sources := range matchRE(reSrc, content) {
112*03ce13f7SAndroid Build Coastguard Worker		for _, source := range matchRE(reQuoted, sources) {
113*03ce13f7SAndroid Build Coastguard Worker			if strings.HasPrefix(source, ":") {
114*03ce13f7SAndroid Build Coastguard Worker				continue // Build target, we can't resolve.
115*03ce13f7SAndroid Build Coastguard Worker			}
116*03ce13f7SAndroid Build Coastguard Worker			if err := checkSource(path, source); err != nil {
117*03ce13f7SAndroid Build Coastguard Worker				errs = append(errs, err)
118*03ce13f7SAndroid Build Coastguard Worker			}
119*03ce13f7SAndroid Build Coastguard Worker		}
120*03ce13f7SAndroid Build Coastguard Worker	}
121*03ce13f7SAndroid Build Coastguard Worker	return errs
122*03ce13f7SAndroid Build Coastguard Worker}
123*03ce13f7SAndroid Build Coastguard Worker
124*03ce13f7SAndroid Build Coastguard Workerfunc checkGn(path, content string) []error {
125*03ce13f7SAndroid Build Coastguard Worker	errs := []error{}
126*03ce13f7SAndroid Build Coastguard Worker	for _, sources := range matchRE(reSources, content) {
127*03ce13f7SAndroid Build Coastguard Worker		for _, source := range matchRE(reQuoted, sources) {
128*03ce13f7SAndroid Build Coastguard Worker			if strings.ContainsAny(source, "$") {
129*03ce13f7SAndroid Build Coastguard Worker				return nil // Env vars we can't resolve
130*03ce13f7SAndroid Build Coastguard Worker			}
131*03ce13f7SAndroid Build Coastguard Worker			if strings.HasPrefix(source, "//") {
132*03ce13f7SAndroid Build Coastguard Worker				continue // Build target, we can't resolve.
133*03ce13f7SAndroid Build Coastguard Worker			}
134*03ce13f7SAndroid Build Coastguard Worker			if err := checkSource(path, source); err != nil {
135*03ce13f7SAndroid Build Coastguard Worker				errs = append(errs, err)
136*03ce13f7SAndroid Build Coastguard Worker			}
137*03ce13f7SAndroid Build Coastguard Worker		}
138*03ce13f7SAndroid Build Coastguard Worker	}
139*03ce13f7SAndroid Build Coastguard Worker	return errs
140*03ce13f7SAndroid Build Coastguard Worker}
141*03ce13f7SAndroid Build Coastguard Worker
142*03ce13f7SAndroid Build Coastguard Workerfunc checkBazel(path, content string) []error {
143*03ce13f7SAndroid Build Coastguard Worker	errs := []error{}
144*03ce13f7SAndroid Build Coastguard Worker	for _, sources := range matchRE(reSrc, content) {
145*03ce13f7SAndroid Build Coastguard Worker		for _, source := range matchRE(reQuoted, sources) {
146*03ce13f7SAndroid Build Coastguard Worker			if strings.HasPrefix(source, "@") || strings.HasPrefix(source, ":") {
147*03ce13f7SAndroid Build Coastguard Worker				continue // Build target, we can't resolve.
148*03ce13f7SAndroid Build Coastguard Worker			}
149*03ce13f7SAndroid Build Coastguard Worker			if err := checkSource(path, source); err != nil {
150*03ce13f7SAndroid Build Coastguard Worker				errs = append(errs, err)
151*03ce13f7SAndroid Build Coastguard Worker			}
152*03ce13f7SAndroid Build Coastguard Worker		}
153*03ce13f7SAndroid Build Coastguard Worker	}
154*03ce13f7SAndroid Build Coastguard Worker	return errs
155*03ce13f7SAndroid Build Coastguard Worker}
156*03ce13f7SAndroid Build Coastguard Worker
157*03ce13f7SAndroid Build Coastguard Workerfunc checkSource(path, source string) error {
158*03ce13f7SAndroid Build Coastguard Worker	source = filepath.Join(filepath.Dir(path), source)
159*03ce13f7SAndroid Build Coastguard Worker
160*03ce13f7SAndroid Build Coastguard Worker	if strings.Contains(source, "*") {
161*03ce13f7SAndroid Build Coastguard Worker		sources, err := filepath.Glob(source)
162*03ce13f7SAndroid Build Coastguard Worker		if err != nil {
163*03ce13f7SAndroid Build Coastguard Worker			return fmt.Errorf("In '%v': %w", path, err)
164*03ce13f7SAndroid Build Coastguard Worker		}
165*03ce13f7SAndroid Build Coastguard Worker		if len(sources) == 0 {
166*03ce13f7SAndroid Build Coastguard Worker			return fmt.Errorf("In '%v': Glob '%v' does not reference any files", path, source)
167*03ce13f7SAndroid Build Coastguard Worker		}
168*03ce13f7SAndroid Build Coastguard Worker		return nil
169*03ce13f7SAndroid Build Coastguard Worker	}
170*03ce13f7SAndroid Build Coastguard Worker
171*03ce13f7SAndroid Build Coastguard Worker	stat, err := os.Stat(source)
172*03ce13f7SAndroid Build Coastguard Worker	if err != nil {
173*03ce13f7SAndroid Build Coastguard Worker		return fmt.Errorf("In '%v': %w", path, err)
174*03ce13f7SAndroid Build Coastguard Worker	}
175*03ce13f7SAndroid Build Coastguard Worker	if stat.IsDir() {
176*03ce13f7SAndroid Build Coastguard Worker		return fmt.Errorf("In '%v': '%v' refers to a directory, not a file", path, source)
177*03ce13f7SAndroid Build Coastguard Worker	}
178*03ce13f7SAndroid Build Coastguard Worker	return nil
179*03ce13f7SAndroid Build Coastguard Worker}
180*03ce13f7SAndroid Build Coastguard Worker
181*03ce13f7SAndroid Build Coastguard Workerfunc matchRE(re *regexp.Regexp, text string) []string {
182*03ce13f7SAndroid Build Coastguard Worker	out := []string{}
183*03ce13f7SAndroid Build Coastguard Worker	for _, match := range re.FindAllStringSubmatch(text, -1) {
184*03ce13f7SAndroid Build Coastguard Worker		if len(match) < 2 {
185*03ce13f7SAndroid Build Coastguard Worker			return nil
186*03ce13f7SAndroid Build Coastguard Worker		}
187*03ce13f7SAndroid Build Coastguard Worker		out = append(out, match[1])
188*03ce13f7SAndroid Build Coastguard Worker	}
189*03ce13f7SAndroid Build Coastguard Worker	return out
190*03ce13f7SAndroid Build Coastguard Worker}
191