51279d3a7b
Define cc_api_headers module to import from API surfaces and replace existing header definition if needed. Tested with : cc_api_headers { name: "libc_headers", export_system_include_dirs: [ "include", ], min_sdk_version: "1", sdk_version: "1", vendor_available: true, native_bridge_supported: true, ... } Bug: 236087698 Test: ALLOW_MISSING_DEPENDENCIES=true m -j vendorimage succeeded Change-Id: I2c3294fe19a272453a168d8c7beeee9859bd4583
304 lines
10 KiB
Go
304 lines
10 KiB
Go
// Copyright 2021 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package cc
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"android/soong/multitree"
|
|
)
|
|
|
|
func init() {
|
|
RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
|
|
}
|
|
|
|
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
|
|
ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
|
|
|
|
// cc_api_stub_library shares a lot of ndk_library, and this will be refactored later
|
|
ctx.RegisterModuleType("cc_api_stub_library", CcApiStubLibraryFactory)
|
|
ctx.RegisterModuleType("cc_api_contribution", CcApiContributionFactory)
|
|
}
|
|
|
|
// 'cc_api_library' is a module type which is from the exported API surface
|
|
// with C shared library type. The module will replace original module, and
|
|
// offer a link to the module that generates shared library object from the
|
|
// map file.
|
|
type apiLibraryProperties struct {
|
|
Src *string `android:"arch_variant"`
|
|
}
|
|
|
|
type apiLibraryDecorator struct {
|
|
*libraryDecorator
|
|
properties apiLibraryProperties
|
|
}
|
|
|
|
func CcApiLibraryFactory() android.Module {
|
|
module, decorator := NewLibrary(android.DeviceSupported)
|
|
apiLibraryDecorator := &apiLibraryDecorator{
|
|
libraryDecorator: decorator,
|
|
}
|
|
apiLibraryDecorator.BuildOnlyShared()
|
|
|
|
module.stl = nil
|
|
module.sanitize = nil
|
|
decorator.disableStripping()
|
|
|
|
module.compiler = nil
|
|
module.linker = apiLibraryDecorator
|
|
module.installer = nil
|
|
module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
|
|
|
|
// Mark module as stub, so APEX would not include this stub in the package.
|
|
module.library.setBuildStubs(true)
|
|
|
|
// Prevent default system libs (libc, libm, and libdl) from being linked
|
|
if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
|
|
apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
|
|
}
|
|
|
|
apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
|
|
apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
|
|
|
|
module.Init()
|
|
|
|
return module
|
|
}
|
|
|
|
func (d *apiLibraryDecorator) Name(basename string) string {
|
|
return basename + multitree.GetApiImportSuffix()
|
|
}
|
|
|
|
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
|
|
// Export headers as system include dirs if specified. Mostly for libc
|
|
if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
|
|
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
|
|
d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
|
|
d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
|
|
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
|
|
}
|
|
|
|
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
|
|
d.libraryDecorator.flagExporter.exportIncludes(ctx)
|
|
d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
|
|
d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
|
|
d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
|
|
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
|
|
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
|
|
d.libraryDecorator.flagExporter.setProvider(ctx)
|
|
|
|
in := android.PathForModuleSrc(ctx, *d.properties.Src)
|
|
|
|
d.unstrippedOutputFile = in
|
|
libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
|
|
|
|
tocFile := android.PathForModuleOut(ctx, libName+".toc")
|
|
d.tocFile = android.OptionalPathForPath(tocFile)
|
|
TransformSharedObjectToToc(ctx, in, tocFile)
|
|
|
|
ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
|
|
SharedLibrary: in,
|
|
Target: ctx.Target(),
|
|
|
|
TableOfContents: d.tocFile,
|
|
})
|
|
|
|
return in
|
|
}
|
|
|
|
func (d *apiLibraryDecorator) availableFor(what string) bool {
|
|
// Stub from API surface should be available for any APEX.
|
|
return true
|
|
}
|
|
|
|
// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
|
|
// header libraries. The module will replace any dependencies to existing
|
|
// original header libraries.
|
|
type apiHeadersDecorator struct {
|
|
*libraryDecorator
|
|
}
|
|
|
|
func CcApiHeadersFactory() android.Module {
|
|
module, decorator := NewLibrary(android.DeviceSupported)
|
|
apiHeadersDecorator := &apiHeadersDecorator{
|
|
libraryDecorator: decorator,
|
|
}
|
|
apiHeadersDecorator.HeaderOnly()
|
|
|
|
module.stl = nil
|
|
module.sanitize = nil
|
|
decorator.disableStripping()
|
|
|
|
module.compiler = nil
|
|
module.linker = apiHeadersDecorator
|
|
module.installer = nil
|
|
|
|
// Mark module as stub, so APEX would not include this stub in the package.
|
|
module.library.setBuildStubs(true)
|
|
|
|
// Prevent default system libs (libc, libm, and libdl) from being linked
|
|
if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
|
|
apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
|
|
}
|
|
|
|
apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
|
|
apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
|
|
|
|
module.Init()
|
|
|
|
return module
|
|
}
|
|
|
|
func (d *apiHeadersDecorator) Name(basename string) string {
|
|
return basename + multitree.GetApiImportSuffix()
|
|
}
|
|
|
|
func (d *apiHeadersDecorator) availableFor(what string) bool {
|
|
// Stub from API surface should be available for any APEX.
|
|
return true
|
|
}
|
|
|
|
func CcApiStubLibraryFactory() android.Module {
|
|
module, decorator := NewLibrary(android.DeviceSupported)
|
|
apiStubDecorator := &apiStubDecorator{
|
|
libraryDecorator: decorator,
|
|
}
|
|
apiStubDecorator.BuildOnlyShared()
|
|
|
|
module.compiler = apiStubDecorator
|
|
module.linker = apiStubDecorator
|
|
module.installer = nil
|
|
module.library = apiStubDecorator
|
|
module.Properties.HideFromMake = true // TODO: remove
|
|
|
|
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
|
|
module.AddProperties(&module.Properties,
|
|
&apiStubDecorator.properties,
|
|
&apiStubDecorator.MutatedProperties,
|
|
&apiStubDecorator.apiStubLibraryProperties)
|
|
return module
|
|
}
|
|
|
|
type apiStubLiraryProperties struct {
|
|
Imported_includes []string `android:"path"`
|
|
}
|
|
|
|
type apiStubDecorator struct {
|
|
*libraryDecorator
|
|
properties libraryProperties
|
|
apiStubLibraryProperties apiStubLiraryProperties
|
|
}
|
|
|
|
func (compiler *apiStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
|
|
firstVersion := String(compiler.properties.First_version)
|
|
return ndkLibraryVersions(ctx, android.ApiLevelOrPanic(ctx, firstVersion))
|
|
}
|
|
|
|
func (decorator *apiStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
|
|
if decorator.stubsVersion() == "" {
|
|
decorator.setStubsVersion("current")
|
|
} // TODO: fix
|
|
symbolFile := String(decorator.properties.Symbol_file)
|
|
nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
|
|
android.ApiLevelOrPanic(ctx, decorator.stubsVersion()),
|
|
"")
|
|
return compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
|
|
}
|
|
|
|
func (decorator *apiStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
|
|
decorator.reexportDirs(android.PathsForModuleSrc(ctx, decorator.apiStubLibraryProperties.Imported_includes)...)
|
|
return decorator.libraryDecorator.link(ctx, flags, deps, objects)
|
|
}
|
|
|
|
func init() {
|
|
pctx.HostBinToolVariable("gen_api_surface_build_files", "gen_api_surface_build_files")
|
|
}
|
|
|
|
type CcApiContribution struct {
|
|
android.ModuleBase
|
|
properties ccApiContributionProperties
|
|
}
|
|
|
|
type ccApiContributionProperties struct {
|
|
Symbol_file *string `android:"path"`
|
|
First_version *string
|
|
Export_include_dir *string
|
|
}
|
|
|
|
func CcApiContributionFactory() android.Module {
|
|
module := &CcApiContribution{}
|
|
module.AddProperties(&module.properties)
|
|
android.InitAndroidModule(module)
|
|
return module
|
|
}
|
|
|
|
// Do some simple validations
|
|
// Majority of the build rules will be created in the ctx of the api surface this module contributes to
|
|
func (contrib *CcApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
if contrib.properties.Symbol_file == nil {
|
|
ctx.PropertyErrorf("symbol_file", "%v does not have symbol file", ctx.ModuleName())
|
|
}
|
|
if contrib.properties.First_version == nil {
|
|
ctx.PropertyErrorf("first_version", "%v does not have first_version for stub variants", ctx.ModuleName())
|
|
}
|
|
}
|
|
|
|
// Path is out/soong/.export/ but will be different in final multi-tree layout
|
|
func outPathApiSurface(ctx android.ModuleContext, myModuleName string, pathComponent string) android.OutputPath {
|
|
return android.PathForOutput(ctx, ".export", ctx.ModuleName(), myModuleName, pathComponent)
|
|
}
|
|
|
|
func (contrib *CcApiContribution) CopyFilesWithTag(apiSurfaceContext android.ModuleContext) map[string]android.Paths {
|
|
// copy map.txt for now
|
|
// hardlinks cannot be created since nsjail creates a different mountpoint for out/
|
|
myDir := apiSurfaceContext.OtherModuleDir(contrib)
|
|
genMapTxt := outPathApiSurface(apiSurfaceContext, contrib.Name(), String(contrib.properties.Symbol_file))
|
|
apiSurfaceContext.Build(pctx, android.BuildParams{
|
|
Rule: android.Cp,
|
|
Description: "import map.txt file",
|
|
Input: android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Symbol_file)),
|
|
Output: genMapTxt,
|
|
})
|
|
|
|
outputs := make(map[string]android.Paths)
|
|
outputs["map"] = []android.Path{genMapTxt}
|
|
|
|
if contrib.properties.Export_include_dir != nil {
|
|
includeDir := android.PathForSource(apiSurfaceContext, myDir, String(contrib.properties.Export_include_dir))
|
|
outputs["export_include_dir"] = []android.Path{includeDir}
|
|
}
|
|
return outputs
|
|
}
|
|
|
|
var _ multitree.ApiContribution = (*CcApiContribution)(nil)
|
|
|
|
/*
|
|
func (contrib *CcApiContribution) GenerateBuildFiles(apiSurfaceContext android.ModuleContext) android.Paths {
|
|
genAndroidBp := outPathApiSurface(apiSurfaceContext, contrib.Name(), "Android.bp")
|
|
|
|
// generate Android.bp
|
|
apiSurfaceContext.Build(pctx, android.BuildParams{
|
|
Rule: genApiSurfaceBuildFiles,
|
|
Description: "generate API surface build files",
|
|
Outputs: []android.WritablePath{genAndroidBp},
|
|
Args: map[string]string{
|
|
"name": contrib.Name() + "." + apiSurfaceContext.ModuleName(), //e.g. liblog.ndk
|
|
"symbol_file": String(contrib.properties.Symbol_file),
|
|
"first_version": String(contrib.properties.First_version),
|
|
},
|
|
})
|
|
return []android.Path{genAndroidBp}
|
|
}
|
|
*/
|