blob: 9f1aa09c6bf84e8feab954b5fbd7312a7283d623 [file] [log] [blame]
Liz Kammer2dd9ca42020-11-25 16:06:39 -08001package bp2build
2
3import (
Liz Kammer2dd9ca42020-11-25 16:06:39 -08004 "reflect"
Liz Kammer2dd9ca42020-11-25 16:06:39 -08005 "strings"
6
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +00007 "android/soong/android"
Liz Kammer2dd9ca42020-11-25 16:06:39 -08008 "github.com/google/blueprint/proptools"
9)
10
11type BazelFile struct {
12 Dir string
13 Basename string
14 Contents string
15}
16
usta40caf952023-08-04 16:52:14 -040017func CreateBazelFiles(ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
Jingwen Chen6c309cd2021-04-01 07:11:11 +000018 var files []BazelFile
Liz Kammer2dd9ca42020-11-25 16:06:39 -080019
Jingwen Chen33832f92021-01-24 22:55:54 -050020 if mode == QueryView {
Jingwen Chen6c309cd2021-04-01 07:11:11 +000021 // Write top level WORKSPACE.
22 files = append(files, newFile("", "WORKSPACE", ""))
23
Jingwen Chen12b4c272021-03-10 02:05:59 -050024 // 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
Jingwen Chen73850672020-12-14 08:25:34 -050029 // 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)))
Liz Kammer2dd9ca42020-11-25 16:06:39 -080036 }
Liz Kammer2dd9ca42020-11-25 16:06:39 -080037
Cole Faust324a92e2022-08-23 15:29:05 -070038 files = append(files, createBuildFiles(buildToTargets, mode)...)
Liz Kammer2dd9ca42020-11-25 16:06:39 -080039
40 return files
41}
42
Cole Faust324a92e2022-08-23 15:29:05 -070043func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080044 files := make([]BazelFile, 0, len(buildToTargets))
Cole Faust18994c72023-02-28 16:02:16 -080045 for _, dir := range android.SortedKeys(buildToTargets) {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080046 targets := buildToTargets[dir]
Jingwen Chen49109762021-05-25 05:16:48 +000047 targets.sort()
48
49 var content string
Colin Crossb63d7b32023-12-07 16:54:51 -080050 if mode == QueryView {
Jingwen Chen49109762021-05-25 05:16:48 +000051 content = soongModuleLoad
Liz Kammer2dd9ca42020-11-25 16:06:39 -080052 }
Jingwen Chen40067de2021-01-26 21:58:43 -050053 if content != "" {
54 // If there are load statements, add a couple of newlines.
55 content += "\n\n"
56 }
57 content += targets.String()
Liz Kammerba3ea162021-02-17 13:22:03 -050058 files = append(files, newFile(dir, GeneratedBuildFileName, content))
Liz Kammer2dd9ca42020-11-25 16:06:39 -080059 }
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"
Liz Kammer2dd9ca42020-11-25 16:06:39 -080073)
74
75var (
76 // Certain module property names are blocklisted/ignored here, for the reasons commented.
77 ignoredPropNames = map[string]bool{
Sam Delmerico263efde2022-09-08 10:43:42 -040078 "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
Liz Kammer2dd9ca42020-11-25 16:06:39 -080089 }
90)
91
92func shouldGenerateAttribute(prop string) bool {
93 return !ignoredPropNames[prop]
94}
95
96func shouldSkipStructField(field reflect.StructField) bool {
Liz Kammer7a210ac2021-09-22 15:52:58 -040097 if field.PkgPath != "" && !field.Anonymous {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080098 // Skip unexported fields. Some properties are
99 // internal to Soong only, and these fields do not have PkgPath.
100 return true
101 }
Sasha Smundak8bea2672022-08-04 13:31:14 -0700102 // fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc.
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800103 // 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}