blob: 043c03c30f95602abff0ac03f3a08931e33f022a [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 Kimee58c932022-10-25 22:59:41 +090018 "strings"
19
20 "github.com/google/blueprint/proptools"
21
Inseob Kim5eb7ee92022-04-27 10:30:34 +090022 "android/soong/android"
23 "android/soong/multitree"
24)
25
26func init() {
27 RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
28}
29
30func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
Kiyoung Kim487689e2022-07-26 09:48:22 +090031 ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
Kiyoung Kim51279d32022-08-24 14:10:46 +090032 ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
Kiyoung Kimee58c932022-10-25 22:59:41 +090033 ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
34}
35
36func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
37 m, ok := ctx.Module().(*Module)
38 if !ok {
39 return
40 }
41
42 apiLibrary, ok := m.linker.(*apiLibraryDecorator)
43 if !ok {
44 return
45 }
46
47 if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
48 // Add LLNDK dependencies
49 for _, variant := range apiLibrary.properties.Variants {
50 if variant == "llndk" {
51 variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
52 ctx.AddDependency(m, nil, variantName)
53 break
54 }
55 }
56 }
Inseob Kim5eb7ee92022-04-27 10:30:34 +090057}
58
Kiyoung Kim487689e2022-07-26 09:48:22 +090059// 'cc_api_library' is a module type which is from the exported API surface
60// with C shared library type. The module will replace original module, and
61// offer a link to the module that generates shared library object from the
62// map file.
63type apiLibraryProperties struct {
Kiyoung Kimee58c932022-10-25 22:59:41 +090064 Src *string `android:"arch_variant"`
65 Variants []string
Kiyoung Kim487689e2022-07-26 09:48:22 +090066}
67
68type apiLibraryDecorator struct {
69 *libraryDecorator
70 properties apiLibraryProperties
71}
72
73func CcApiLibraryFactory() android.Module {
74 module, decorator := NewLibrary(android.DeviceSupported)
75 apiLibraryDecorator := &apiLibraryDecorator{
76 libraryDecorator: decorator,
77 }
78 apiLibraryDecorator.BuildOnlyShared()
79
80 module.stl = nil
81 module.sanitize = nil
82 decorator.disableStripping()
83
84 module.compiler = nil
85 module.linker = apiLibraryDecorator
86 module.installer = nil
Kiyoung Kimee58c932022-10-25 22:59:41 +090087 module.library = apiLibraryDecorator
Kiyoung Kim487689e2022-07-26 09:48:22 +090088 module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
89
Kiyoung Kim487689e2022-07-26 09:48:22 +090090 // Prevent default system libs (libc, libm, and libdl) from being linked
91 if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
92 apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
93 }
94
Kiyoung Kim835c5892022-08-17 16:40:16 +090095 apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
96 apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
97
Kiyoung Kim487689e2022-07-26 09:48:22 +090098 module.Init()
99
100 return module
101}
102
103func (d *apiLibraryDecorator) Name(basename string) string {
104 return basename + multitree.GetApiImportSuffix()
105}
106
Spandan Dasf0beebc2022-10-18 18:23:28 +0000107// Export include dirs without checking for existence.
108// The directories are not guaranteed to exist during Soong analysis.
109func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
110 exporterProps := d.flagExporter.Properties
111 for _, dir := range exporterProps.Export_include_dirs {
Spandan Dasc6c10fa2022-10-21 21:52:13 +0000112 d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
Spandan Dasf0beebc2022-10-18 18:23:28 +0000113 }
114 // system headers
115 for _, dir := range exporterProps.Export_system_include_dirs {
Spandan Dasc6c10fa2022-10-21 21:52:13 +0000116 d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
Spandan Dasf0beebc2022-10-18 18:23:28 +0000117 }
118}
119
Kiyoung Kim487689e2022-07-26 09:48:22 +0900120func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
Kiyoung Kimee58c932022-10-25 22:59:41 +0900121 m, _ := ctx.Module().(*Module)
122
123 var in android.Path
124
125 if src := proptools.String(d.properties.Src); src != "" {
126 in = android.PathForModuleSrc(ctx, src)
127 }
128
129 // LLNDK variant
130 if m.UseVndk() && d.hasLLNDKStubs() {
131 apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
132
133 var mod android.Module
134
135 ctx.VisitDirectDeps(func(depMod android.Module) {
136 if depMod.Name() == apiVariantModule {
137 mod = depMod
138 }
139 })
140
141 if mod != nil {
142 variantMod, ok := mod.(*CcApiVariant)
143 if ok {
144 in = variantMod.Src()
145
146 // Copy LLDNK properties to cc_api_library module
147 d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
148 d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
149 variantMod.exportProperties.Export_headers...)
150
151 // Export headers as system include dirs if specified. Mostly for libc
152 if proptools.Bool(variantMod.exportProperties.Export_headers_as_system) {
153 d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
154 d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
155 d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
156 d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
157 }
158 }
159 }
Kiyoung Kim51279d32022-08-24 14:10:46 +0900160 }
161
Kiyoung Kim487689e2022-07-26 09:48:22 +0900162 // Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
Spandan Dasf0beebc2022-10-18 18:23:28 +0000163 d.exportIncludes(ctx)
Kiyoung Kim487689e2022-07-26 09:48:22 +0900164 d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
165 d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
166 d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
167 d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
168 d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
Kiyoung Kim487689e2022-07-26 09:48:22 +0900169
Kiyoung Kimee58c932022-10-25 22:59:41 +0900170 if in == nil {
171 ctx.PropertyErrorf("src", "Unable to locate source property")
172 return nil
Spandan Dasf0beebc2022-10-18 18:23:28 +0000173 }
Kiyoung Kim487689e2022-07-26 09:48:22 +0900174
Spandan Dasa3c8a172022-10-26 20:54:32 +0000175 // Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
176 // The .so file itself has an order-only dependency on the headers contributed by this library.
177 // Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
178 d.libraryDecorator.reexportDeps(in)
179 d.libraryDecorator.flagExporter.setProvider(ctx)
180
Kiyoung Kim487689e2022-07-26 09:48:22 +0900181 d.unstrippedOutputFile = in
182 libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
183
184 tocFile := android.PathForModuleOut(ctx, libName+".toc")
185 d.tocFile = android.OptionalPathForPath(tocFile)
186 TransformSharedObjectToToc(ctx, in, tocFile)
187
188 ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
189 SharedLibrary: in,
190 Target: ctx.Target(),
191
192 TableOfContents: d.tocFile,
193 })
194
195 return in
196}
197
198func (d *apiLibraryDecorator) availableFor(what string) bool {
199 // Stub from API surface should be available for any APEX.
200 return true
201}
202
Kiyoung Kimee58c932022-10-25 22:59:41 +0900203func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
204 m, ok := ctx.Module().(*Module)
205
206 if !ok {
207 return nil
208 }
209
210 if d.hasLLNDKStubs() && m.UseVndk() {
211 // LLNDK libraries only need a single stubs variant.
212 return []string{android.FutureApiLevel.String()}
213 }
214
215 // TODO(b/244244438) Create more version information for NDK and APEX variations
216 // NDK variants
217 if m.MinSdkVersion() == "" {
218 return nil
219 }
220
221 firstVersion, err := nativeApiLevelFromUser(ctx,
222 m.MinSdkVersion())
223
224 if err != nil {
225 return nil
226 }
227
228 return ndkLibraryVersions(ctx, firstVersion)
229}
230
231func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
232 for _, variant := range d.properties.Variants {
233 if strings.Contains(variant, "llndk") {
234 return true
235 }
236 }
237 return false
238}
239
Kiyoung Kim51279d32022-08-24 14:10:46 +0900240// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
241// header libraries. The module will replace any dependencies to existing
242// original header libraries.
243type apiHeadersDecorator struct {
244 *libraryDecorator
245}
246
247func CcApiHeadersFactory() android.Module {
248 module, decorator := NewLibrary(android.DeviceSupported)
249 apiHeadersDecorator := &apiHeadersDecorator{
250 libraryDecorator: decorator,
251 }
252 apiHeadersDecorator.HeaderOnly()
253
254 module.stl = nil
255 module.sanitize = nil
256 decorator.disableStripping()
257
258 module.compiler = nil
259 module.linker = apiHeadersDecorator
260 module.installer = nil
261
Kiyoung Kim51279d32022-08-24 14:10:46 +0900262 // Prevent default system libs (libc, libm, and libdl) from being linked
263 if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
264 apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
265 }
266
267 apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
268 apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
269
270 module.Init()
271
272 return module
273}
274
275func (d *apiHeadersDecorator) Name(basename string) string {
276 return basename + multitree.GetApiImportSuffix()
277}
278
279func (d *apiHeadersDecorator) availableFor(what string) bool {
280 // Stub from API surface should be available for any APEX.
281 return true
Kiyoung Kim487689e2022-07-26 09:48:22 +0900282}
Kiyoung Kimee58c932022-10-25 22:59:41 +0900283
284type ccApiexportProperties struct {
285 Src *string `android:"arch_variant"`
286 Variant *string
287 Version *string
288}
289
290type variantExporterProperties struct {
Kiyoung Kim3d776f42022-11-11 12:35:01 +0900291 // Header directory to export
292 Export_headers []string `android:"arch_variant"`
Kiyoung Kimee58c932022-10-25 22:59:41 +0900293
294 // Export all headers as system include
295 Export_headers_as_system *bool
296}
297
298type CcApiVariant struct {
299 android.ModuleBase
300
301 properties ccApiexportProperties
302 exportProperties variantExporterProperties
303
304 src android.Path
305}
306
307var _ android.Module = (*CcApiVariant)(nil)
308var _ android.ImageInterface = (*CcApiVariant)(nil)
309
310func CcApiVariantFactory() android.Module {
311 module := &CcApiVariant{}
312
313 module.AddProperties(&module.properties)
314 module.AddProperties(&module.exportProperties)
315
316 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
317 return module
318}
319
320func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
321 // No need to build
322
323 if proptools.String(v.properties.Src) == "" {
324 ctx.PropertyErrorf("src", "src is a required property")
325 }
326
327 // Skip the existence check of the stub prebuilt file.
328 // The file is not guaranteed to exist during Soong analysis.
329 // Build orchestrator will be responsible for creating a connected ninja graph.
330 v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), proptools.String(v.properties.Src))
331}
332
333func (v *CcApiVariant) Name() string {
334 version := proptools.String(v.properties.Version)
335 return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
336}
337
338func (v *CcApiVariant) Src() android.Path {
339 return v.src
340}
341
342func BuildApiVariantName(baseName string, variant string, version string) string {
343 names := []string{baseName, variant}
344 if version != "" {
345 names = append(names, version)
346 }
347
348 return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
349}
350
351// Implement ImageInterface to generate image variants
352func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
353func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool { return false }
354func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
355func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
356func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
357func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool { return false }
358func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
359 var variations []string
360 platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
361
362 if proptools.String(v.properties.Variant) == "llndk" {
363 variations = append(variations, VendorVariationPrefix+platformVndkVersion)
364 variations = append(variations, ProductVariationPrefix+platformVndkVersion)
365 }
366
367 return variations
368}
369func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
370}