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 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 // Which headers to process with versioner. This really only handles 40 // bionic/libc/include right now. 41 Export_preprocessed_headers []string 42 43 // Whether the system library uses symbol versions. 44 Unversioned *bool 45 46 // list of llndk headers to re-export include directories from. 47 Export_llndk_headers []string 48 49 // list of directories relative to the Blueprints file that willbe added to the include path 50 // (using -I) for any module that links against the LLNDK variant of this module, replacing 51 // any that were listed outside the llndk clause. 52 Override_export_include_dirs []string 53 54 // whether this module can be directly depended upon by libs that are installed 55 // to /vendor and /product. 56 // When set to true, this module can only be depended on by VNDK libraries, not 57 // vendor nor product libraries. This effectively hides this module from 58 // non-system modules. Default value is false. 59 Private *bool 60 61 // if true, make this module available to provide headers to other modules that set 62 // llndk.symbol_file. 63 Llndk_headers *bool 64} 65 66func makeLlndkVars(ctx android.MakeVarsContext) { 67 // Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if 68 // they been moved to an apex. 69 movedToApexLlndkLibraries := make(map[string]bool) 70 ctx.VisitAllModules(func(module android.Module) { 71 if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() { 72 // Skip bionic libs, they are handled in different manner 73 name := library.implementationModuleName(module.(*Module).BaseModuleName()) 74 if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) { 75 movedToApexLlndkLibraries[name] = true 76 } 77 } 78 }) 79 80 ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES", 81 strings.Join(android.SortedKeys(movedToApexLlndkLibraries), " ")) 82} 83 84func init() { 85 RegisterLlndkLibraryTxtType(android.InitRegistrationContext) 86} 87 88func RegisterLlndkLibraryTxtType(ctx android.RegistrationContext) { 89 ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory) 90} 91 92type llndkLibrariesTxtModule struct { 93 android.SingletonModuleBase 94 95 outputFile android.OutputPath 96 moduleNames []string 97 fileNames []string 98} 99 100var _ etc.PrebuiltEtcModule = &llndkLibrariesTxtModule{} 101 102// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries 103// generated by Soong but can be referenced by other modules. 104// For example, apex_vndk can depend on these files as prebuilt. 105// Make uses LLNDK_LIBRARIES to determine which libraries to install. 106// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN. 107// Therefore, by removing the library here, we cause it to only be installed if libc 108// depends on it. 109func llndkLibrariesTxtFactory() android.SingletonModule { 110 m := &llndkLibrariesTxtModule{} 111 android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon) 112 return m 113} 114 115func (txt *llndkLibrariesTxtModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 116 filename := txt.Name() 117 118 txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath 119 120 installPath := android.PathForModuleInstall(ctx, "etc") 121 ctx.InstallFile(installPath, filename, txt.outputFile) 122 123 ctx.SetOutputFiles(android.Paths{txt.outputFile}, "") 124} 125 126func getVndkFileName(m *Module) (string, error) { 127 if library, ok := m.linker.(*libraryDecorator); ok { 128 return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil 129 } 130 if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok { 131 return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil 132 } 133 return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker) 134} 135 136func (txt *llndkLibrariesTxtModule) GenerateSingletonBuildActions(ctx android.SingletonContext) { 137 if txt.outputFile.String() == "" { 138 // Skip if target file path is empty 139 return 140 } 141 142 ctx.VisitAllModules(func(m android.Module) { 143 if c, ok := m.(*Module); ok && c.VendorProperties.IsLLNDK && !c.Header() && !c.IsVndkPrebuiltLibrary() { 144 filename, err := getVndkFileName(c) 145 if err != nil { 146 ctx.ModuleErrorf(m, "%s", err) 147 } 148 149 if !strings.HasPrefix(ctx.ModuleName(m), "libclang_rt.hwasan") { 150 txt.moduleNames = append(txt.moduleNames, ctx.ModuleName(m)) 151 } 152 txt.fileNames = append(txt.fileNames, filename) 153 } 154 }) 155 txt.moduleNames = android.SortedUniqueStrings(txt.moduleNames) 156 txt.fileNames = android.SortedUniqueStrings(txt.fileNames) 157 158 android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n")) 159} 160 161func (txt *llndkLibrariesTxtModule) AndroidMkEntries() []android.AndroidMkEntries { 162 return []android.AndroidMkEntries{{ 163 Class: "ETC", 164 OutputFile: android.OptionalPathForPath(txt.outputFile), 165 ExtraEntries: []android.AndroidMkExtraEntriesFunc{ 166 func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { 167 entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base()) 168 }, 169 }, 170 }} 171} 172 173func (txt *llndkLibrariesTxtModule) MakeVars(ctx android.MakeVarsContext) { 174 ctx.Strict("LLNDK_LIBRARIES", strings.Join(txt.moduleNames, " ")) 175} 176 177// PrebuiltEtcModule interface 178func (txt *llndkLibrariesTxtModule) BaseDir() string { 179 return "etc" 180} 181 182// PrebuiltEtcModule interface 183func (txt *llndkLibrariesTxtModule) SubDir() string { 184 return "" 185} 186 187func (txt *llndkLibrariesTxtModule) OutputFiles(tag string) (android.Paths, error) { 188 return android.Paths{txt.outputFile}, nil 189} 190 191func llndkMutator(mctx android.BottomUpMutatorContext) { 192 m, ok := mctx.Module().(*Module) 193 if !ok { 194 return 195 } 196 197 if shouldSkipLlndkMutator(mctx, m) { 198 return 199 } 200 201 lib, isLib := m.linker.(*libraryDecorator) 202 prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker) 203 204 if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() { 205 m.VendorProperties.IsLLNDK = true 206 } 207 if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() { 208 m.VendorProperties.IsLLNDK = true 209 } 210 211 if vndkprebuilt, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok { 212 if !Bool(vndkprebuilt.properties.Vndk.Enabled) { 213 m.VendorProperties.IsLLNDK = true 214 } 215 } 216} 217 218// Check for modules that mustn't be LLNDK 219func shouldSkipLlndkMutator(mctx android.BottomUpMutatorContext, m *Module) bool { 220 if !m.Enabled(mctx) { 221 return true 222 } 223 if !m.Device() { 224 return true 225 } 226 if m.Target().NativeBridge == android.NativeBridgeEnabled { 227 return true 228 } 229 return false 230} 231