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