blob: 731b17e3a5fc21ce9d8255b342996f20e9c83228 [file] [log] [blame]
Liz Kammer2dd9ca42020-11-25 16:06:39 -08001package bp2build
2
3import (
Jingwen Chen0ee88a62022-01-07 14:55:29 +00004 "encoding/json"
Liz Kammer2dd9ca42020-11-25 16:06:39 -08005 "reflect"
Liz Kammer2dd9ca42020-11-25 16:06:39 -08006 "strings"
7
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +00008 "android/soong/android"
Sam Delmerico932c01c2022-03-25 16:33:26 +00009 cc_config "android/soong/cc/config"
10 java_config "android/soong/java/config"
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux447f6c92021-08-31 20:30:36 +000011
Jingwen Chen7810e172022-07-29 02:25:34 +000012 "android/soong/apex"
13
Liz Kammer2dd9ca42020-11-25 16:06:39 -080014 "github.com/google/blueprint/proptools"
15)
16
17type BazelFile struct {
18 Dir string
19 Basename string
20 Contents string
21}
22
Chris Parsons3b1f83d2021-10-14 14:08:38 -040023func CreateSoongInjectionFiles(cfg android.Config, metrics CodegenMetrics) []BazelFile {
Jingwen Chenbf61afb2021-05-06 13:31:18 +000024 var files []BazelFile
25
Jingwen Chenc63677b2021-06-17 05:43:19 +000026 files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
Sam Delmerico932c01c2022-03-25 16:33:26 +000027 files = append(files, newFile("cc_toolchain", "constants.bzl", cc_config.BazelCcToolchainVars(cfg)))
28
29 files = append(files, newFile("java_toolchain", GeneratedBuildFileName, "")) // Creates a //java_toolchain package.
30 files = append(files, newFile("java_toolchain", "constants.bzl", java_config.BazelJavaToolchainVars(cfg)))
Jingwen Chenbf61afb2021-05-06 13:31:18 +000031
Jingwen Chen7810e172022-07-29 02:25:34 +000032 files = append(files, newFile("apex_toolchain", GeneratedBuildFileName, "")) // Creates a //apex_toolchain package.
33 files = append(files, newFile("apex_toolchain", "constants.bzl", apex.BazelApexToolchainVars()))
34
Jingwen Chen61174502021-09-17 08:40:45 +000035 files = append(files, newFile("metrics", "converted_modules.txt", strings.Join(metrics.convertedModules, "\n")))
Jingwen Chenc63677b2021-06-17 05:43:19 +000036
Jingwen Chen01812022021-11-19 14:29:43 +000037 files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
38
Liz Kammere8303bd2022-02-16 09:02:48 -050039 files = append(files, newFile("product_config", "arch_configuration.bzl", android.StarlarkArchConfigurations()))
40
Jingwen Chen0ee88a62022-01-07 14:55:29 +000041 apiLevelsContent, err := json.Marshal(android.GetApiLevelsMap(cfg))
42 if err != nil {
43 panic(err)
44 }
45 files = append(files, newFile("api_levels", GeneratedBuildFileName, `exports_files(["api_levels.json"])`))
46 files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
Yu Liufc603162022-03-01 15:44:08 -080047 files = append(files, newFile("api_levels", "api_levels.bzl", android.StarlarkApiLevelConfigs(cfg)))
Jingwen Chen0ee88a62022-01-07 14:55:29 +000048
Jingwen Chenbf61afb2021-05-06 13:31:18 +000049 return files
50}
51
Jingwen Chen61174502021-09-17 08:40:45 +000052func convertedModules(convertedModules []string) string {
53 return strings.Join(convertedModules, "\n")
Jingwen Chenc63677b2021-06-17 05:43:19 +000054}
55
Liz Kammer2dd9ca42020-11-25 16:06:39 -080056func CreateBazelFiles(
Sasha Smundak0fd93e02022-05-19 19:34:31 -070057 cfg android.Config,
Liz Kammer2dd9ca42020-11-25 16:06:39 -080058 ruleShims map[string]RuleShim,
Jingwen Chen40067de2021-01-26 21:58:43 -050059 buildToTargets map[string]BazelTargets,
Jingwen Chen33832f92021-01-24 22:55:54 -050060 mode CodegenMode) []BazelFile {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080061
Jingwen Chen6c309cd2021-04-01 07:11:11 +000062 var files []BazelFile
Liz Kammer2dd9ca42020-11-25 16:06:39 -080063
Jingwen Chen33832f92021-01-24 22:55:54 -050064 if mode == QueryView {
Jingwen Chen6c309cd2021-04-01 07:11:11 +000065 // Write top level WORKSPACE.
66 files = append(files, newFile("", "WORKSPACE", ""))
67
Jingwen Chen12b4c272021-03-10 02:05:59 -050068 // Used to denote that the top level directory is a package.
69 files = append(files, newFile("", GeneratedBuildFileName, ""))
70
71 files = append(files, newFile(bazelRulesSubDir, GeneratedBuildFileName, ""))
72
Jingwen Chen73850672020-12-14 08:25:34 -050073 // These files are only used for queryview.
74 files = append(files, newFile(bazelRulesSubDir, "providers.bzl", providersBzl))
75
76 for bzlFileName, ruleShim := range ruleShims {
77 files = append(files, newFile(bazelRulesSubDir, bzlFileName+".bzl", ruleShim.content))
78 }
79 files = append(files, newFile(bazelRulesSubDir, "soong_module.bzl", generateSoongModuleBzl(ruleShims)))
Liz Kammer2dd9ca42020-11-25 16:06:39 -080080 }
Liz Kammer2dd9ca42020-11-25 16:06:39 -080081
Cole Faust324a92e2022-08-23 15:29:05 -070082 files = append(files, createBuildFiles(buildToTargets, mode)...)
Liz Kammer2dd9ca42020-11-25 16:06:39 -080083
84 return files
85}
86
Cole Faust324a92e2022-08-23 15:29:05 -070087func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080088 files := make([]BazelFile, 0, len(buildToTargets))
89 for _, dir := range android.SortedStringKeys(buildToTargets) {
Liz Kammer2dd9ca42020-11-25 16:06:39 -080090 targets := buildToTargets[dir]
Jingwen Chen49109762021-05-25 05:16:48 +000091 targets.sort()
92
93 var content string
Jingwen Chen40067de2021-01-26 21:58:43 -050094 if mode == Bp2Build {
Jingwen Chen49109762021-05-25 05:16:48 +000095 content = `# READ THIS FIRST:
96# This file was automatically generated by bp2build for the Bazel migration project.
97# Feel free to edit or test it, but do *not* check it into your version control system.
98`
Cole Faustea602c52022-08-31 14:48:26 -070099
100 // Hardcode the default visibility.
101 content += "package(default_visibility = [\"//visibility:public\"])\n"
Jingwen Chen1c231732021-02-05 09:38:15 -0500102 content += targets.LoadStatements()
Jingwen Chen49109762021-05-25 05:16:48 +0000103 } else if mode == QueryView {
104 content = soongModuleLoad
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800105 }
Jingwen Chen40067de2021-01-26 21:58:43 -0500106 if content != "" {
107 // If there are load statements, add a couple of newlines.
108 content += "\n\n"
109 }
110 content += targets.String()
Liz Kammerba3ea162021-02-17 13:22:03 -0500111 files = append(files, newFile(dir, GeneratedBuildFileName, content))
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800112 }
113 return files
114}
115
116func newFile(dir, basename, content string) BazelFile {
117 return BazelFile{
118 Dir: dir,
119 Basename: basename,
120 Contents: content,
121 }
122}
123
124const (
125 bazelRulesSubDir = "build/bazel/queryview_rules"
126
127 // additional files:
128 // * workspace file
129 // * base BUILD file
130 // * rules BUILD file
131 // * rules providers.bzl file
132 // * rules soong_module.bzl file
133 numAdditionalFiles = 5
134)
135
136var (
137 // Certain module property names are blocklisted/ignored here, for the reasons commented.
138 ignoredPropNames = map[string]bool{
Sam Delmerico263efde2022-09-08 10:43:42 -0400139 "name": true, // redundant, since this is explicitly generated for every target
140 "from": true, // reserved keyword
141 "in": true, // reserved keyword
142 "size": true, // reserved for tests
143 "arch": true, // interface prop type is not supported yet.
144 "multilib": true, // interface prop type is not supported yet.
145 "target": true, // interface prop type is not supported yet.
146 "visibility": true, // Bazel has native visibility semantics. Handle later.
147 "features": true, // There is already a built-in attribute 'features' which cannot be overridden.
148 "for": true, // reserved keyword, b/233579439
149 "versions_with_info": true, // TODO(b/245730552) struct properties not fully supported
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800150 }
151)
152
153func shouldGenerateAttribute(prop string) bool {
154 return !ignoredPropNames[prop]
155}
156
157func shouldSkipStructField(field reflect.StructField) bool {
Liz Kammer7a210ac2021-09-22 15:52:58 -0400158 if field.PkgPath != "" && !field.Anonymous {
Liz Kammer2dd9ca42020-11-25 16:06:39 -0800159 // Skip unexported fields. Some properties are
160 // internal to Soong only, and these fields do not have PkgPath.
161 return true
162 }
163 // fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc
164 // but cannot be set in a .bp file
165 if proptools.HasTag(field, "blueprint", "mutated") {
166 return true
167 }
168 return false
169}
170
171// FIXME(b/168089390): In Bazel, rules ending with "_test" needs to be marked as
172// testonly = True, forcing other rules that depend on _test rules to also be
173// marked as testonly = True. This semantic constraint is not present in Soong.
174// To work around, rename "*_test" rules to "*_test_".
175func canonicalizeModuleType(moduleName string) string {
176 if strings.HasSuffix(moduleName, "_test") {
177 return moduleName + "_"
178 }
179
180 return moduleName
181}