1*333d2b36SAndroid Build Coastguard Worker// Copyright (C) 2020 The Android Open Source Project 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage linkerconfig 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "sort" 19*333d2b36SAndroid Build Coastguard Worker "strings" 20*333d2b36SAndroid Build Coastguard Worker 21*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint/proptools" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "android/soong/android" 24*333d2b36SAndroid Build Coastguard Worker "android/soong/cc" 25*333d2b36SAndroid Build Coastguard Worker "android/soong/etc" 26*333d2b36SAndroid Build Coastguard Worker) 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Workervar ( 29*333d2b36SAndroid Build Coastguard Worker pctx = android.NewPackageContext("android/soong/linkerconfig") 30*333d2b36SAndroid Build Coastguard Worker) 31*333d2b36SAndroid Build Coastguard Worker 32*333d2b36SAndroid Build Coastguard Workerfunc init() { 33*333d2b36SAndroid Build Coastguard Worker pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config") 34*333d2b36SAndroid Build Coastguard Worker registerLinkerConfigBuildComponent(android.InitRegistrationContext) 35*333d2b36SAndroid Build Coastguard Worker} 36*333d2b36SAndroid Build Coastguard Worker 37*333d2b36SAndroid Build Coastguard Workerfunc registerLinkerConfigBuildComponent(ctx android.RegistrationContext) { 38*333d2b36SAndroid Build Coastguard Worker ctx.RegisterModuleType("linker_config", LinkerConfigFactory) 39*333d2b36SAndroid Build Coastguard Worker} 40*333d2b36SAndroid Build Coastguard Worker 41*333d2b36SAndroid Build Coastguard Workertype linkerConfigProperties struct { 42*333d2b36SAndroid Build Coastguard Worker // source linker configuration property file 43*333d2b36SAndroid Build Coastguard Worker Src *string `android:"path"` 44*333d2b36SAndroid Build Coastguard Worker 45*333d2b36SAndroid Build Coastguard Worker // If set to true, allow module to be installed to one of the partitions. 46*333d2b36SAndroid Build Coastguard Worker // Default value is true. 47*333d2b36SAndroid Build Coastguard Worker // Installable should be marked as false for APEX configuration to avoid 48*333d2b36SAndroid Build Coastguard Worker // conflicts of configuration on /system/etc directory. 49*333d2b36SAndroid Build Coastguard Worker Installable *bool 50*333d2b36SAndroid Build Coastguard Worker} 51*333d2b36SAndroid Build Coastguard Worker 52*333d2b36SAndroid Build Coastguard Workertype linkerConfig struct { 53*333d2b36SAndroid Build Coastguard Worker android.ModuleBase 54*333d2b36SAndroid Build Coastguard Worker properties linkerConfigProperties 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Worker outputFilePath android.OutputPath 57*333d2b36SAndroid Build Coastguard Worker installDirPath android.InstallPath 58*333d2b36SAndroid Build Coastguard Worker} 59*333d2b36SAndroid Build Coastguard Worker 60*333d2b36SAndroid Build Coastguard Worker// Implement PrebuiltEtcModule interface to fit in APEX prebuilt list. 61*333d2b36SAndroid Build Coastguard Workervar _ etc.PrebuiltEtcModule = (*linkerConfig)(nil) 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Workerfunc (l *linkerConfig) BaseDir() string { 64*333d2b36SAndroid Build Coastguard Worker return "etc" 65*333d2b36SAndroid Build Coastguard Worker} 66*333d2b36SAndroid Build Coastguard Worker 67*333d2b36SAndroid Build Coastguard Workerfunc (l *linkerConfig) SubDir() string { 68*333d2b36SAndroid Build Coastguard Worker return "" 69*333d2b36SAndroid Build Coastguard Worker} 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Workerfunc (l *linkerConfig) OutputFile() android.OutputPath { 72*333d2b36SAndroid Build Coastguard Worker return l.outputFilePath 73*333d2b36SAndroid Build Coastguard Worker} 74*333d2b36SAndroid Build Coastguard Worker 75*333d2b36SAndroid Build Coastguard Workerfunc (l *linkerConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { 76*333d2b36SAndroid Build Coastguard Worker input := android.PathForModuleSrc(ctx, android.String(l.properties.Src)) 77*333d2b36SAndroid Build Coastguard Worker output := android.PathForModuleOut(ctx, "linker.config.pb").OutputPath 78*333d2b36SAndroid Build Coastguard Worker 79*333d2b36SAndroid Build Coastguard Worker builder := android.NewRuleBuilder(pctx, ctx) 80*333d2b36SAndroid Build Coastguard Worker BuildLinkerConfig(ctx, builder, android.Paths{input}, nil, nil, output) 81*333d2b36SAndroid Build Coastguard Worker builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String()) 82*333d2b36SAndroid Build Coastguard Worker 83*333d2b36SAndroid Build Coastguard Worker l.outputFilePath = output 84*333d2b36SAndroid Build Coastguard Worker l.installDirPath = android.PathForModuleInstall(ctx, "etc") 85*333d2b36SAndroid Build Coastguard Worker if !proptools.BoolDefault(l.properties.Installable, true) { 86*333d2b36SAndroid Build Coastguard Worker l.SkipInstall() 87*333d2b36SAndroid Build Coastguard Worker } 88*333d2b36SAndroid Build Coastguard Worker ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath) 89*333d2b36SAndroid Build Coastguard Worker 90*333d2b36SAndroid Build Coastguard Worker ctx.SetOutputFiles(android.Paths{l.outputFilePath}, "") 91*333d2b36SAndroid Build Coastguard Worker} 92*333d2b36SAndroid Build Coastguard Worker 93*333d2b36SAndroid Build Coastguard Workerfunc BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder, 94*333d2b36SAndroid Build Coastguard Worker inputs android.Paths, provideModules []android.Module, requireModules []android.Module, output android.OutputPath) { 95*333d2b36SAndroid Build Coastguard Worker 96*333d2b36SAndroid Build Coastguard Worker // First, convert the input json to protobuf format 97*333d2b36SAndroid Build Coastguard Worker interimOutput := android.PathForModuleOut(ctx, "temp.pb") 98*333d2b36SAndroid Build Coastguard Worker cmd := builder.Command(). 99*333d2b36SAndroid Build Coastguard Worker BuiltTool("conv_linker_config"). 100*333d2b36SAndroid Build Coastguard Worker Flag("proto"). 101*333d2b36SAndroid Build Coastguard Worker Flag("--force") 102*333d2b36SAndroid Build Coastguard Worker for _, input := range inputs { 103*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithInput("-s ", input) 104*333d2b36SAndroid Build Coastguard Worker } 105*333d2b36SAndroid Build Coastguard Worker cmd.FlagWithOutput("-o ", interimOutput) 106*333d2b36SAndroid Build Coastguard Worker 107*333d2b36SAndroid Build Coastguard Worker // Secondly, if there's provideLibs gathered from provideModules, append them 108*333d2b36SAndroid Build Coastguard Worker var provideLibs []string 109*333d2b36SAndroid Build Coastguard Worker for _, m := range provideModules { 110*333d2b36SAndroid Build Coastguard Worker if c, ok := m.(*cc.Module); ok && (cc.IsStubTarget(c) || c.HasLlndkStubs()) { 111*333d2b36SAndroid Build Coastguard Worker for _, ps := range android.OtherModuleProviderOrDefault( 112*333d2b36SAndroid Build Coastguard Worker ctx, c, android.InstallFilesProvider).PackagingSpecs { 113*333d2b36SAndroid Build Coastguard Worker provideLibs = append(provideLibs, ps.FileName()) 114*333d2b36SAndroid Build Coastguard Worker } 115*333d2b36SAndroid Build Coastguard Worker } 116*333d2b36SAndroid Build Coastguard Worker } 117*333d2b36SAndroid Build Coastguard Worker provideLibs = android.FirstUniqueStrings(provideLibs) 118*333d2b36SAndroid Build Coastguard Worker sort.Strings(provideLibs) 119*333d2b36SAndroid Build Coastguard Worker 120*333d2b36SAndroid Build Coastguard Worker var requireLibs []string 121*333d2b36SAndroid Build Coastguard Worker for _, m := range requireModules { 122*333d2b36SAndroid Build Coastguard Worker if c, ok := m.(*cc.Module); ok && c.HasStubsVariants() && !c.Host() { 123*333d2b36SAndroid Build Coastguard Worker requireLibs = append(requireLibs, c.ImplementationModuleName(ctx)+".so") 124*333d2b36SAndroid Build Coastguard Worker } 125*333d2b36SAndroid Build Coastguard Worker } 126*333d2b36SAndroid Build Coastguard Worker 127*333d2b36SAndroid Build Coastguard Worker requireLibs = android.FirstUniqueStrings(requireLibs) 128*333d2b36SAndroid Build Coastguard Worker sort.Strings(requireLibs) 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Worker if len(provideLibs) > 0 { 131*333d2b36SAndroid Build Coastguard Worker prevOutput := interimOutput 132*333d2b36SAndroid Build Coastguard Worker interimOutput = android.PathForModuleOut(ctx, "temp_provideLibs.pb") 133*333d2b36SAndroid Build Coastguard Worker builder.Command(). 134*333d2b36SAndroid Build Coastguard Worker BuiltTool("conv_linker_config"). 135*333d2b36SAndroid Build Coastguard Worker Flag("append"). 136*333d2b36SAndroid Build Coastguard Worker FlagWithInput("-s ", prevOutput). 137*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("-o ", interimOutput). 138*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--key ", "provideLibs"). 139*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(provideLibs, " "))) 140*333d2b36SAndroid Build Coastguard Worker builder.Temporary(prevOutput) 141*333d2b36SAndroid Build Coastguard Worker } 142*333d2b36SAndroid Build Coastguard Worker if len(requireLibs) > 0 { 143*333d2b36SAndroid Build Coastguard Worker prevOutput := interimOutput 144*333d2b36SAndroid Build Coastguard Worker interimOutput = android.PathForModuleOut(ctx, "temp_requireLibs.pb") 145*333d2b36SAndroid Build Coastguard Worker builder.Command(). 146*333d2b36SAndroid Build Coastguard Worker BuiltTool("conv_linker_config"). 147*333d2b36SAndroid Build Coastguard Worker Flag("append"). 148*333d2b36SAndroid Build Coastguard Worker FlagWithInput("-s ", prevOutput). 149*333d2b36SAndroid Build Coastguard Worker FlagWithOutput("-o ", interimOutput). 150*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--key ", "requireLibs"). 151*333d2b36SAndroid Build Coastguard Worker FlagWithArg("--value ", proptools.ShellEscapeIncludingSpaces(strings.Join(requireLibs, " "))) 152*333d2b36SAndroid Build Coastguard Worker builder.Temporary(prevOutput) 153*333d2b36SAndroid Build Coastguard Worker } 154*333d2b36SAndroid Build Coastguard Worker 155*333d2b36SAndroid Build Coastguard Worker // cp to the final output 156*333d2b36SAndroid Build Coastguard Worker builder.Command().Text("cp").Input(interimOutput).Output(output) 157*333d2b36SAndroid Build Coastguard Worker 158*333d2b36SAndroid Build Coastguard Worker builder.Temporary(interimOutput) 159*333d2b36SAndroid Build Coastguard Worker builder.DeleteTemporaryFiles() 160*333d2b36SAndroid Build Coastguard Worker} 161*333d2b36SAndroid Build Coastguard Worker 162*333d2b36SAndroid Build Coastguard Worker// linker_config generates protobuf file from json file. This protobuf file will be used from 163*333d2b36SAndroid Build Coastguard Worker// linkerconfig while generating ld.config.txt. Format of this file can be found from 164*333d2b36SAndroid Build Coastguard Worker// https://android.googlesource.com/platform/system/linkerconfig/+/main/README.md 165*333d2b36SAndroid Build Coastguard Workerfunc LinkerConfigFactory() android.Module { 166*333d2b36SAndroid Build Coastguard Worker m := &linkerConfig{} 167*333d2b36SAndroid Build Coastguard Worker m.AddProperties(&m.properties) 168*333d2b36SAndroid Build Coastguard Worker android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibFirst) 169*333d2b36SAndroid Build Coastguard Worker return m 170*333d2b36SAndroid Build Coastguard Worker} 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Workerfunc (l *linkerConfig) AndroidMkEntries() []android.AndroidMkEntries { 173*333d2b36SAndroid Build Coastguard Worker installable := proptools.BoolDefault(l.properties.Installable, true) 174*333d2b36SAndroid Build Coastguard Worker return []android.AndroidMkEntries{android.AndroidMkEntries{ 175*333d2b36SAndroid Build Coastguard Worker Class: "ETC", 176*333d2b36SAndroid Build Coastguard Worker OutputFile: android.OptionalPathForPath(l.outputFilePath), 177*333d2b36SAndroid Build Coastguard Worker ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 178*333d2b36SAndroid Build Coastguard Worker func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 179*333d2b36SAndroid Build Coastguard Worker entries.SetString("LOCAL_MODULE_PATH", l.installDirPath.String()) 180*333d2b36SAndroid Build Coastguard Worker entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.outputFilePath.Base()) 181*333d2b36SAndroid Build Coastguard Worker entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !installable) 182*333d2b36SAndroid Build Coastguard Worker }, 183*333d2b36SAndroid Build Coastguard Worker }, 184*333d2b36SAndroid Build Coastguard Worker }} 185*333d2b36SAndroid Build Coastguard Worker} 186