| 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 | } |