Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 1 | package bp2build |
| 2 | |
| 3 | import ( |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 4 | "reflect" |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 5 | "strings" |
| 6 | |
Alex Márquez Pérez Muñíz Díaz Púras Thaureaux | 447f6c9 | 2021-08-31 20:30:36 +0000 | [diff] [blame] | 7 | "android/soong/android" |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 8 | "github.com/google/blueprint/proptools" |
| 9 | ) |
| 10 | |
| 11 | type BazelFile struct { |
| 12 | Dir string |
| 13 | Basename string |
| 14 | Contents string |
| 15 | } |
| 16 | |
usta | 40caf95 | 2023-08-04 16:52:14 -0400 | [diff] [blame] | 17 | func CreateBazelFiles(ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { |
Jingwen Chen | 6c309cd | 2021-04-01 07:11:11 +0000 | [diff] [blame] | 18 | var files []BazelFile |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 19 | |
Jingwen Chen | 33832f9 | 2021-01-24 22:55:54 -0500 | [diff] [blame] | 20 | if mode == QueryView { |
Jingwen Chen | 6c309cd | 2021-04-01 07:11:11 +0000 | [diff] [blame] | 21 | // Write top level WORKSPACE. |
| 22 | files = append(files, newFile("", "WORKSPACE", "")) |
| 23 | |
Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 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 | |
Jingwen Chen | 7385067 | 2020-12-14 08:25:34 -0500 | [diff] [blame] | 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))) |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 36 | } |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 37 | |
Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 38 | files = append(files, createBuildFiles(buildToTargets, mode)...) |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 39 | |
| 40 | return files |
| 41 | } |
| 42 | |
Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 43 | func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile { |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 44 | files := make([]BazelFile, 0, len(buildToTargets)) |
Cole Faust | 18994c7 | 2023-02-28 16:02:16 -0800 | [diff] [blame] | 45 | for _, dir := range android.SortedKeys(buildToTargets) { |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 46 | targets := buildToTargets[dir] |
Jingwen Chen | 4910976 | 2021-05-25 05:16:48 +0000 | [diff] [blame] | 47 | targets.sort() |
| 48 | |
| 49 | var content string |
Colin Cross | b63d7b3 | 2023-12-07 16:54:51 -0800 | [diff] [blame] | 50 | if mode == QueryView { |
Jingwen Chen | 4910976 | 2021-05-25 05:16:48 +0000 | [diff] [blame] | 51 | content = soongModuleLoad |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 52 | } |
Jingwen Chen | 40067de | 2021-01-26 21:58:43 -0500 | [diff] [blame] | 53 | if content != "" { |
| 54 | // If there are load statements, add a couple of newlines. |
| 55 | content += "\n\n" |
| 56 | } |
| 57 | content += targets.String() |
Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 58 | files = append(files, newFile(dir, GeneratedBuildFileName, content)) |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 59 | } |
| 60 | return files |
| 61 | } |
| 62 | |
| 63 | func newFile(dir, basename, content string) BazelFile { |
| 64 | return BazelFile{ |
| 65 | Dir: dir, |
| 66 | Basename: basename, |
| 67 | Contents: content, |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | const ( |
| 72 | bazelRulesSubDir = "build/bazel/queryview_rules" |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 73 | ) |
| 74 | |
| 75 | var ( |
| 76 | // Certain module property names are blocklisted/ignored here, for the reasons commented. |
| 77 | ignoredPropNames = map[string]bool{ |
Sam Delmerico | 263efde | 2022-09-08 10:43:42 -0400 | [diff] [blame] | 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 |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 89 | } |
| 90 | ) |
| 91 | |
| 92 | func shouldGenerateAttribute(prop string) bool { |
| 93 | return !ignoredPropNames[prop] |
| 94 | } |
| 95 | |
| 96 | func shouldSkipStructField(field reflect.StructField) bool { |
Liz Kammer | 7a210ac | 2021-09-22 15:52:58 -0400 | [diff] [blame] | 97 | if field.PkgPath != "" && !field.Anonymous { |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 98 | // Skip unexported fields. Some properties are |
| 99 | // internal to Soong only, and these fields do not have PkgPath. |
| 100 | return true |
| 101 | } |
Sasha Smundak | 8bea267 | 2022-08-04 13:31:14 -0700 | [diff] [blame] | 102 | // fields with tag `blueprint:"mutated"` are exported to enable modification in mutators, etc. |
Liz Kammer | 2dd9ca4 | 2020-11-25 16:06:39 -0800 | [diff] [blame] | 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_". |
| 114 | func canonicalizeModuleType(moduleName string) string { |
| 115 | if strings.HasSuffix(moduleName, "_test") { |
| 116 | return moduleName + "_" |
| 117 | } |
| 118 | |
| 119 | return moduleName |
| 120 | } |