blob: bc61b6cb594240de4d8b9c49a157fe2c9a63718e [file] [log] [blame]
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -08001// 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 (
Jayant Chowdharydcd33b62018-02-23 16:43:23 -080018 "sync"
Jayant Chowdhary9677e8c2017-06-15 14:45:18 -070019
Colin Cross36242852017-06-23 15:06:31 -070020 "android/soong/android"
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -080021 "android/soong/cc/config"
22)
23
Jayant Chowdharydcd33b62018-02-23 16:43:23 -080024var (
Yo Chiang8aa4e3f2020-11-19 16:30:49 +080025 lsdumpPathsLock sync.Mutex
Colin Cross50bc3bc2024-10-25 09:53:41 -070026 lsdumpKey = android.NewOnceKey("lsdump")
Jayant Chowdharydcd33b62018-02-23 16:43:23 -080027)
28
Colin Cross50bc3bc2024-10-25 09:53:41 -070029func lsdumpPaths(config android.Config) *[]string {
30 return config.Once(lsdumpKey, func() any {
31 return &[]string{}
32 }).(*[]string)
33}
34
Hsin-Yi Chen362c1882024-02-06 15:43:17 +080035type lsdumpTag string
36
37const (
Hsin-Yi Chen98da0212024-04-14 19:08:17 +080038 apexLsdumpTag lsdumpTag = "APEX"
Hsin-Yi Chen362c1882024-02-06 15:43:17 +080039 llndkLsdumpTag lsdumpTag = "LLNDK"
Hsin-Yi Chen362c1882024-02-06 15:43:17 +080040 platformLsdumpTag lsdumpTag = "PLATFORM"
41 productLsdumpTag lsdumpTag = "PRODUCT"
42 vendorLsdumpTag lsdumpTag = "VENDOR"
43)
44
45// Return the prebuilt ABI dump directory for a tag; an empty string for an opt-in dump.
46func (tag *lsdumpTag) dirName() string {
47 switch *tag {
Hsin-Yi Chen98da0212024-04-14 19:08:17 +080048 case apexLsdumpTag:
49 return "platform"
Hsin-Yi Chen362c1882024-02-06 15:43:17 +080050 case llndkLsdumpTag:
51 return "vndk"
Hsin-Yi Chen362c1882024-02-06 15:43:17 +080052 default:
53 return ""
54 }
55}
56
Hsin-Yi Chen8feb4132022-12-26 15:54:36 +080057// Properties for ABI compatibility checker in Android.bp.
58type headerAbiCheckerProperties struct {
59 // Enable ABI checks (even if this is not an LLNDK/VNDK lib)
60 Enabled *bool
61
62 // Path to a symbol file that specifies the symbols to be included in the generated
63 // ABI dump file
64 Symbol_file *string `android:"path"`
65
66 // Symbol versions that should be ignored from the symbol file
67 Exclude_symbol_versions []string
68
69 // Symbol tags that should be ignored from the symbol file
70 Exclude_symbol_tags []string
71
72 // Run checks on all APIs (in addition to the ones referred by
73 // one of exported ELF symbols.)
74 Check_all_apis *bool
75
76 // Extra flags passed to header-abi-diff
77 Diff_flags []string
78
79 // Opt-in reference dump directories
80 Ref_dump_dirs []string
81}
82
83func (props *headerAbiCheckerProperties) enabled() bool {
84 return Bool(props.Enabled)
85}
86
87func (props *headerAbiCheckerProperties) explicitlyDisabled() bool {
88 return !BoolDefault(props.Enabled, true)
89}
90
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -080091type SAbiProperties struct {
Yo Chiang2bbadfa2020-12-14 11:42:16 +080092 // Whether ABI dump should be created for this module.
Colin Cross91ae5ec2024-10-01 14:03:40 -070093 // Set by `sabiTransitionMutator` if this module is a shared library that needs ABI check,
94 // or a static library that is depended on by an ABI checked library.
Yo Chiang2bbadfa2020-12-14 11:42:16 +080095 ShouldCreateSourceAbiDump bool `blueprint:"mutated"`
Yo Chiang8aa4e3f2020-11-19 16:30:49 +080096
97 // Include directories that may contain ABI information exported by a library.
98 // These directories are passed to the header-abi-dumper.
Hsin-Yi Chen5f228b02024-04-02 12:38:47 +080099 ReexportedIncludes []string `blueprint:"mutated"`
100 ReexportedSystemIncludes []string `blueprint:"mutated"`
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -0800101}
102
103type sabi struct {
104 Properties SAbiProperties
105}
106
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800107func (sabi *sabi) props() []interface{} {
108 return []interface{}{&sabi.Properties}
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -0800109}
110
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800111func (sabi *sabi) flags(ctx ModuleContext, flags Flags) Flags {
Yo Chiang8aa4e3f2020-11-19 16:30:49 +0800112 // Filter out flags which libTooling don't understand.
113 // This is here for legacy reasons and future-proof, in case the version of libTooling and clang
114 // diverge.
115 flags.Local.ToolingCFlags = config.ClangLibToolingFilterUnknownCflags(flags.Local.CFlags)
116 flags.Global.ToolingCFlags = config.ClangLibToolingFilterUnknownCflags(flags.Global.CFlags)
117 flags.Local.ToolingCppFlags = config.ClangLibToolingFilterUnknownCflags(flags.Local.CppFlags)
118 flags.Global.ToolingCppFlags = config.ClangLibToolingFilterUnknownCflags(flags.Global.CppFlags)
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -0800119 return flags
120}
121
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800122// Returns true if ABI dump should be created for this library, either because library is ABI
123// checked or is depended on by an ABI checked library.
124// Could be called as a nil receiver.
125func (sabi *sabi) shouldCreateSourceAbiDump() bool {
126 return sabi != nil && sabi.Properties.ShouldCreateSourceAbiDump
127}
128
Hsin-Yi Chen50884dc2024-01-05 14:41:06 +0800129// Returns a slice of strings that represent the ABI dumps generated for this module.
Colin Cross91ae5ec2024-10-01 14:03:40 -0700130func classifySourceAbiDump(m *Module) []lsdumpTag {
Hsin-Yi Chen362c1882024-02-06 15:43:17 +0800131 result := []lsdumpTag{}
Colin Cross91ae5ec2024-10-01 14:03:40 -0700132 headerAbiChecker := m.library.getHeaderAbiCheckerProperties(m)
Hsin-Yi Chen8feb4132022-12-26 15:54:36 +0800133 if headerAbiChecker.explicitlyDisabled() {
Hsin-Yi Chen50884dc2024-01-05 14:41:06 +0800134 return result
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800135 }
Hsin-Yi Chen27bafd02024-01-08 18:38:42 +0800136 if !m.InProduct() && !m.InVendor() {
Hsin-Yi Chen27bafd02024-01-08 18:38:42 +0800137 if m.isImplementationForLLNDKPublic() {
Hsin-Yi Chen362c1882024-02-06 15:43:17 +0800138 result = append(result, llndkLsdumpTag)
Hsin-Yi Chen27bafd02024-01-08 18:38:42 +0800139 }
Hsin-Yi Chen98da0212024-04-14 19:08:17 +0800140 if m.library.hasStubsVariants() {
141 result = append(result, apexLsdumpTag)
Hsin-Yi Chen3d5c6792024-04-22 11:47:57 +0800142 }
143 if headerAbiChecker.enabled() {
Hsin-Yi Chen362c1882024-02-06 15:43:17 +0800144 result = append(result, platformLsdumpTag)
Hsin-Yi Chen27bafd02024-01-08 18:38:42 +0800145 }
Hsin-Yi Chen50884dc2024-01-05 14:41:06 +0800146 } else if headerAbiChecker.enabled() {
Hsin-Yi Chen8feb4132022-12-26 15:54:36 +0800147 if m.InProduct() {
Hsin-Yi Chen362c1882024-02-06 15:43:17 +0800148 result = append(result, productLsdumpTag)
Hsin-Yi Chen8feb4132022-12-26 15:54:36 +0800149 }
150 if m.InVendor() {
Hsin-Yi Chen362c1882024-02-06 15:43:17 +0800151 result = append(result, vendorLsdumpTag)
Hsin-Yi Chen8feb4132022-12-26 15:54:36 +0800152 }
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800153 }
Hsin-Yi Chen50884dc2024-01-05 14:41:06 +0800154 return result
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800155}
156
Colin Cross91ae5ec2024-10-01 14:03:40 -0700157type shouldCreateAbiDumpContext interface {
158 android.ModuleProviderContext
159 Module() android.Module
160 Config() android.Config
161}
162
163var _ shouldCreateAbiDumpContext = android.ModuleContext(nil)
164var _ shouldCreateAbiDumpContext = android.OutgoingTransitionContext(nil)
165
166// Called from sabiTransitionMutator to check whether ABI dumps should be created for this module.
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800167// ctx should be wrapping a native library type module.
Colin Cross91ae5ec2024-10-01 14:03:40 -0700168func shouldCreateSourceAbiDumpForLibrary(ctx shouldCreateAbiDumpContext) bool {
169 m, ok := ctx.Module().(*Module)
170 if !ok {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800171 return false
Yo Chiang8aa4e3f2020-11-19 16:30:49 +0800172 }
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800173
Colin Cross91ae5ec2024-10-01 14:03:40 -0700174 // Only generate ABI dump for device modules.
175 if !m.Device() {
176 return false
177 }
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800178
179 // Only create ABI dump for native library module types.
180 if m.library == nil {
181 return false
182 }
183
Colin Cross91ae5ec2024-10-01 14:03:40 -0700184 // Don't create ABI dump for static libraries
185 // The sabi variant will be propagated to dependencies of ABI checked libraries.
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800186 if m.library.static() {
Colin Cross91ae5ec2024-10-01 14:03:40 -0700187 return false
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800188 }
189
190 // Module is shared library type.
191
Yo Chiangd737d3f2020-11-30 20:00:42 +0800192 // Don't check uninstallable modules.
Colin Crossa9c8c9f2020-12-16 10:20:23 -0800193 if m.IsHideFromMake() {
Yo Chiangd737d3f2020-11-30 20:00:42 +0800194 return false
195 }
196
197 // Don't check ramdisk or recovery variants. Only check core, vendor or product variants.
198 if m.InRamdisk() || m.InVendorRamdisk() || m.InRecovery() {
199 return false
200 }
201
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800202 // Don't create ABI dump for prebuilts.
Ivan Lozano3a7d0002021-03-30 12:19:36 -0400203 if m.Prebuilt() != nil || m.IsSnapshotPrebuilt() {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800204 return false
205 }
206
207 // Coverage builds have extra symbols.
208 if m.isCoverageVariant() {
209 return false
210 }
211
212 // Some sanitizer variants may have different ABI.
213 if m.sanitize != nil && !m.sanitize.isVariantOnProductionDevice() {
214 return false
215 }
216
217 // Don't create ABI dump for stubs.
Colin Cross127bb8b2020-12-16 16:46:01 -0800218 if m.isNDKStubLibrary() || m.IsLlndk() || m.IsStubs() {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800219 return false
220 }
221
Colin Crossff694a82023-12-13 15:54:49 -0800222 apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
223 if apexInfo.IsForPlatform() {
Yo Chiangd737d3f2020-11-30 20:00:42 +0800224 // Bionic libraries that are installed to the bootstrap directory are not ABI checked.
225 // Only the runtime APEX variants, which are the implementation libraries of bionic NDK stubs,
226 // are checked.
227 if InstallToBootstrap(m.BaseModuleName(), ctx.Config()) {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800228 return false
229 }
Yo Chiangd737d3f2020-11-30 20:00:42 +0800230 } else {
231 // Don't create ABI dump if this library is for APEX but isn't exported.
232 if !m.HasStubsVariants() {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800233 return false
234 }
235 }
Colin Cross91ae5ec2024-10-01 14:03:40 -0700236 return len(classifySourceAbiDump(m)) > 0
Yo Chiang8aa4e3f2020-11-19 16:30:49 +0800237}
238
239// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
240// of their dependencies would be generated.
Colin Cross91ae5ec2024-10-01 14:03:40 -0700241type sabiTransitionMutator struct{}
242
243func (s *sabiTransitionMutator) Split(ctx android.BaseModuleContext) []string {
244 return []string{""}
245}
246
247func (s *sabiTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800248 // Escape hatch to not check any ABI dump.
Colin Cross91ae5ec2024-10-01 14:03:40 -0700249 if ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
250 return ""
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800251 }
Colin Cross91ae5ec2024-10-01 14:03:40 -0700252
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800253 // Only create ABI dump for native shared libraries and their static library dependencies.
Colin Cross91ae5ec2024-10-01 14:03:40 -0700254 if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
255 if shouldCreateSourceAbiDumpForLibrary(ctx) {
256 if IsStaticDepTag(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
257 return "sabi"
258 }
259 } else if sourceVariation == "sabi" {
260 if IsWholeStaticLib(ctx.DepTag()) || ctx.DepTag() == reuseObjTag {
261 return "sabi"
262 }
263 }
264 }
265
266 return ""
267}
268
269func (s *sabiTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
270 if incomingVariation == "" {
271 return ""
272 }
273
274 if incomingVariation == "sabi" {
275 if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
276 return "sabi"
277 }
278 }
279
280 return ""
281}
282
283func (s *sabiTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
284 if m, ok := ctx.Module().(*Module); ok && m.sabi != nil {
285 if variation == "sabi" {
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800286 m.sabi.Properties.ShouldCreateSourceAbiDump = true
Colin Cross91ae5ec2024-10-01 14:03:40 -0700287 m.HideFromMake()
288 m.Properties.PreventInstall = true
289 } else if shouldCreateSourceAbiDumpForLibrary(ctx) {
290 // Escape hatch to not check any ABI dump.
291 if !ctx.Config().IsEnvTrue("SKIP_ABI_CHECKS") {
292 m.sabi.Properties.ShouldCreateSourceAbiDump = true
293 }
Yo Chiang2bbadfa2020-12-14 11:42:16 +0800294 }
Jayant Chowdhary3e231fd2017-02-08 13:45:53 -0800295 }
296}
Hsin-Yi Chen53489642019-07-31 17:10:45 +0800297
Yo Chiang8aa4e3f2020-11-19 16:30:49 +0800298// Add an entry to the global list of lsdump. The list is exported to a Make variable by
299// `cc.makeVarsProvider`.
Colin Cross50bc3bc2024-10-25 09:53:41 -0700300func addLsdumpPath(config android.Config, lsdumpPath string) {
301 lsdumpPaths := lsdumpPaths(config)
Yo Chiang8aa4e3f2020-11-19 16:30:49 +0800302 lsdumpPathsLock.Lock()
303 defer lsdumpPathsLock.Unlock()
Colin Cross50bc3bc2024-10-25 09:53:41 -0700304 *lsdumpPaths = append(*lsdumpPaths, lsdumpPath)
Hsin-Yi Chen53489642019-07-31 17:10:45 +0800305}