• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1package bp2build
2
3import (
4	"reflect"
5	"strings"
6
7	"android/soong/android"
8	"github.com/google/blueprint/proptools"
9)
10
11type BazelFile struct {
12	Dir      string
13	Basename string
14	Contents string
15}
16
17func CreateBazelFiles(ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
18	var files []BazelFile
19
20	if mode == QueryView {
21		// Write top level WORKSPACE.
22		files = append(files, newFile("", "WORKSPACE", ""))
23
24		// Used to denote that the top level directory is a package.
25		files = append(files, newFile("", GeneratedBuildFileName, ""))
26
27		files = append(files, newFile(bazelRulesSubDir, GeneratedBuildFileName, ""))
28
29		// These files are only used for queryview.
30		files = append(files, newFile(bazelRulesSubDir, "providers.bzl", providersBzl))
31
32		for bzlFileName, ruleShim := range ruleShims {
33			files = append(files, newFile(bazelRulesSubDir, bzlFileName+".bzl", ruleShim.content))
34		}
35		files = append(files, newFile(bazelRulesSubDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims)))
36	}
37
38	files = append(files, createBuildFiles(buildToTargets, mode)...)
39
40	return files
41}
42
43func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
44	files := make([]BazelFile, 0, len(buildToTargets))
45	for _, dir := range android.SortedKeys(buildToTargets) {
46		targets := buildToTargets[dir]
47		targets.sort()
48
49		var content string
50		if mode == QueryView {
51			content = soongModuleLoad
52		}
53		if content != "" {
54			// If there are load statements, add a couple of newlines.
55			content += "\n\n"
56		}
57		content += targets.String()
58		files = append(files, newFile(dir, GeneratedBuildFileName, content))
59	}
60	return files
61}
62
63func newFile(dir, basename, content string) BazelFile {
64	return BazelFile{
65		Dir:      dir,
66		Basename: basename,
67		Contents: content,
68	}
69}
70
71const (
72	bazelRulesSubDir = "build/bazel/queryview_rules"
73)
74
75var (
76	// Certain module property names are blocklisted/ignored here, for the reasons commented.
77	ignoredPropNames = map[string]bool{
78		"name":               true, // redundant, since this is explicitly generated for every target
79		"from":               true, // reserved keyword
80		"in":                 true, // reserved keyword
81		"size":               true, // reserved for tests
82		"arch":               true, // interface prop type is not supported yet.
83		"multilib":           true, // interface prop type is not supported yet.
84		"target":             true, // interface prop type is not supported yet.
85		"visibility":         true, // Bazel has native visibility semantics. Handle later.
86		"features":           true, // There is already a built-in attribute 'features' which cannot be overridden.
87		"for":                true, // reserved keyword, b/233579439
88		"versions_with_info": true, // TODO(b/245730552) struct properties not fully supported
89	}
90)
91
92func shouldGenerateAttribute(prop string) bool {
93	return !ignoredPropNames[prop]
94}
95
96func shouldSkipStructField(field reflect.StructField) bool {
97	if field.PkgPath != "" && !field.Anonymous {
98		// Skip unexported fields. Some properties are
99		// internal to Soong only, and these fields do not have PkgPath.
100		return true
101	}
102	// fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc.
103	// but cannot be set in a .bp file
104	if proptools.HasTag(field, "blueprint", "mutated") {
105		return true
106	}
107	return false
108}
109
110// FIXME(b/168089390): In Bazel, rules ending with "_test" needs to be marked as
111// testonly = True, forcing other rules that depend on _test rules to also be
112// marked as testonly = True. This semantic constraint is not present in Soong.
113// To work around, rename "*_test" rules to "*_test_".
114func canonicalizeModuleType(moduleName string) string {
115	if strings.HasSuffix(moduleName, "_test") {
116		return moduleName + "_"
117	}
118
119	return moduleName
120}
121