blob: d21df51055e5bedb3c628bfe752159dd256a8c40 [file] [log] [blame]
Inseob Kim5eb7ee92022-04-27 10:30:34 +09001// Copyright 2021 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 (
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +090018 "regexp"
Kiyoung Kimee58c932022-10-25 22:59:41 +090019 "strings"
20
Inseob Kim5eb7ee92022-04-27 10:30:34 +090021 "android/soong/android"
22 "android/soong/multitree"
23)
24
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +090025var (
26 ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
27)
28
Inseob Kim5eb7ee92022-04-27 10:30:34 +090029func init() {
30 RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
31}
32
33func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
Kiyoung Kim487689e2022-07-26 09:48:22 +090034 ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
Kiyoung Kim51279d32022-08-24 14:10:46 +090035 ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
Kiyoung Kimee58c932022-10-25 22:59:41 +090036 ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
37}
38
39func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
40 m, ok := ctx.Module().(*Module)
41 if !ok {
42 return
43 }
44
45 apiLibrary, ok := m.linker.(*apiLibraryDecorator)
46 if !ok {
47 return
48 }
49
50 if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +090051 // Add LLNDK variant dependency
52 if inList("llndk", apiLibrary.properties.Variants) {
53 variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
54 ctx.AddDependency(m, nil, variantName)
55 }
56 } else if m.IsSdkVariant() {
57 // Add NDK variant dependencies
58 targetVariant := "ndk." + m.StubsVersion()
59 if inList(targetVariant, apiLibrary.properties.Variants) {
60 variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
61 ctx.AddDependency(m, nil, variantName)
Kiyoung Kimee58c932022-10-25 22:59:41 +090062 }
63 }
Inseob Kim5eb7ee92022-04-27 10:30:34 +090064}
65
Kiyoung Kim487689e2022-07-26 09:48:22 +090066// 'cc_api_library' is a module type which is from the exported API surface
67// with C shared library type. The module will replace original module, and
68// offer a link to the module that generates shared library object from the
69// map file.
70type apiLibraryProperties struct {
Kiyoung Kimee58c932022-10-25 22:59:41 +090071 Src *string `android:"arch_variant"`
72 Variants []string
Kiyoung Kim487689e2022-07-26 09:48:22 +090073}
74
75type apiLibraryDecorator struct {
76 *libraryDecorator
77 properties apiLibraryProperties
78}
79
80func CcApiLibraryFactory() android.Module {
81 module, decorator := NewLibrary(android.DeviceSupported)
82 apiLibraryDecorator := &apiLibraryDecorator{
83 libraryDecorator: decorator,
84 }
85 apiLibraryDecorator.BuildOnlyShared()
86
87 module.stl = nil
88 module.sanitize = nil
89 decorator.disableStripping()
90
91 module.compiler = nil
92 module.linker = apiLibraryDecorator
93 module.installer = nil
Kiyoung Kimee58c932022-10-25 22:59:41 +090094 module.library = apiLibraryDecorator
Kiyoung Kim487689e2022-07-26 09:48:22 +090095 module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
96
Kiyoung Kim487689e2022-07-26 09:48:22 +090097 // Prevent default system libs (libc, libm, and libdl) from being linked
98 if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
99 apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
100 }
101
Kiyoung Kim835c5892022-08-17 16:40:16 +0900102 apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
103 apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
104
Kiyoung Kim487689e2022-07-26 09:48:22 +0900105 module.Init()
106
107 return module
108}
109
110func (d *apiLibraryDecorator) Name(basename string) string {
111 return basename + multitree.GetApiImportSuffix()
112}
113
Spandan Dasf0beebc2022-10-18 18:23:28 +0000114// Export include dirs without checking for existence.
115// The directories are not guaranteed to exist during Soong analysis.
116func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
117 exporterProps := d.flagExporter.Properties
118 for _, dir := range exporterProps.Export_include_dirs {
Spandan Dasc6c10fa2022-10-21 21:52:13 +0000119 d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
Spandan Dasf0beebc2022-10-18 18:23:28 +0000120 }
121 // system headers
122 for _, dir := range exporterProps.Export_system_include_dirs {
Spandan Dasc6c10fa2022-10-21 21:52:13 +0000123 d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
Spandan Dasf0beebc2022-10-18 18:23:28 +0000124 }
125}
126
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900127func (d *apiLibraryDecorator) linkerInit(ctx BaseModuleContext) {
128 d.baseLinker.linkerInit(ctx)
129
130 if d.hasNDKStubs() {
131 // Set SDK version of module as current
132 ctx.Module().(*Module).Properties.Sdk_version = StringPtr("current")
133
134 // Add NDK stub as NDK known libs
135 name := ctx.ModuleName()
136
137 ndkKnownLibsLock.Lock()
138 ndkKnownLibs := getNDKKnownLibs(ctx.Config())
139 if !inList(name, *ndkKnownLibs) {
140 *ndkKnownLibs = append(*ndkKnownLibs, name)
141 }
142 ndkKnownLibsLock.Unlock()
143 }
144}
145
Kiyoung Kim487689e2022-07-26 09:48:22 +0900146func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900147 m, _ := ctx.Module().(*Module)
148
149 var in android.Path
150
Spandan Das6830f6b2022-12-02 23:26:38 +0000151 // src might not exist during the beginning of soong analysis in Multi-tree
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900152 if src := String(d.properties.Src); src != "" {
Spandan Das6830f6b2022-12-02 23:26:38 +0000153 in = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), src)
Kiyoung Kimee58c932022-10-25 22:59:41 +0900154 }
155
156 // LLNDK variant
157 if m.UseVndk() && d.hasLLNDKStubs() {
158 apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
159
160 var mod android.Module
161
162 ctx.VisitDirectDeps(func(depMod android.Module) {
163 if depMod.Name() == apiVariantModule {
164 mod = depMod
165 }
166 })
167
168 if mod != nil {
169 variantMod, ok := mod.(*CcApiVariant)
170 if ok {
171 in = variantMod.Src()
172
173 // Copy LLDNK properties to cc_api_library module
174 d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
175 d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
Kiyoung Kim62ed3dd2022-12-02 10:20:55 +0900176 variantMod.exportProperties.Export_include_dirs...)
Kiyoung Kimee58c932022-10-25 22:59:41 +0900177
178 // Export headers as system include dirs if specified. Mostly for libc
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900179 if Bool(variantMod.exportProperties.Export_headers_as_system) {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900180 d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
181 d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
182 d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
183 d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
184 }
185 }
186 }
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900187 } else if m.IsSdkVariant() {
188 // NDK Variant
189 apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion())
190
191 var mod android.Module
192
193 ctx.VisitDirectDeps(func(depMod android.Module) {
194 if depMod.Name() == apiVariantModule {
195 mod = depMod
196 }
197 })
198
199 if mod != nil {
200 variantMod, ok := mod.(*CcApiVariant)
201 if ok {
202 in = variantMod.Src()
203
204 // Copy NDK properties to cc_api_library module
205 d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
206 d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
Kiyoung Kim62ed3dd2022-12-02 10:20:55 +0900207 variantMod.exportProperties.Export_include_dirs...)
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900208 }
209 }
Kiyoung Kim51279d32022-08-24 14:10:46 +0900210 }
211
Kiyoung Kim487689e2022-07-26 09:48:22 +0900212 // Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
Spandan Dasf0beebc2022-10-18 18:23:28 +0000213 d.exportIncludes(ctx)
Kiyoung Kim487689e2022-07-26 09:48:22 +0900214 d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
215 d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
216 d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
217 d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
218 d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
Kiyoung Kim487689e2022-07-26 09:48:22 +0900219
Kiyoung Kimee58c932022-10-25 22:59:41 +0900220 if in == nil {
221 ctx.PropertyErrorf("src", "Unable to locate source property")
222 return nil
Spandan Dasf0beebc2022-10-18 18:23:28 +0000223 }
Kiyoung Kim487689e2022-07-26 09:48:22 +0900224
Spandan Dasa3c8a172022-10-26 20:54:32 +0000225 // Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
226 // The .so file itself has an order-only dependency on the headers contributed by this library.
227 // Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
228 d.libraryDecorator.reexportDeps(in)
229 d.libraryDecorator.flagExporter.setProvider(ctx)
230
Kiyoung Kim487689e2022-07-26 09:48:22 +0900231 d.unstrippedOutputFile = in
232 libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
233
234 tocFile := android.PathForModuleOut(ctx, libName+".toc")
235 d.tocFile = android.OptionalPathForPath(tocFile)
236 TransformSharedObjectToToc(ctx, in, tocFile)
237
238 ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
239 SharedLibrary: in,
240 Target: ctx.Target(),
241
242 TableOfContents: d.tocFile,
243 })
244
245 return in
246}
247
248func (d *apiLibraryDecorator) availableFor(what string) bool {
249 // Stub from API surface should be available for any APEX.
250 return true
251}
252
Kiyoung Kimee58c932022-10-25 22:59:41 +0900253func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
254 m, ok := ctx.Module().(*Module)
255
256 if !ok {
257 return nil
258 }
259
260 if d.hasLLNDKStubs() && m.UseVndk() {
261 // LLNDK libraries only need a single stubs variant.
262 return []string{android.FutureApiLevel.String()}
263 }
264
265 // TODO(b/244244438) Create more version information for NDK and APEX variations
266 // NDK variants
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900267
268 if m.IsSdkVariant() {
269 // TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
270 if d.hasNDKStubs() {
271 return d.getNdkVersions()
272 }
273 }
274
Kiyoung Kimee58c932022-10-25 22:59:41 +0900275 if m.MinSdkVersion() == "" {
276 return nil
277 }
278
279 firstVersion, err := nativeApiLevelFromUser(ctx,
280 m.MinSdkVersion())
281
282 if err != nil {
283 return nil
284 }
285
286 return ndkLibraryVersions(ctx, firstVersion)
287}
288
289func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900290 return inList("llndk", d.properties.Variants)
291}
292
293func (d *apiLibraryDecorator) hasNDKStubs() bool {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900294 for _, variant := range d.properties.Variants {
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900295 if ndkVariantRegex.MatchString(variant) {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900296 return true
297 }
298 }
299 return false
300}
301
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900302func (d *apiLibraryDecorator) getNdkVersions() []string {
303 ndkVersions := []string{}
304
305 for _, variant := range d.properties.Variants {
306 if match := ndkVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
307 ndkVersions = append(ndkVersions, match[1])
308 }
309 }
310
311 return ndkVersions
312}
313
Kiyoung Kim51279d32022-08-24 14:10:46 +0900314// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
315// header libraries. The module will replace any dependencies to existing
316// original header libraries.
317type apiHeadersDecorator struct {
318 *libraryDecorator
319}
320
321func CcApiHeadersFactory() android.Module {
322 module, decorator := NewLibrary(android.DeviceSupported)
323 apiHeadersDecorator := &apiHeadersDecorator{
324 libraryDecorator: decorator,
325 }
326 apiHeadersDecorator.HeaderOnly()
327
328 module.stl = nil
329 module.sanitize = nil
330 decorator.disableStripping()
331
332 module.compiler = nil
333 module.linker = apiHeadersDecorator
334 module.installer = nil
335
Kiyoung Kim51279d32022-08-24 14:10:46 +0900336 // Prevent default system libs (libc, libm, and libdl) from being linked
337 if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
338 apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
339 }
340
341 apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
342 apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
343
344 module.Init()
345
346 return module
347}
348
349func (d *apiHeadersDecorator) Name(basename string) string {
350 return basename + multitree.GetApiImportSuffix()
351}
352
353func (d *apiHeadersDecorator) availableFor(what string) bool {
354 // Stub from API surface should be available for any APEX.
355 return true
Kiyoung Kim487689e2022-07-26 09:48:22 +0900356}
Kiyoung Kimee58c932022-10-25 22:59:41 +0900357
358type ccApiexportProperties struct {
359 Src *string `android:"arch_variant"`
360 Variant *string
361 Version *string
362}
363
364type variantExporterProperties struct {
Kiyoung Kim3d776f42022-11-11 12:35:01 +0900365 // Header directory to export
Kiyoung Kim62ed3dd2022-12-02 10:20:55 +0900366 Export_include_dirs []string `android:"arch_variant"`
Kiyoung Kimee58c932022-10-25 22:59:41 +0900367
368 // Export all headers as system include
369 Export_headers_as_system *bool
370}
371
372type CcApiVariant struct {
373 android.ModuleBase
374
375 properties ccApiexportProperties
376 exportProperties variantExporterProperties
377
378 src android.Path
379}
380
381var _ android.Module = (*CcApiVariant)(nil)
382var _ android.ImageInterface = (*CcApiVariant)(nil)
383
384func CcApiVariantFactory() android.Module {
385 module := &CcApiVariant{}
386
387 module.AddProperties(&module.properties)
388 module.AddProperties(&module.exportProperties)
389
390 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
391 return module
392}
393
394func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
395 // No need to build
396
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900397 if String(v.properties.Src) == "" {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900398 ctx.PropertyErrorf("src", "src is a required property")
399 }
400
401 // Skip the existence check of the stub prebuilt file.
402 // The file is not guaranteed to exist during Soong analysis.
403 // Build orchestrator will be responsible for creating a connected ninja graph.
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900404 v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), String(v.properties.Src))
Kiyoung Kimee58c932022-10-25 22:59:41 +0900405}
406
407func (v *CcApiVariant) Name() string {
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900408 version := String(v.properties.Version)
Kiyoung Kimee58c932022-10-25 22:59:41 +0900409 return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
410}
411
412func (v *CcApiVariant) Src() android.Path {
413 return v.src
414}
415
416func BuildApiVariantName(baseName string, variant string, version string) string {
417 names := []string{baseName, variant}
418 if version != "" {
419 names = append(names, version)
420 }
421
422 return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
423}
424
425// Implement ImageInterface to generate image variants
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900426func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
427func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
428 return String(v.properties.Variant) == "ndk"
429}
Kiyoung Kimee58c932022-10-25 22:59:41 +0900430func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
431func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
432func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
433func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
434func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
435 var variations []string
436 platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
437
Kiyoung Kimd5d1ab12022-11-28 16:47:10 +0900438 if String(v.properties.Variant) == "llndk" {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900439 variations = append(variations, VendorVariationPrefix+platformVndkVersion)
440 variations = append(variations, ProductVariationPrefix+platformVndkVersion)
441 }
442
443 return variations
444}
445func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
446}