Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 1 | // Copyright (C) 2021 The Android Open Source Project |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | package kernel |
| 16 | |
| 17 | import ( |
| 18 | "fmt" |
| 19 | "path/filepath" |
| 20 | "strings" |
| 21 | |
| 22 | "android/soong/android" |
| 23 | _ "android/soong/cc/config" |
| 24 | |
| 25 | "github.com/google/blueprint" |
| 26 | "github.com/google/blueprint/proptools" |
| 27 | ) |
| 28 | |
| 29 | func init() { |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 30 | pctx.Import("android/soong/cc/config") |
Paul Duffin | e5ac250 | 2021-03-29 01:24:49 +0100 | [diff] [blame] | 31 | registerKernelBuildComponents(android.InitRegistrationContext) |
| 32 | } |
| 33 | |
| 34 | func registerKernelBuildComponents(ctx android.RegistrationContext) { |
| 35 | ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory) |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 36 | } |
| 37 | |
| 38 | type prebuiltKernelModules struct { |
| 39 | android.ModuleBase |
| 40 | |
| 41 | properties prebuiltKernelModulesProperties |
| 42 | |
| 43 | installDir android.InstallPath |
| 44 | } |
| 45 | |
| 46 | type prebuiltKernelModulesProperties struct { |
| 47 | // List or filegroup of prebuilt kernel module files. Should have .ko suffix. |
| 48 | Srcs []string `android:"path,arch_variant"` |
| 49 | |
| 50 | // Kernel version that these modules are for. Kernel modules are installed to |
| 51 | // /lib/modules/<kernel_version> directory in the corresponding partition. Default is "". |
| 52 | Kernel_version *string |
| 53 | } |
| 54 | |
| 55 | // prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory. |
| 56 | // In addition, this module builds modules.load, modules.dep, modules.softdep and modules.alias |
| 57 | // using depmod and installs them as well. |
| 58 | func prebuiltKernelModulesFactory() android.Module { |
| 59 | module := &prebuiltKernelModules{} |
| 60 | module.AddProperties(&module.properties) |
| 61 | android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) |
| 62 | return module |
| 63 | } |
| 64 | |
| 65 | func (pkm *prebuiltKernelModules) KernelVersion() string { |
| 66 | return proptools.StringDefault(pkm.properties.Kernel_version, "") |
| 67 | } |
| 68 | |
| 69 | func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) { |
| 70 | // do nothing |
| 71 | } |
| 72 | |
| 73 | func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
| 74 | modules := android.PathsForModuleSrc(ctx, pkm.properties.Srcs) |
| 75 | |
| 76 | depmodOut := runDepmod(ctx, modules) |
| 77 | strippedModules := stripDebugSymbols(ctx, modules) |
| 78 | |
Jiyong Park | 599992b | 2021-02-04 19:40:56 +0900 | [diff] [blame] | 79 | installDir := android.PathForModuleInstall(ctx, "lib", "modules") |
Jiyong Park | 6446b62 | 2021-02-01 20:08:28 +0900 | [diff] [blame] | 80 | if pkm.KernelVersion() != "" { |
| 81 | installDir = installDir.Join(ctx, pkm.KernelVersion()) |
| 82 | } |
| 83 | |
| 84 | for _, m := range strippedModules { |
| 85 | ctx.InstallFile(installDir, filepath.Base(m.String()), m) |
| 86 | } |
| 87 | ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad) |
| 88 | ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep) |
| 89 | ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep) |
| 90 | ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias) |
| 91 | } |
| 92 | |
| 93 | var ( |
| 94 | pctx = android.NewPackageContext("android/soong/kernel") |
| 95 | |
| 96 | stripRule = pctx.AndroidStaticRule("strip", |
| 97 | blueprint.RuleParams{ |
| 98 | Command: "$stripCmd -o $out --strip-debug $in", |
| 99 | CommandDeps: []string{"$stripCmd"}, |
| 100 | }, "stripCmd") |
| 101 | ) |
| 102 | |
| 103 | func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths { |
| 104 | dir := android.PathForModuleOut(ctx, "stripped").OutputPath |
| 105 | var outputs android.OutputPaths |
| 106 | |
| 107 | for _, m := range modules { |
| 108 | stripped := dir.Join(ctx, filepath.Base(m.String())) |
| 109 | ctx.Build(pctx, android.BuildParams{ |
| 110 | Rule: stripRule, |
| 111 | Input: m, |
| 112 | Output: stripped, |
| 113 | Args: map[string]string{ |
| 114 | "stripCmd": "${config.ClangBin}/llvm-strip", |
| 115 | }, |
| 116 | }) |
| 117 | outputs = append(outputs, stripped) |
| 118 | } |
| 119 | |
| 120 | return outputs |
| 121 | } |
| 122 | |
| 123 | type depmodOutputs struct { |
| 124 | modulesLoad android.OutputPath |
| 125 | modulesDep android.OutputPath |
| 126 | modulesSoftdep android.OutputPath |
| 127 | modulesAlias android.OutputPath |
| 128 | } |
| 129 | |
| 130 | func runDepmod(ctx android.ModuleContext, modules android.Paths) depmodOutputs { |
| 131 | baseDir := android.PathForModuleOut(ctx, "depmod").OutputPath |
| 132 | fakeVer := "0.0" // depmod demands this anyway |
| 133 | modulesDir := baseDir.Join(ctx, "lib", "modules", fakeVer) |
| 134 | |
| 135 | builder := android.NewRuleBuilder(pctx, ctx) |
| 136 | |
| 137 | // Copy the module files to a temporary dir |
| 138 | builder.Command().Text("rm").Flag("-rf").Text(modulesDir.String()) |
| 139 | builder.Command().Text("mkdir").Flag("-p").Text(modulesDir.String()) |
| 140 | for _, m := range modules { |
| 141 | builder.Command().Text("cp").Input(m).Text(modulesDir.String()) |
| 142 | } |
| 143 | |
| 144 | // Enumerate modules to load |
| 145 | modulesLoad := modulesDir.Join(ctx, "modules.load") |
| 146 | var basenames []string |
| 147 | for _, m := range modules { |
| 148 | basenames = append(basenames, filepath.Base(m.String())) |
| 149 | } |
| 150 | builder.Command(). |
| 151 | Text("echo").Flag("\"" + strings.Join(basenames, " ") + "\""). |
| 152 | Text("|").Text("tr").Flag("\" \"").Flag("\"\\n\""). |
| 153 | Text(">").Output(modulesLoad) |
| 154 | |
| 155 | // Run depmod to build modules.dep/softdep/alias files |
| 156 | modulesDep := modulesDir.Join(ctx, "modules.dep") |
| 157 | modulesSoftdep := modulesDir.Join(ctx, "modules.softdep") |
| 158 | modulesAlias := modulesDir.Join(ctx, "modules.alias") |
| 159 | builder.Command(). |
| 160 | BuiltTool("depmod"). |
| 161 | FlagWithArg("-b ", baseDir.String()). |
| 162 | Text(fakeVer). |
| 163 | ImplicitOutput(modulesDep). |
| 164 | ImplicitOutput(modulesSoftdep). |
| 165 | ImplicitOutput(modulesAlias) |
| 166 | |
| 167 | builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName())) |
| 168 | |
| 169 | return depmodOutputs{modulesLoad, modulesDep, modulesSoftdep, modulesAlias} |
| 170 | } |