blob: 1597a6f1f2b4b2e079bc67f3a18c16456eb961af [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 (
18 "android/soong/android"
19 "android/soong/multitree"
20)
21
22func init() {
23 RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
24}
25
26func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
Kiyoung Kim487689e2022-07-26 09:48:22 +090027 ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
Kiyoung Kim51279d32022-08-24 14:10:46 +090028 ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
29
30 // cc_api_stub_library shares a lot of ndk_library, and this will be refactored later
Inseob Kim5eb7ee92022-04-27 10:30:34 +090031 ctx.RegisterModuleType("cc_api_stub_library", CcApiStubLibraryFactory)
32 ctx.RegisterModuleType("cc_api_contribution", CcApiContributionFactory)
33}
34
Kiyoung Kim487689e2022-07-26 09:48:22 +090035// 'cc_api_library' is a module type which is from the exported API surface
36// with C shared library type. The module will replace original module, and
37// offer a link to the module that generates shared library object from the
38// map file.
39type apiLibraryProperties struct {
40 Src *string `android:"arch_variant"`
41}
42
43type apiLibraryDecorator struct {
44 *libraryDecorator
45 properties apiLibraryProperties
46}
47
48func CcApiLibraryFactory() android.Module {
49 module, decorator := NewLibrary(android.DeviceSupported)
50 apiLibraryDecorator := &apiLibraryDecorator{
51 libraryDecorator: decorator,
52 }
53 apiLibraryDecorator.BuildOnlyShared()
54
55 module.stl = nil
56 module.sanitize = nil
57 decorator.disableStripping()
58
59 module.compiler = nil
60 module.linker = apiLibraryDecorator
61 module.installer = nil
62 module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
63
64 // Mark module as stub, so APEX would not include this stub in the package.
65 module.library.setBuildStubs(true)
66
67 // Prevent default system libs (libc, libm, and libdl) from being linked
68 if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
69 apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
70 }
71
Kiyoung Kim835c5892022-08-17 16:40:16 +090072 apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
73 apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
74
Kiyoung Kim487689e2022-07-26 09:48:22 +090075 module.Init()
76
77 return module
78}
79
80func (d *apiLibraryDecorator) Name(basename string) string {
81 return basename + multitree.GetApiImportSuffix()
82}
83
Spandan Dasf0beebc2022-10-18 18:23:28 +000084// Export include dirs without checking for existence.
85// The directories are not guaranteed to exist during Soong analysis.
86func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
87 exporterProps := d.flagExporter.Properties
88 for _, dir := range exporterProps.Export_include_dirs {
89 d.dirs = append(d.dirs, android.PathForSource(ctx, ctx.ModuleDir(), dir))
90 }
91 // system headers
92 for _, dir := range exporterProps.Export_system_include_dirs {
93 d.systemDirs = append(d.systemDirs, android.PathForSource(ctx, ctx.ModuleDir(), dir))
94 }
95}
96
Kiyoung Kim487689e2022-07-26 09:48:22 +090097func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
Kiyoung Kim51279d32022-08-24 14:10:46 +090098 // Export headers as system include dirs if specified. Mostly for libc
99 if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
100 d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
101 d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
102 d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
103 d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
104 }
105
Kiyoung Kim487689e2022-07-26 09:48:22 +0900106 // Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
Spandan Dasf0beebc2022-10-18 18:23:28 +0000107 d.exportIncludes(ctx)
Kiyoung Kim487689e2022-07-26 09:48:22 +0900108 d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
109 d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
110 d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
111 d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
112 d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
113 d.libraryDecorator.flagExporter.setProvider(ctx)
114
Spandan Dasf0beebc2022-10-18 18:23:28 +0000115 if d.properties.Src == nil {
116 ctx.PropertyErrorf("src", "src is a required property")
117 }
118 // Skip the existence check of the stub prebuilt file.
119 // The file is not guaranteed to exist during Soong analysis.
120 // Build orchestrator will be responsible for creating a connected ninja graph.
121 in := android.PathForSource(ctx, ctx.ModuleDir(), *d.properties.Src)
Kiyoung Kim487689e2022-07-26 09:48:22 +0900122
123 d.unstrippedOutputFile = in
124 libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
125
126 tocFile := android.PathForModuleOut(ctx, libName+".toc")
127 d.tocFile = android.OptionalPathForPath(tocFile)
128 TransformSharedObjectToToc(ctx, in, tocFile)
129
130 ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
131 SharedLibrary: in,
132 Target: ctx.Target(),
133
134 TableOfContents: d.tocFile,
135 })
136
137 return in
138}
139
140func (d *apiLibraryDecorator) availableFor(what string) bool {
141 // Stub from API surface should be available for any APEX.
142 return true
143}
144
Kiyoung Kim51279d32022-08-24 14:10:46 +0900145// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
146// header libraries. The module will replace any dependencies to existing
147// original header libraries.
148type apiHeadersDecorator struct {
149 *libraryDecorator
150}
151
152func CcApiHeadersFactory() android.Module {
153 module, decorator := NewLibrary(android.DeviceSupported)
154 apiHeadersDecorator := &apiHeadersDecorator{
155 libraryDecorator: decorator,
156 }
157 apiHeadersDecorator.HeaderOnly()
158
159 module.stl = nil
160 module.sanitize = nil
161 decorator.disableStripping()
162
163 module.compiler = nil
164 module.linker = apiHeadersDecorator
165 module.installer = nil
166
167 // Mark module as stub, so APEX would not include this stub in the package.
168 module.library.setBuildStubs(true)
169
170 // Prevent default system libs (libc, libm, and libdl) from being linked
171 if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
172 apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
173 }
174
175 apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
176 apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
177
178 module.Init()
179
180 return module
181}
182
183func (d *apiHeadersDecorator) Name(basename string) string {
184 return basename + multitree.GetApiImportSuffix()
185}
186
187func (d *apiHeadersDecorator) availableFor(what string) bool {
188 // Stub from API surface should be available for any APEX.
189 return true
Kiyoung Kim487689e2022-07-26 09:48:22 +0900190}
191
Inseob Kim5eb7ee92022-04-27 10:30:34 +0900192func CcApiStubLibraryFactory() android.Module {
193 module, decorator := NewLibrary(android.DeviceSupported)
194 apiStubDecorator := &apiStubDecorator{
195 libraryDecorator: decorator,
196 }
197 apiStubDecorator.BuildOnlyShared()
198
199 module.compiler = apiStubDecorator
200 module.linker = apiStubDecorator
201 module.installer = nil
202 module.library = apiStubDecorator
203 module.Properties.HideFromMake = true // TODO: remove
204
205 android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
206 module.AddProperties(&module.Properties,
207 &apiStubDecorator.properties,
208 &apiStubDecorator.MutatedProperties,
209 &apiStubDecorator.apiStubLibraryProperties)
210 return module
211}
212
213type apiStubLiraryProperties struct {
214 Imported_includes []string `android:"path"`
215}
216
217type apiStubDecorator struct {
218 *libraryDecorator
219 properties libraryProperties
220 apiStubLibraryProperties apiStubLiraryProperties
221}
222
223func (compiler *apiStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
224 firstVersion := String(compiler.properties.First_version)
225 return ndkLibraryVersions(ctx, android.ApiLevelOrPanic(ctx, firstVersion))
226}
227
228func (decorator *apiStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
229 if decorator.stubsVersion() == "" {
230 decorator.setStubsVersion("current")
231 } // TODO: fix
232 symbolFile := String(decorator.properties.Symbol_file)
233 nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
234 android.ApiLevelOrPanic(ctx, decorator.stubsVersion()),
235 "")
236 return compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
237}
238
239func (decorator *apiStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
240 decorator.reexportDirs(android.PathsForModuleSrc(ctx, decorator.apiStubLibraryProperties.Imported_includes)...)
241 return decorator.libraryDecorator.link(ctx, flags, deps, objects)
242}
243
244func init() {
245 pctx.HostBinToolVariable("gen_api_surface_build_files", "gen_api_surface_build_files")
246}
247
248type CcApiContribution struct {
249 android.ModuleBase
250 properties ccApiContributionProperties
251}
252
253type ccApiContributionProperties struct {
254 Symbol_file *string `android:"path"`
255 First_version *string
256 Export_include_dir *string
257}
258
259func CcApiContributionFactory() android.Module {
260 module := &CcApiContribution{}
261 module.AddProperties(&module.properties)
262 android.InitAndroidModule(module)
263 return module
264}
265
266// Do some simple validations
267// Majority of the build rules will be created in the ctx of the api surface this module contributes to
268func (contrib *CcApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
269 if contrib.properties.Symbol_file == nil {
270 ctx.PropertyErrorf("symbol_file", "%v does not have symbol file", ctx.ModuleName())
271 }
272 if contrib.properties.First_version == nil {
273 ctx.PropertyErrorf("first_version", "%v does not have first_version for stub variants", ctx.ModuleName())
274 }
275}
276
277// Path is out/soong/.export/ but will be different in final multi-tree layout
278func outPathApiSurface(ctx android.ModuleContext, myModuleName string, pathComponent string) android.OutputPath {
279 return android.PathForOutput(ctx, ".export", ctx.ModuleName(), myModuleName, pathComponent)
280}
281
282func (contrib *CcApiContribution) CopyFilesWithTag(apiSurfaceContext android.ModuleContext) map[string]android.Paths {
283 // copy map.txt for now
284 // hardlinks cannot be created since nsjail creates a different mountpoint for out/
285 myDir := apiSurfaceContext.OtherModuleDir(contrib)
286 genMapTxt := outPathApiSurface(apiSurfaceContext, contrib.Name(), String(contrib.properties.Symbol_file))
287 apiSurfaceContext.Build(pctx, android.BuildParams{
288 Rule: android.Cp,
289 Description: "import map.txt file",
290 Input: android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Symbol_file)),
291 Output: genMapTxt,
292 })
293
294 outputs := make(map[string]android.Paths)
295 outputs["map"] = []android.Path{genMapTxt}
296
297 if contrib.properties.Export_include_dir != nil {
298 includeDir := android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Export_include_dir))
299 outputs["export_include_dir"] = []android.Path{includeDir}
300 }
301 return outputs
302}
303
304var _ multitree.ApiContribution = (*CcApiContribution)(nil)
305
306/*
307func (contrib *CcApiContribution) GenerateBuildFiles(apiSurfaceContext android.ModuleContext) android.Paths {
308 genAndroidBp := outPathApiSurface(apiSurfaceContext, contrib.Name(), "Android.bp")
309
310 // generate Android.bp
311 apiSurfaceContext.Build(pctx, android.BuildParams{
312 Rule: genApiSurfaceBuildFiles,
313 Description: "generate API surface build files",
314 Outputs: []android.WritablePath{genAndroidBp},
315 Args: map[string]string{
316 "name": contrib.Name() + "." + apiSurfaceContext.ModuleName(), //e.g. liblog.ndk
317 "symbol_file": String(contrib.properties.Symbol_file),
318 "first_version": String(contrib.properties.First_version),
319 },
320 })
321 return []android.Path{genAndroidBp}
322}
323*/