blob: cccc47400ecf5938c7f5436cdb911b29aa6572c6 [file] [log] [blame]
Liz Kammer2dd9ca42020-11-25 16:06:39 -08001package bp2build
2
3import (
4 "android/soong/android"
5 "reflect"
6 "sort"
7 "strings"
8
9 "github.com/google/blueprint/proptools"
10)
11
12type BazelFile struct {
13 Dir string
14 Basename string
15 Contents string
16}
17
18func CreateBazelFiles(
19 ruleShims map[string]RuleShim,
Jingwen Chen73850672020-12-14 08:25:34 -050020 buildToTargets map[string][]BazelTarget,
21 bp2buildEnabled bool) []BazelFile {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080022 files := make([]BazelFile, 0, len(ruleShims)+len(buildToTargets)+numAdditionalFiles)
23
24 // Write top level files: WORKSPACE and BUILD. These files are empty.
25 files = append(files, newFile("", "WORKSPACE", ""))
26 // Used to denote that the top level directory is a package.
27 files = append(files, newFile("", "BUILD", ""))
28
29 files = append(files, newFile(bazelRulesSubDir, "BUILD", ""))
Liz Kammer2dd9ca42020-11-25 16:06:39 -080030
Jingwen Chen73850672020-12-14 08:25:34 -050031 if !bp2buildEnabled {
32 // These files are only used for queryview.
33 files = append(files, newFile(bazelRulesSubDir, "providers.bzl", providersBzl))
34
35 for bzlFileName, ruleShim := range ruleShims {
36 files = append(files, newFile(bazelRulesSubDir, bzlFileName+".bzl", ruleShim.content))
37 }
38 files = append(files, newFile(bazelRulesSubDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims)))
Liz Kammer2dd9ca42020-11-25 16:06:39 -080039 }
Liz Kammer2dd9ca42020-11-25 16:06:39 -080040
Jingwen Chen73850672020-12-14 08:25:34 -050041 files = append(files, createBuildFiles(buildToTargets, bp2buildEnabled)...)
Liz Kammer2dd9ca42020-11-25 16:06:39 -080042
43 return files
44}
45
Jingwen Chen73850672020-12-14 08:25:34 -050046func createBuildFiles(buildToTargets map[string][]BazelTarget, bp2buildEnabled bool) []BazelFile {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080047 files := make([]BazelFile, 0, len(buildToTargets))
48 for _, dir := range android.SortedStringKeys(buildToTargets) {
49 content := soongModuleLoad
Jingwen Chen73850672020-12-14 08:25:34 -050050 if bp2buildEnabled {
51 // No need to load soong_module for bp2build BUILD files.
52 content = ""
53 }
Liz Kammer2dd9ca42020-11-25 16:06:39 -080054 targets := buildToTargets[dir]
55 sort.Slice(targets, func(i, j int) bool { return targets[i].name < targets[j].name })
56 for _, t := range targets {
57 content += "\n\n"
58 content += t.content
59 }
60 files = append(files, newFile(dir, "BUILD.bazel", content))
61 }
62 return files
63}
64
65func newFile(dir, basename, content string) BazelFile {
66 return BazelFile{
67 Dir: dir,
68 Basename: basename,
69 Contents: content,
70 }
71}
72
73const (
74 bazelRulesSubDir = "build/bazel/queryview_rules"
75
76 // additional files:
77 // * workspace file
78 // * base BUILD file
79 // * rules BUILD file
80 // * rules providers.bzl file
81 // * rules soong_module.bzl file
82 numAdditionalFiles = 5
83)
84
85var (
86 // Certain module property names are blocklisted/ignored here, for the reasons commented.
87 ignoredPropNames = map[string]bool{
88 "name": true, // redundant, since this is explicitly generated for every target
89 "from": true, // reserved keyword
90 "in": true, // reserved keyword
91 "arch": true, // interface prop type is not supported yet.
92 "multilib": true, // interface prop type is not supported yet.
93 "target": true, // interface prop type is not supported yet.
94 "visibility": true, // Bazel has native visibility semantics. Handle later.
95 "features": true, // There is already a built-in attribute 'features' which cannot be overridden.
96 }
97)
98
99func shouldGenerateAttribute(prop string) bool {
100 return !ignoredPropNames[prop]
101}
102
103func shouldSkipStructField(field reflect.StructField) bool {
104 if field.PkgPath != "" {
105 // Skip unexported fields. Some properties are
106 // internal to Soong only, and these fields do not have PkgPath.
107 return true
108 }
109 // fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc
110 // but cannot be set in a .bp file
111 if proptools.HasTag(field, "blueprint", "mutated") {
112 return true
113 }
114 return false
115}
116
117// FIXME(b/168089390): In Bazel, rules ending with "_test" needs to be marked as
118// testonly = True, forcing other rules that depend on _test rules to also be
119// marked as testonly = True. This semantic constraint is not present in Soong.
120// To work around, rename "*_test" rules to "*_test_".
121func canonicalizeModuleType(moduleName string) string {
122 if strings.HasSuffix(moduleName, "_test") {
123 return moduleName + "_"
124 }
125
126 return moduleName
127}