1// Copyright 2017 Google Inc. All rights reserved. 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 15package cc 16 17import ( 18 "fmt" 19 "strings" 20 21 "android/soong/android" 22 "android/soong/etc" 23) 24 25var ( 26 llndkLibrarySuffix = ".llndk" 27) 28 29// Holds properties to describe a stub shared library based on the provided version file. 30type llndkLibraryProperties struct { 31 // Relative path to the symbol map. 32 // An example file can be seen here: TODO(danalbert): Make an example. 33 Symbol_file *string `android:"path,arch_variant"` 34 35 // Whether to export any headers as -isystem instead of -I. Mainly for use by 36 // bionic/libc. 37 Export_headers_as_system *bool 38 39 // Whether the system library uses symbol versions. 40 Unversioned *bool 41 42 // list of llndk headers to re-export include directories from. 43 Export_llndk_headers []string 44 45 // list of directories relative to the Blueprints file that willbe added to the include path 46 // (using -I) for any module that links against the LLNDK variant of this module, replacing 47 // any that were listed outside the llndk clause. 48 Override_export_include_dirs []string 49 50 // whether this module can be directly depended upon by libs that are installed 51 // to /vendor and /product. 52 // When set to true, this module can only be depended on by VNDK libraries, not 53 // vendor nor product libraries. This effectively hides this module from 54 // non-system modules. Default value is false. 55 Private *bool 56 57 // if true, make this module available to provide headers to other modules that set 58 // llndk.symbol_file. 59 Llndk_headers *bool 60 61 // moved_to_apex marks this module has having been distributed through an apex module. 62 Moved_to_apex *bool 63} 64 65func makeLlndkVars(ctx android.MakeVarsContext) { 66 67} 68 69func init() { 70 RegisterLlndkLibraryTxtType(android.InitRegistrationContext) 71 android.RegisterParallelSingletonType("movedToApexLlndkLibraries", movedToApexLlndkLibrariesFactory) 72} 73 74func movedToApexLlndkLibrariesFactory() android.Singleton { 75 return &movedToApexLlndkLibraries{} 76} 77 78type movedToApexLlndkLibraries struct { 79 movedToApexLlndkLibraries []string 80} 81 82func (s *movedToApexLlndkLibraries) GenerateBuildActions(ctx android.SingletonContext) { 83 // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config. 84 movedToApexLlndkLibrariesMap := make(map[string]bool) 85 ctx.VisitAllModuleProxies(func(module android.ModuleProxy) { 86 if library, ok := android.OtherModuleProvider(ctx, module, LinkableInfoProvider); ok { 87 if library.HasLLNDKStubs && library.IsLLNDKMovedToApex { 88 movedToApexLlndkLibrariesMap[library.ImplementationModuleName] = true 89 } 90 } 91 }) 92 s.movedToApexLlndkLibraries = android.SortedKeys(movedToApexLlndkLibrariesMap) 93 94 var sb strings.Builder 95 for i, l := range s.movedToApexLlndkLibraries { 96 if i > 0 { 97 sb.WriteRune(' ') 98 } 99 sb.WriteString(l) 100 sb.WriteString(".so") 101 } 102 android.WriteFileRule(ctx, MovedToApexLlndkLibrariesFile(ctx), sb.String()) 103} 104 105func MovedToApexLlndkLibrariesFile(ctx android.PathContext) android.WritablePath { 106 return android.PathForIntermediates(ctx, "moved_to_apex_llndk_libraries.txt") 107} 108 109func (s *movedToApexLlndkLibraries) MakeVars(ctx android.MakeVarsContext) { 110 ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", strings.Join(s.movedToApexLlndkLibraries, " ")) 111} 112 113func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) { 114 ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) 115} 116 117type llndkLibrariesTxtModule struct { 118 android.SingletonModuleBase 119 120 outputFile android.OutputPath 121 moduleNames []string 122 fileNames []string 123} 124 125var _ etc.PrebuiltEtcModule = &llndkLibrariesTxtModule{} 126 127// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries 128// generated by Soong but can be referenced by other modules. 129// For example, apex_vndk can depend on these files as prebuilt. 130// Make uses LLNDK_LIBRARIES to determine which libraries to install. 131// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN. 132// Therefore, by removing the library here, we cause it to only be installed if libc 133// depends on it. 134func llndkLibrariesTxtFactory() android.SingletonModule { 135 m := &llndkLibrariesTxtModule{} 136 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 137 return m 138} 139 140func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 141 filename := txt.Name() 142 143 txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath 144 145 installPath := android.PathForModuleInstall(ctx, "etc") 146 ctx.InstallFile(installPath, filename, txt.outputFile) 147 148 ctx.SetOutputFiles(android.Paths{txt.outputFile}, "") 149 150 etc.SetCommonPrebuiltEtcInfo(ctx, txt) 151} 152 153func getVndkFileName(info *LinkerInfo) (string, error) { 154 if info != nil { 155 if info.LibraryDecoratorInfo != nil { 156 return info.LibraryDecoratorInfo.VndkFileName, nil 157 } 158 if info.PrebuiltLibraryLinkerInfo != nil { 159 return info.PrebuiltLibraryLinkerInfo.VndkFileName, nil 160 } 161 } 162 return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", info) 163} 164 165func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { 166 if txt.outputFile.String() == "" { 167 // Skip if target file path is empty 168 return 169 } 170 171 ctx.VisitAllModuleProxies(func(m android.ModuleProxy) { 172 ccInfo, ok := android.OtherModuleProvider(ctx, m, CcInfoProvider) 173 if !ok { 174 return 175 } 176 linkableInfo, ok := android.OtherModuleProvider(ctx, m, LinkableInfoProvider) 177 if !ok { 178 return 179 } 180 if linkableInfo.IsLlndk && !linkableInfo.Header && !linkableInfo.IsVndkPrebuiltLibrary { 181 filename, err := getVndkFileName(ccInfo.LinkerInfo) 182 if err != nil { 183 ctx.ModuleErrorf(m, "%s", err) 184 } 185 186 if !strings.HasPrefix(ctx.ModuleName(m), "libclang_rt.hwasan") { 187 txt.moduleNames = append(txt.moduleNames, ctx.ModuleName(m)) 188 } 189 txt.fileNames = append(txt.fileNames, filename) 190 } 191 }) 192 txt.moduleNames = android.SortedUniqueStrings(txt.moduleNames) 193 txt.fileNames = android.SortedUniqueStrings(txt.fileNames) 194 195 android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n")) 196} 197 198func (txt *llndkLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries { 199 return []android.AndroidMkEntries{{ 200 Class: "ETC", 201 OutputFile: android.OptionalPathForPath(txt.outputFile), 202 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 203 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 204 entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base()) 205 }, 206 }, 207 }} 208} 209 210func (txt *llndkLibrariesTxtModule) MakeVars(ctx android.MakeVarsContext) { 211 ctx.Strict("LLNDK_LIBRARIES", strings.Join(txt.moduleNames, " ")) 212} 213 214// PrebuiltEtcModule interface 215func (txt *llndkLibrariesTxtModule) BaseDir() string { 216 return "etc" 217} 218 219// PrebuiltEtcModule interface 220func (txt *llndkLibrariesTxtModule) SubDir() string { 221 return "" 222} 223 224func llndkMutator(mctx android.BottomUpMutatorContext) { 225 m, ok := mctx.Module().(*Module) 226 if !ok { 227 return 228 } 229 230 if shouldSkipLlndkMutator(mctx, m) { 231 return 232 } 233 234 lib, isLib := m.linker.(*libraryDecorator) 235 prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) 236 237 if m.InVendorOrProduct() && isLib && lib.HasLLNDKStubs() { 238 m.VendorProperties.IsLLNDK = true 239 } 240 if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.HasLLNDKStubs() { 241 m.VendorProperties.IsLLNDK = true 242 } 243 244 if vndkprebuilt, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { 245 if !Bool(vndkprebuilt.properties.Vndk.Enabled) { 246 m.VendorProperties.IsLLNDK = true 247 } 248 } 249} 250 251// Check for modules that mustn't be LLNDK 252func shouldSkipLlndkMutator(mctx android.BottomUpMutatorContext, m *Module) bool { 253 if !m.Enabled(mctx) { 254 return true 255 } 256 if !m.Device() { 257 return true 258 } 259 if m.Target().NativeBridge == android.NativeBridgeEnabled { 260 return true 261 } 262 return false 263} 264