| // Copyright (C) 2021 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package kernel |
| |
| import ( |
| "fmt" |
| "path/filepath" |
| "strings" |
| |
| "android/soong/android" |
| _ "android/soong/cc/config" |
| |
| "github.com/google/blueprint" |
| "github.com/google/blueprint/proptools" |
| ) |
| |
| func init() { |
| pctx.Import("android/soong/cc/config") |
| registerKernelBuildComponents(android.InitRegistrationContext) |
| } |
| |
| func registerKernelBuildComponents(ctx android.RegistrationContext) { |
| ctx.RegisterModuleType("prebuilt_kernel_modules", prebuiltKernelModulesFactory) |
| } |
| |
| type prebuiltKernelModules struct { |
| android.ModuleBase |
| |
| properties prebuiltKernelModulesProperties |
| |
| installDir android.InstallPath |
| } |
| |
| type prebuiltKernelModulesProperties struct { |
| // List or filegroup of prebuilt kernel module files. Should have .ko suffix. |
| Srcs []string `android:"path,arch_variant"` |
| |
| // Kernel version that these modules are for. Kernel modules are installed to |
| // /lib/modules/<kernel_version> directory in the corresponding partition. Default is "". |
| Kernel_version *string |
| |
| // Whether this module is directly installable to one of the partitions. Default is true |
| Installable *bool |
| } |
| |
| // prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory. |
| // In addition, this module builds modules.load, modules.dep, modules.softdep and modules.alias |
| // using depmod and installs them as well. |
| func prebuiltKernelModulesFactory() android.Module { |
| module := &prebuiltKernelModules{} |
| module.AddProperties(&module.properties) |
| android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) |
| return module |
| } |
| |
| func (pkm *prebuiltKernelModules) installable() bool { |
| return proptools.BoolDefault(pkm.properties.Installable, true) |
| } |
| |
| func (pkm *prebuiltKernelModules) KernelVersion() string { |
| return proptools.StringDefault(pkm.properties.Kernel_version, "") |
| } |
| |
| func (pkm *prebuiltKernelModules) DepsMutator(ctx android.BottomUpMutatorContext) { |
| // do nothing |
| } |
| |
| func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) { |
| if !pkm.installable() { |
| pkm.SkipInstall() |
| } |
| modules := android.PathsForModuleSrc(ctx, pkm.properties.Srcs) |
| |
| depmodOut := runDepmod(ctx, modules) |
| strippedModules := stripDebugSymbols(ctx, modules) |
| |
| installDir := android.PathForModuleInstall(ctx, "lib", "modules") |
| if pkm.KernelVersion() != "" { |
| installDir = installDir.Join(ctx, pkm.KernelVersion()) |
| } |
| |
| for _, m := range strippedModules { |
| ctx.InstallFile(installDir, filepath.Base(m.String()), m) |
| } |
| ctx.InstallFile(installDir, "modules.load", depmodOut.modulesLoad) |
| ctx.InstallFile(installDir, "modules.dep", depmodOut.modulesDep) |
| ctx.InstallFile(installDir, "modules.softdep", depmodOut.modulesSoftdep) |
| ctx.InstallFile(installDir, "modules.alias", depmodOut.modulesAlias) |
| } |
| |
| var ( |
| pctx = android.NewPackageContext("android/soong/kernel") |
| |
| stripRule = pctx.AndroidStaticRule("strip", |
| blueprint.RuleParams{ |
| Command: "$stripCmd -o $out --strip-debug $in", |
| CommandDeps: []string{"$stripCmd"}, |
| }, "stripCmd") |
| ) |
| |
| func stripDebugSymbols(ctx android.ModuleContext, modules android.Paths) android.OutputPaths { |
| dir := android.PathForModuleOut(ctx, "stripped").OutputPath |
| var outputs android.OutputPaths |
| |
| for _, m := range modules { |
| stripped := dir.Join(ctx, filepath.Base(m.String())) |
| ctx.Build(pctx, android.BuildParams{ |
| Rule: stripRule, |
| Input: m, |
| Output: stripped, |
| Args: map[string]string{ |
| "stripCmd": "${config.ClangBin}/llvm-strip", |
| }, |
| }) |
| outputs = append(outputs, stripped) |
| } |
| |
| return outputs |
| } |
| |
| type depmodOutputs struct { |
| modulesLoad android.OutputPath |
| modulesDep android.OutputPath |
| modulesSoftdep android.OutputPath |
| modulesAlias android.OutputPath |
| } |
| |
| func runDepmod(ctx android.ModuleContext, modules android.Paths) depmodOutputs { |
| baseDir := android.PathForModuleOut(ctx, "depmod").OutputPath |
| fakeVer := "0.0" // depmod demands this anyway |
| modulesDir := baseDir.Join(ctx, "lib", "modules", fakeVer) |
| |
| builder := android.NewRuleBuilder(pctx, ctx) |
| |
| // Copy the module files to a temporary dir |
| builder.Command().Text("rm").Flag("-rf").Text(modulesDir.String()) |
| builder.Command().Text("mkdir").Flag("-p").Text(modulesDir.String()) |
| for _, m := range modules { |
| builder.Command().Text("cp").Input(m).Text(modulesDir.String()) |
| } |
| |
| // Enumerate modules to load |
| modulesLoad := modulesDir.Join(ctx, "modules.load") |
| var basenames []string |
| for _, m := range modules { |
| basenames = append(basenames, filepath.Base(m.String())) |
| } |
| builder.Command(). |
| Text("echo").Flag("\"" + strings.Join(basenames, " ") + "\""). |
| Text("|").Text("tr").Flag("\" \"").Flag("\"\\n\""). |
| Text(">").Output(modulesLoad) |
| |
| // Run depmod to build modules.dep/softdep/alias files |
| modulesDep := modulesDir.Join(ctx, "modules.dep") |
| modulesSoftdep := modulesDir.Join(ctx, "modules.softdep") |
| modulesAlias := modulesDir.Join(ctx, "modules.alias") |
| builder.Command(). |
| BuiltTool("depmod"). |
| FlagWithArg("-b ", baseDir.String()). |
| Text(fakeVer). |
| ImplicitOutput(modulesDep). |
| ImplicitOutput(modulesSoftdep). |
| ImplicitOutput(modulesAlias) |
| |
| builder.Build("depmod", fmt.Sprintf("depmod %s", ctx.ModuleName())) |
| |
| return depmodOutputs{modulesLoad, modulesDep, modulesSoftdep, modulesAlias} |
| } |