From ee599d6694cf14bf582559b141d0ecf5b6a07105 Mon Sep 17 00:00:00 2001 From: Kiyoung Kim Date: Fri, 22 Mar 2024 18:00:40 +0900 Subject: [PATCH] Update linker.config.pb based on package dependency Current linker.config.pb from the package is generated with auto-detected provide libs, but this misses require libs which can be detected from module dependency. This change adds extra require libs to linker.config.pb generated from system image so it can link with modules outside of system image. Bug: 324995772 Test: Link succeeded from Cuttlefish with soong defined system image Change-Id: I8563ec9ddce2a1648cc9ee55704c9483e137b710 --- filesystem/system_image.go | 27 +++++++++++++++++++--- linkerconfig/linkerconfig.go | 45 ++++++++++++++++++++++++++++-------- 2 files changed, 60 insertions(+), 12 deletions(-) diff --git a/filesystem/system_image.go b/filesystem/system_image.go index 78ce3770c..5028a493e 100644 --- a/filesystem/system_image.go +++ b/filesystem/system_image.go @@ -56,19 +56,40 @@ func (s *systemImage) buildLinkerConfigFile(ctx android.ModuleContext, root andr output := root.Join(ctx, "system", "etc", "linker.config.pb") // we need "Module"s for packaging items - var otherModules []android.Module + modulesInPackageByModule := make(map[android.Module]bool) + modulesInPackageByName := make(map[string]bool) + deps := s.gatherFilteredPackagingSpecs(ctx) ctx.WalkDeps(func(child, parent android.Module) bool { for _, ps := range child.PackagingSpecs() { if _, ok := deps[ps.RelPathInPackage()]; ok { - otherModules = append(otherModules, child) + modulesInPackageByModule[child] = true + modulesInPackageByName[child.Name()] = true + return true } } return true }) + provideModules := make([]android.Module, 0, len(modulesInPackageByModule)) + for mod := range modulesInPackageByModule { + provideModules = append(provideModules, mod) + } + + var requireModules []android.Module + ctx.WalkDeps(func(child, parent android.Module) bool { + _, parentInPackage := modulesInPackageByModule[parent] + _, childInPackageName := modulesInPackageByName[child.Name()] + + // When parent is in the package, and child (or its variant) is not, this can be from an interface. + if parentInPackage && !childInPackageName { + requireModules = append(requireModules, child) + } + return true + }) + builder := android.NewRuleBuilder(pctx, ctx) - linkerconfig.BuildLinkerConfig(ctx, builder, input, otherModules, output) + linkerconfig.BuildLinkerConfig(ctx, builder, input, provideModules, requireModules, output) builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String()) return output } diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go index 78b62d9b8..98aa40805 100644 --- a/linkerconfig/linkerconfig.go +++ b/linkerconfig/linkerconfig.go @@ -89,7 +89,7 @@ func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath builder := android.NewRuleBuilder(pctx, ctx) - BuildLinkerConfig(ctx, builder, input, nil, output) + BuildLinkerConfig(ctx, builder, input, nil, nil, output) builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String()) l.outputFilePath = output @@ -101,7 +101,7 @@ func (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { } func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, - input android.Path, otherModules []android.Module, output android.OutputPath) { + input android.Path, provideModules []android.Module, requireModules []android.Module, output android.OutputPath) { // First, convert the input json to protobuf format interimOutput := android.PathForModuleOut(ctx, "temp.pb") @@ -111,9 +111,9 @@ func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, FlagWithInput("-s ", input). FlagWithOutput("-o ", interimOutput) - // Secondly, if there's provideLibs gathered from otherModules, append them + // Secondly, if there's provideLibs gathered from provideModules, append them var provideLibs []string - for _, m := range otherModules { + for _, m := range provideModules { if c, ok := m.(*cc.Module); ok && cc.IsStubTarget(c) { for _, ps := range c.PackagingSpecs() { provideLibs = append(provideLibs, ps.FileName()) @@ -122,18 +122,45 @@ func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, } provideLibs = android.FirstUniqueStrings(provideLibs) sort.Strings(provideLibs) + + var requireLibs []string + for _, m := range requireModules { + if c, ok := m.(*cc.Module); ok && c.HasStubsVariants() && !c.Host() { + requireLibs = append(requireLibs, c.ImplementationModuleName(ctx)+".so") + } + } + + requireLibs = android.FirstUniqueStrings(requireLibs) + sort.Strings(requireLibs) + if len(provideLibs) > 0 { + prevOutput := interimOutput + interimOutput = android.PathForModuleOut(ctx, "temp_provideLibs.pb") builder.Command(). BuiltTool("conv_linker_config"). Flag("append"). - FlagWithInput("-s ", interimOutput). - FlagWithOutput("-o ", output). + FlagWithInput("-s ", prevOutput). + FlagWithOutput("-o ", interimOutput). FlagWithArg("--key ", "provideLibs"). FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(provideLibs, " "))) - } else { - // If nothing to add, just cp to the final output - builder.Command().Text("cp").Input(interimOutput).Output(output) + builder.Temporary(prevOutput) } + if len(requireLibs) > 0 { + prevOutput := interimOutput + interimOutput = android.PathForModuleOut(ctx, "temp_requireLibs.pb") + builder.Command(). + BuiltTool("conv_linker_config"). + Flag("append"). + FlagWithInput("-s ", prevOutput). + FlagWithOutput("-o ", interimOutput). + FlagWithArg("--key ", "requireLibs"). + FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(requireLibs, " "))) + builder.Temporary(prevOutput) + } + + // cp to the final output + builder.Command().Text("cp").Input(interimOutput).Output(output) + builder.Temporary(interimOutput) builder.DeleteTemporaryFiles() }