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 // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to generate the linker config. 67 movedToApexLlndkLibraries := make(map[string]bool) 68 ctx.VisitAllModules(func(module android.Module) { 69 if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() { 70 if library.isLLNDKMovedToApex() { 71 name := library.implementationModuleName(module.(*Module).BaseModuleName()) 72 movedToApexLlndkLibraries[name] = true 73 } 74 } 75 }) 76 77 ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", 78 strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " ")) 79} 80 81func init() { 82 RegisterLlndkLibraryTxtType(android.InitRegistrationContext) 83} 84 85func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) { 86 ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) 87} 88 89type llndkLibrariesTxtModule struct { 90 android.SingletonModuleBase 91 92 outputFile android.OutputPath 93 moduleNames []string 94 fileNames []string 95} 96 97var _ etc.PrebuiltEtcModule = &llndkLibrariesTxtModule{} 98 99// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries 100// generated by Soong but can be referenced by other modules. 101// For example, apex_vndk can depend on these files as prebuilt. 102// Make uses LLNDK_LIBRARIES to determine which libraries to install. 103// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN. 104// Therefore, by removing the library here, we cause it to only be installed if libc 105// depends on it. 106func llndkLibrariesTxtFactory() android.SingletonModule { 107 m := &llndkLibrariesTxtModule{} 108 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 109 return m 110} 111 112func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 113 filename := txt.Name() 114 115 txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath 116 117 installPath := android.PathForModuleInstall(ctx, "etc") 118 ctx.InstallFile(installPath, filename, txt.outputFile) 119 120 ctx.SetOutputFiles(android.Paths{txt.outputFile}, "") 121} 122 123func getVndkFileName(m *Module) (string, error) { 124 if library, ok := m.linker.(*libraryDecorator); ok { 125 return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil 126 } 127 if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { 128 return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil 129 } 130 return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) 131} 132 133func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { 134 if txt.outputFile.String() == "" { 135 // Skip if target file path is empty 136 return 137 } 138 139 ctx.VisitAllModules(func(m android.Module) { 140 if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() { 141 filename, err := getVndkFileName(c) 142 if err != nil { 143 ctx.ModuleErrorf(m, "%s", err) 144 } 145 146 if !strings.HasPrefix(ctx.ModuleName(m), "libclang_rt.hwasan") { 147 txt.moduleNames = append(txt.moduleNames, ctx.ModuleName(m)) 148 } 149 txt.fileNames = append(txt.fileNames, filename) 150 } 151 }) 152 txt.moduleNames = android.SortedUniqueStrings(txt.moduleNames) 153 txt.fileNames = android.SortedUniqueStrings(txt.fileNames) 154 155 android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n")) 156} 157 158func (txt *llndkLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries { 159 return []android.AndroidMkEntries{{ 160 Class: "ETC", 161 OutputFile: android.OptionalPathForPath(txt.outputFile), 162 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 163 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 164 entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base()) 165 }, 166 }, 167 }} 168} 169 170func (txt *llndkLibrariesTxtModule) MakeVars(ctx android.MakeVarsContext) { 171 ctx.Strict("LLNDK_LIBRARIES", strings.Join(txt.moduleNames, " ")) 172} 173 174// PrebuiltEtcModule interface 175func (txt *llndkLibrariesTxtModule) BaseDir() string { 176 return "etc" 177} 178 179// PrebuiltEtcModule interface 180func (txt *llndkLibrariesTxtModule) SubDir() string { 181 return "" 182} 183 184func llndkMutator(mctx android.BottomUpMutatorContext) { 185 m, ok := mctx.Module().(*Module) 186 if !ok { 187 return 188 } 189 190 if shouldSkipLlndkMutator(mctx, m) { 191 return 192 } 193 194 lib, isLib := m.linker.(*libraryDecorator) 195 prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) 196 197 if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() { 198 m.VendorProperties.IsLLNDK = true 199 } 200 if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() { 201 m.VendorProperties.IsLLNDK = true 202 } 203 204 if vndkprebuilt, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { 205 if !Bool(vndkprebuilt.properties.Vndk.Enabled) { 206 m.VendorProperties.IsLLNDK = true 207 } 208 } 209} 210 211// Check for modules that mustn't be LLNDK 212func shouldSkipLlndkMutator(mctx android.BottomUpMutatorContext, m *Module) bool { 213 if !m.Enabled(mctx) { 214 return true 215 } 216 if !m.Device() { 217 return true 218 } 219 if m.Target().NativeBridge == android.NativeBridgeEnabled { 220 return true 221 } 222 return false 223} 224