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 "sync" 19 20 "android/soong/android" 21 "android/soong/cc/config" 22) 23 24var ( 25 lsdumpPaths []string 26 lsdumpPathsLock sync.Mutex 27) 28 29type SAbiProperties struct { 30 // Whether ABI dump should be created for this module. 31 // Set by `sabiDepsMutator` if this module is a shared library that needs ABI check, or a static 32 // library that is depended on by an ABI checked library. 33 ShouldCreateSourceAbiDump bool `blueprint:"mutated"` 34 35 // Include directories that may contain ABI information exported by a library. 36 // These directories are passed to the header-abi-dumper. 37 ReexportedIncludes []string `blueprint:"mutated"` 38} 39 40type sabi struct { 41 Properties SAbiProperties 42} 43 44func (sabi *sabi) props() []interface{} { 45 return []interface{}{&sabi.Properties} 46} 47 48func (sabi *sabi) begin(ctx BaseModuleContext) {} 49 50func (sabi *sabi) deps(ctx BaseModuleContext, deps Deps) Deps { 51 return deps 52} 53 54func (sabi *sabi) flags(ctx ModuleContext, flags Flags) Flags { 55 // Filter out flags which libTooling don't understand. 56 // This is here for legacy reasons and future-proof, in case the version of libTooling and clang 57 // diverge. 58 flags.Local.ToolingCFlags = config.ClangLibToolingFilterUnknownCflags(flags.Local.CFlags) 59 flags.Global.ToolingCFlags = config.ClangLibToolingFilterUnknownCflags(flags.Global.CFlags) 60 flags.Local.ToolingCppFlags = config.ClangLibToolingFilterUnknownCflags(flags.Local.CppFlags) 61 flags.Global.ToolingCppFlags = config.ClangLibToolingFilterUnknownCflags(flags.Global.CppFlags) 62 return flags 63} 64 65// Returns true if ABI dump should be created for this library, either because library is ABI 66// checked or is depended on by an ABI checked library. 67// Could be called as a nil receiver. 68func (sabi *sabi) shouldCreateSourceAbiDump() bool { 69 return sabi != nil && sabi.Properties.ShouldCreateSourceAbiDump 70} 71 72// Returns a string that represents the class of the ABI dump. 73// Returns an empty string if ABI check is disabled for this library. 74func classifySourceAbiDump(ctx android.BaseModuleContext) string { 75 m := ctx.Module().(*Module) 76 if m.library.headerAbiCheckerExplicitlyDisabled() { 77 return "" 78 } 79 // Return NDK if the library is both NDK and LLNDK. 80 if m.IsNdk(ctx.Config()) { 81 return "NDK" 82 } 83 if m.isImplementationForLLNDKPublic() { 84 return "LLNDK" 85 } 86 if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate() { 87 if m.IsVndkSp() { 88 if m.IsVndkExt() { 89 return "VNDK-SP-ext" 90 } else { 91 return "VNDK-SP" 92 } 93 } else { 94 if m.IsVndkExt() { 95 return "VNDK-ext" 96 } else { 97 return "VNDK-core" 98 } 99 } 100 } 101 if m.library.headerAbiCheckerEnabled() || m.library.hasStubsVariants() { 102 return "PLATFORM" 103 } 104 return "" 105} 106 107// Called from sabiDepsMutator to check whether ABI dumps should be created for this module. 108// ctx should be wrapping a native library type module. 109func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool { 110 if ctx.Fuchsia() { 111 return false 112 } 113 114 // Only generate ABI dump for device modules. 115 if !ctx.Device() { 116 return false 117 } 118 119 m := ctx.Module().(*Module) 120 121 // Only create ABI dump for native library module types. 122 if m.library == nil { 123 return false 124 } 125 126 // Create ABI dump for static libraries only if they are dependencies of ABI checked libraries. 127 if m.library.static() { 128 return m.sabi.shouldCreateSourceAbiDump() 129 } 130 131 // Module is shared library type. 132 133 // Don't check uninstallable modules. 134 if m.IsHideFromMake() { 135 return false 136 } 137 138 // Don't check ramdisk or recovery variants. Only check core, vendor or product variants. 139 if m.InRamdisk() || m.InVendorRamdisk() || m.InRecovery() { 140 return false 141 } 142 143 // Don't create ABI dump for prebuilts. 144 if m.Prebuilt() != nil || m.IsSnapshotPrebuilt() { 145 return false 146 } 147 148 // Coverage builds have extra symbols. 149 if m.isCoverageVariant() { 150 return false 151 } 152 153 // Some sanitizer variants may have different ABI. 154 if m.sanitize != nil && !m.sanitize.isVariantOnProductionDevice() { 155 return false 156 } 157 158 // Don't create ABI dump for stubs. 159 if m.isNDKStubLibrary() || m.IsLlndk() || m.IsStubs() { 160 return false 161 } 162 163 isPlatformVariant := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() 164 if isPlatformVariant { 165 // Bionic libraries that are installed to the bootstrap directory are not ABI checked. 166 // Only the runtime APEX variants, which are the implementation libraries of bionic NDK stubs, 167 // are checked. 168 if InstallToBootstrap(m.BaseModuleName(), ctx.Config()) { 169 return false 170 } 171 } else { 172 // Don't create ABI dump if this library is for APEX but isn't exported. 173 if !m.HasStubsVariants() { 174 return false 175 } 176 } 177 return classifySourceAbiDump(ctx) != "" 178} 179 180// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps 181// of their dependencies would be generated. 182func sabiDepsMutator(mctx android.TopDownMutatorContext) { 183 // Escape hatch to not check any ABI dump. 184 if mctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") { 185 return 186 } 187 // Only create ABI dump for native shared libraries and their static library dependencies. 188 if m, ok := mctx.Module().(*Module); ok && m.sabi != nil { 189 if shouldCreateSourceAbiDumpForLibrary(mctx) { 190 // Mark this module so that .sdump / .lsdump for this library can be generated. 191 m.sabi.Properties.ShouldCreateSourceAbiDump = true 192 // Mark all of its static library dependencies. 193 mctx.VisitDirectDeps(func(child android.Module) { 194 depTag := mctx.OtherModuleDependencyTag(child) 195 if IsStaticDepTag(depTag) || depTag == reuseObjTag { 196 if c, ok := child.(*Module); ok && c.sabi != nil { 197 // Mark this module so that .sdump for this static library can be generated. 198 c.sabi.Properties.ShouldCreateSourceAbiDump = true 199 } 200 } 201 }) 202 } 203 } 204} 205 206// Add an entry to the global list of lsdump. The list is exported to a Make variable by 207// `cc.makeVarsProvider`. 208func addLsdumpPath(lsdumpPath string) { 209 lsdumpPathsLock.Lock() 210 defer lsdumpPathsLock.Unlock() 211 lsdumpPaths = append(lsdumpPaths, lsdumpPath) 212} 213