Support cc_library_shared for mixed builds
Authors: cparsons, eakammer, jingwen This CL also contains .toc file integration between Bazel and Make. Fixes: b/190524879 Test: build/bazel/ci/mixed_droid.sh Co-authored-by: Christopher Parsons <cparsons@google.com> Co-authored-by: Liz Kammer <eakammer@google.com> Co-authored-by: Jingwen Chen <jingwen@google.com> Change-Id: If484042a58cb9f0db6d30a460f415f5684b4cbf6
This commit is contained in:
committed by
Jingwen Chen
parent
79e04280ba
commit
94a0bba5a9
@@ -218,11 +218,7 @@ var (
|
|||||||
|
|
||||||
// Per-module denylist to opt modules out of mixed builds. Such modules will
|
// Per-module denylist to opt modules out of mixed builds. Such modules will
|
||||||
// still be generated via bp2build.
|
// still be generated via bp2build.
|
||||||
mixedBuildsDisabledList = []string{
|
mixedBuildsDisabledList = []string{}
|
||||||
"libc", // b/190211183, missing libbionic_Slibdl_Sliblibdl_Ubp2build_Ucc_Ulibrary_Ushared.so
|
|
||||||
"libdl", // b/190211183, missing libbionic_Slinker_Slibld-android_Ubp2build_Ucc_Ulibrary_Ushared.so
|
|
||||||
"libdl_android", // b/190211183, missing libbionic_Slinker_Slibld-android_Ubp2build_Ucc_Ulibrary_Ushared.so
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used for quicker lookups
|
// Used for quicker lookups
|
||||||
bp2buildModuleDoNotConvert = map[string]bool{}
|
bp2buildModuleDoNotConvert = map[string]bool{}
|
||||||
|
@@ -542,10 +542,13 @@ def get_arch(target):
|
|||||||
platform_name = build_options(target)["//command_line_option:platforms"][0].name
|
platform_name = build_options(target)["//command_line_option:platforms"][0].name
|
||||||
if platform_name == "host":
|
if platform_name == "host":
|
||||||
return "HOST"
|
return "HOST"
|
||||||
elif not platform_name.startswith("android_"):
|
elif platform_name.startswith("android_"):
|
||||||
fail("expected platform name of the form 'android_<arch>', but was " + str(platforms))
|
return platform_name[len("android_"):]
|
||||||
|
elif platform_name.startswith("linux_"):
|
||||||
|
return platform_name[len("linux_"):]
|
||||||
|
else:
|
||||||
|
fail("expected platform name of the form 'android_<arch>' or 'linux_<arch>', but was " + str(platforms))
|
||||||
return "UNKNOWN"
|
return "UNKNOWN"
|
||||||
return platform_name[len("android_"):]
|
|
||||||
|
|
||||||
def format(target):
|
def format(target):
|
||||||
id_string = str(target.label) + "|" + get_arch(target)
|
id_string = str(target.label) + "|" + get_arch(target)
|
||||||
@@ -742,8 +745,17 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
|
|||||||
}
|
}
|
||||||
rule := NewRuleBuilder(pctx, ctx)
|
rule := NewRuleBuilder(pctx, ctx)
|
||||||
cmd := rule.Command()
|
cmd := rule.Command()
|
||||||
cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ && %s",
|
|
||||||
ctx.Config().BazelContext.OutputBase(), buildStatement.Command))
|
// cd into Bazel's execution root, which is the action cwd.
|
||||||
|
cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ && ", ctx.Config().BazelContext.OutputBase()))
|
||||||
|
|
||||||
|
for _, pair := range buildStatement.Env {
|
||||||
|
// Set per-action env variables, if any.
|
||||||
|
cmd.Flag(pair.Key + "=" + pair.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The actual Bazel action.
|
||||||
|
cmd.Text(" " + buildStatement.Command)
|
||||||
|
|
||||||
for _, outputPath := range buildStatement.OutputPaths {
|
for _, outputPath := range buildStatement.OutputPaths {
|
||||||
cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
|
cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
|
||||||
|
@@ -20,6 +20,10 @@ type CcInfo struct {
|
|||||||
// be a subset of OutputFiles. (or static libraries, this will be equal to OutputFiles,
|
// be a subset of OutputFiles. (or static libraries, this will be equal to OutputFiles,
|
||||||
// but general cc_library will also have dynamic libraries in output files).
|
// but general cc_library will also have dynamic libraries in output files).
|
||||||
RootStaticArchives []string
|
RootStaticArchives []string
|
||||||
|
// Dynamic libraries (.so files) created by the current target. These will
|
||||||
|
// be a subset of OutputFiles. (or shared libraries, this will be equal to OutputFiles,
|
||||||
|
// but general cc_library will also have dynamic libraries in output files).
|
||||||
|
RootDynamicLibraries []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type getOutputFilesRequestType struct{}
|
type getOutputFilesRequestType struct{}
|
||||||
@@ -86,13 +90,21 @@ for linker_input in linker_inputs:
|
|||||||
if linker_input.owner == target.label:
|
if linker_input.owner == target.label:
|
||||||
rootStaticArchives.append(library.static_library.path)
|
rootStaticArchives.append(library.static_library.path)
|
||||||
|
|
||||||
|
rootDynamicLibraries = []
|
||||||
|
|
||||||
|
if "@rules_cc//examples:experimental_cc_shared_library.bzl%CcSharedLibraryInfo" in providers(target):
|
||||||
|
shared_info = providers(target)["@rules_cc//examples:experimental_cc_shared_library.bzl%CcSharedLibraryInfo"]
|
||||||
|
for lib in shared_info.linker_input.libraries:
|
||||||
|
rootDynamicLibraries += [lib.dynamic_library.path]
|
||||||
|
|
||||||
returns = [
|
returns = [
|
||||||
outputFiles,
|
outputFiles,
|
||||||
staticLibraries,
|
staticLibraries,
|
||||||
ccObjectFiles,
|
ccObjectFiles,
|
||||||
includes,
|
includes,
|
||||||
system_includes,
|
system_includes,
|
||||||
rootStaticArchives
|
rootStaticArchives,
|
||||||
|
rootDynamicLibraries
|
||||||
]
|
]
|
||||||
|
|
||||||
return "|".join([", ".join(r) for r in returns])`
|
return "|".join([", ".join(r) for r in returns])`
|
||||||
@@ -106,7 +118,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
|
|||||||
var ccObjects []string
|
var ccObjects []string
|
||||||
|
|
||||||
splitString := strings.Split(rawString, "|")
|
splitString := strings.Split(rawString, "|")
|
||||||
if expectedLen := 6; len(splitString) != expectedLen {
|
if expectedLen := 7; len(splitString) != expectedLen {
|
||||||
return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
|
return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
|
||||||
}
|
}
|
||||||
outputFilesString := splitString[0]
|
outputFilesString := splitString[0]
|
||||||
@@ -118,6 +130,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
|
|||||||
includes := splitOrEmpty(splitString[3], ", ")
|
includes := splitOrEmpty(splitString[3], ", ")
|
||||||
systemIncludes := splitOrEmpty(splitString[4], ", ")
|
systemIncludes := splitOrEmpty(splitString[4], ", ")
|
||||||
rootStaticArchives := splitOrEmpty(splitString[5], ", ")
|
rootStaticArchives := splitOrEmpty(splitString[5], ", ")
|
||||||
|
rootDynamicLibraries := splitOrEmpty(splitString[6], ", ")
|
||||||
return CcInfo{
|
return CcInfo{
|
||||||
OutputFiles: outputFiles,
|
OutputFiles: outputFiles,
|
||||||
CcObjectFiles: ccObjects,
|
CcObjectFiles: ccObjects,
|
||||||
@@ -125,6 +138,7 @@ func (g getCcInfoType) ParseResult(rawString string) (CcInfo, error) {
|
|||||||
Includes: includes,
|
Includes: includes,
|
||||||
SystemIncludes: systemIncludes,
|
SystemIncludes: systemIncludes,
|
||||||
RootStaticArchives: rootStaticArchives,
|
RootStaticArchives: rootStaticArchives,
|
||||||
|
RootDynamicLibraries: rootDynamicLibraries,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ func TestGetCcInfoParseResults(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
description: "no result",
|
description: "no result",
|
||||||
input: "|||||",
|
input: "||||||",
|
||||||
expectedOutput: CcInfo{
|
expectedOutput: CcInfo{
|
||||||
OutputFiles: []string{},
|
OutputFiles: []string{},
|
||||||
CcObjectFiles: []string{},
|
CcObjectFiles: []string{},
|
||||||
@@ -54,11 +54,12 @@ func TestGetCcInfoParseResults(t *testing.T) {
|
|||||||
Includes: []string{},
|
Includes: []string{},
|
||||||
SystemIncludes: []string{},
|
SystemIncludes: []string{},
|
||||||
RootStaticArchives: []string{},
|
RootStaticArchives: []string{},
|
||||||
|
RootDynamicLibraries: []string{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "only output",
|
description: "only output",
|
||||||
input: "test|||||",
|
input: "test||||||",
|
||||||
expectedOutput: CcInfo{
|
expectedOutput: CcInfo{
|
||||||
OutputFiles: []string{"test"},
|
OutputFiles: []string{"test"},
|
||||||
CcObjectFiles: []string{},
|
CcObjectFiles: []string{},
|
||||||
@@ -66,11 +67,12 @@ func TestGetCcInfoParseResults(t *testing.T) {
|
|||||||
Includes: []string{},
|
Includes: []string{},
|
||||||
SystemIncludes: []string{},
|
SystemIncludes: []string{},
|
||||||
RootStaticArchives: []string{},
|
RootStaticArchives: []string{},
|
||||||
|
RootDynamicLibraries: []string{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "all items set",
|
description: "all items set",
|
||||||
input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1",
|
input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1|rootdynamiclibrary1",
|
||||||
expectedOutput: CcInfo{
|
expectedOutput: CcInfo{
|
||||||
OutputFiles: []string{"out1", "out2"},
|
OutputFiles: []string{"out1", "out2"},
|
||||||
CcObjectFiles: []string{"object1", "object2"},
|
CcObjectFiles: []string{"object1", "object2"},
|
||||||
@@ -78,19 +80,20 @@ func TestGetCcInfoParseResults(t *testing.T) {
|
|||||||
Includes: []string{".", "dir/subdir"},
|
Includes: []string{".", "dir/subdir"},
|
||||||
SystemIncludes: []string{"system/dir", "system/other/dir"},
|
SystemIncludes: []string{"system/dir", "system/other/dir"},
|
||||||
RootStaticArchives: []string{"rootstaticarchive1"},
|
RootStaticArchives: []string{"rootstaticarchive1"},
|
||||||
|
RootDynamicLibraries: []string{"rootdynamiclibrary1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "too few result splits",
|
description: "too few result splits",
|
||||||
input: "|",
|
input: "|",
|
||||||
expectedOutput: CcInfo{},
|
expectedOutput: CcInfo{},
|
||||||
expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 6, []string{"", ""}),
|
expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 7, []string{"", ""}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "too many result splits",
|
description: "too many result splits",
|
||||||
input: strings.Repeat("|", 8),
|
input: strings.Repeat("|", 8),
|
||||||
expectedOutput: CcInfo{},
|
expectedOutput: CcInfo{},
|
||||||
expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 6, make([]string, 9)),
|
expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 7, make([]string, 9)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
43
cc/cc.go
43
cc/cc.go
@@ -1673,10 +1673,6 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
|
|
||||||
c.makeLinkType = GetMakeLinkType(actx, c)
|
c.makeLinkType = GetMakeLinkType(actx, c)
|
||||||
|
|
||||||
if c.maybeGenerateBazelActions(actx) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx := &moduleContext{
|
ctx := &moduleContext{
|
||||||
ModuleContext: actx,
|
ModuleContext: actx,
|
||||||
moduleContextImpl: moduleContextImpl{
|
moduleContextImpl: moduleContextImpl{
|
||||||
@@ -1685,6 +1681,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
ctx.ctx = ctx
|
ctx.ctx = ctx
|
||||||
|
|
||||||
|
if c.maybeGenerateBazelActions(actx) {
|
||||||
|
c.maybeInstall(ctx, apexInfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
deps := c.depsToPaths(ctx)
|
deps := c.depsToPaths(ctx)
|
||||||
if ctx.Failed() {
|
if ctx.Failed() {
|
||||||
return
|
return
|
||||||
@@ -1772,19 +1773,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
c.outputFile = android.OptionalPathForPath(outputFile)
|
c.outputFile = android.OptionalPathForPath(outputFile)
|
||||||
|
|
||||||
// If a lib is directly included in any of the APEXes or is not available to the
|
c.maybeUnhideFromMake()
|
||||||
// platform (which is often the case when the stub is provided as a prebuilt),
|
|
||||||
// unhide the stubs variant having the latest version gets visible to make. In
|
|
||||||
// addition, the non-stubs variant is renamed to <libname>.bootstrap. This is to
|
|
||||||
// force anything in the make world to link against the stubs library. (unless it
|
|
||||||
// is explicitly referenced via .bootstrap suffix or the module is marked with
|
|
||||||
// 'bootstrap: true').
|
|
||||||
if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() &&
|
|
||||||
!c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
|
|
||||||
c.IsStubs() && !c.InVendorRamdisk() {
|
|
||||||
c.Properties.HideFromMake = false // unhide
|
|
||||||
// Note: this is still non-installable
|
|
||||||
}
|
|
||||||
|
|
||||||
// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
|
// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
|
||||||
// RECOVERY_SNAPSHOT_VERSION is current.
|
// RECOVERY_SNAPSHOT_VERSION is current.
|
||||||
@@ -1795,6 +1784,26 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.maybeInstall(ctx, apexInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Module) maybeUnhideFromMake() {
|
||||||
|
// If a lib is directly included in any of the APEXes or is not available to the
|
||||||
|
// platform (which is often the case when the stub is provided as a prebuilt),
|
||||||
|
// unhide the stubs variant having the latest version gets visible to make. In
|
||||||
|
// addition, the non-stubs variant is renamed to <libname>.bootstrap. This is to
|
||||||
|
// force anything in the make world to link against the stubs library. (unless it
|
||||||
|
// is explicitly referenced via .bootstrap suffix or the module is marked with
|
||||||
|
// 'bootstrap: true').
|
||||||
|
if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() &&
|
||||||
|
!c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
|
||||||
|
c.IsStubs() && !c.InVendorRamdisk() {
|
||||||
|
c.Properties.HideFromMake = false // unhide
|
||||||
|
// Note: this is still non-installable
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Module) maybeInstall(ctx ModuleContext, apexInfo android.ApexInfo) {
|
||||||
if !proptools.BoolDefault(c.Properties.Installable, true) {
|
if !proptools.BoolDefault(c.Properties.Installable, true) {
|
||||||
// If the module has been specifically configure to not be installed then
|
// If the module has been specifically configure to not be installed then
|
||||||
// hide from make as otherwise it will break when running inside make
|
// hide from make as otherwise it will break when running inside make
|
||||||
|
112
cc/library.go
112
cc/library.go
@@ -28,6 +28,7 @@ import (
|
|||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
"android/soong/bazel"
|
"android/soong/bazel"
|
||||||
|
"android/soong/bazel/cquery"
|
||||||
"android/soong/cc/config"
|
"android/soong/cc/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -579,22 +580,10 @@ type ccLibraryBazelHandler struct {
|
|||||||
module *Module
|
module *Module
|
||||||
}
|
}
|
||||||
|
|
||||||
func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
|
// generateStaticBazelBuildActions constructs the StaticLibraryInfo Soong
|
||||||
if !handler.module.static() {
|
// provider from a Bazel shared library's CcInfo provider.
|
||||||
// TODO(cparsons): Support shared libraries.
|
func (handler *ccLibraryBazelHandler) generateStaticBazelBuildActions(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) bool {
|
||||||
return false
|
|
||||||
}
|
|
||||||
bazelCtx := ctx.Config().BazelContext
|
|
||||||
ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
|
|
||||||
if err != nil {
|
|
||||||
ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !ok {
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
rootStaticArchives := ccInfo.RootStaticArchives
|
rootStaticArchives := ccInfo.RootStaticArchives
|
||||||
objPaths := ccInfo.CcObjectFiles
|
|
||||||
if len(rootStaticArchives) != 1 {
|
if len(rootStaticArchives) != 1 {
|
||||||
ctx.ModuleErrorf("expected exactly one root archive file for '%s', but got %s", label, rootStaticArchives)
|
ctx.ModuleErrorf("expected exactly one root archive file for '%s', but got %s", label, rootStaticArchives)
|
||||||
return false
|
return false
|
||||||
@@ -602,6 +591,7 @@ func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.Modu
|
|||||||
outputFilePath := android.PathForBazelOut(ctx, rootStaticArchives[0])
|
outputFilePath := android.PathForBazelOut(ctx, rootStaticArchives[0])
|
||||||
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
||||||
|
|
||||||
|
objPaths := ccInfo.CcObjectFiles
|
||||||
objFiles := make(android.Paths, len(objPaths))
|
objFiles := make(android.Paths, len(objPaths))
|
||||||
for i, objPath := range objPaths {
|
for i, objPath := range objPaths {
|
||||||
objFiles[i] = android.PathForBazelOut(ctx, objPath)
|
objFiles[i] = android.PathForBazelOut(ctx, objPath)
|
||||||
@@ -615,26 +605,110 @@ func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.Modu
|
|||||||
ReuseObjects: objects,
|
ReuseObjects: objects,
|
||||||
Objects: objects,
|
Objects: objects,
|
||||||
|
|
||||||
// TODO(cparsons): Include transitive static libraries in this provider to support
|
// TODO(b/190524881): Include transitive static libraries in this provider to support
|
||||||
// static libraries with deps.
|
// static libraries with deps.
|
||||||
TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
|
TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
|
||||||
Direct(outputFilePath).
|
Direct(outputFilePath).
|
||||||
Build(),
|
Build(),
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfoFromCcInfo(ctx, ccInfo))
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateSharedBazelBuildActions constructs the SharedLibraryInfo Soong
|
||||||
|
// provider from a Bazel shared library's CcInfo provider.
|
||||||
|
func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) bool {
|
||||||
|
rootDynamicLibraries := ccInfo.RootDynamicLibraries
|
||||||
|
|
||||||
|
if len(rootDynamicLibraries) != 1 {
|
||||||
|
ctx.ModuleErrorf("expected exactly one root dynamic library file for '%s', but got %s", label, rootDynamicLibraries)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
outputFilePath := android.PathForBazelOut(ctx, rootDynamicLibraries[0])
|
||||||
|
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
||||||
|
|
||||||
|
handler.module.linker.(*libraryDecorator).unstrippedOutputFile = outputFilePath
|
||||||
|
|
||||||
|
tocFile := getTocFile(ctx, label, ccInfo.OutputFiles)
|
||||||
|
handler.module.linker.(*libraryDecorator).tocFile = tocFile
|
||||||
|
|
||||||
|
ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
|
||||||
|
TableOfContents: tocFile,
|
||||||
|
SharedLibrary: outputFilePath,
|
||||||
|
// TODO(b/190524881): Include transitive static libraries in this provider to support
|
||||||
|
// static libraries with deps.
|
||||||
|
//TransitiveStaticLibrariesForOrdering
|
||||||
|
Target: ctx.Target(),
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// getTocFile looks for the .so.toc file in the target's output files, if any. The .so.toc file
|
||||||
|
// contains the table of contents of all symbols of a shared object.
|
||||||
|
func getTocFile(ctx android.ModuleContext, label string, outputFiles []string) android.OptionalPath {
|
||||||
|
var tocFile string
|
||||||
|
for _, file := range outputFiles {
|
||||||
|
if strings.HasSuffix(file, ".so.toc") {
|
||||||
|
if tocFile != "" {
|
||||||
|
ctx.ModuleErrorf("The %s target cannot produce more than 1 .toc file.", label)
|
||||||
|
}
|
||||||
|
tocFile = file
|
||||||
|
// Don't break to validate that there are no multiple .toc files per .so.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tocFile == "" {
|
||||||
|
return android.OptionalPath{}
|
||||||
|
}
|
||||||
|
return android.OptionalPathForPath(android.PathForBazelOut(ctx, tocFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
|
||||||
|
bazelCtx := ctx.Config().BazelContext
|
||||||
|
ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
|
||||||
|
if err != nil {
|
||||||
|
ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
if handler.module.static() {
|
||||||
|
if ok := handler.generateStaticBazelBuildActions(ctx, label, ccInfo); !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else if handler.module.Shared() {
|
||||||
|
if ok := handler.generateSharedBazelBuildActions(ctx, label, ccInfo); !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
handler.module.linker.(*libraryDecorator).setFlagExporterInfoFromCcInfo(ctx, ccInfo)
|
||||||
|
handler.module.maybeUnhideFromMake()
|
||||||
|
|
||||||
if i, ok := handler.module.linker.(snapshotLibraryInterface); ok {
|
if i, ok := handler.module.linker.(snapshotLibraryInterface); ok {
|
||||||
// Dependencies on this library will expect collectedSnapshotHeaders to
|
// Dependencies on this library will expect collectedSnapshotHeaders to
|
||||||
// be set, otherwise validation will fail. For now, set this to an empty
|
// be set, otherwise validation will fail. For now, set this to an empty
|
||||||
// list.
|
// list.
|
||||||
// TODO(cparsons): More closely mirror the collectHeadersForSnapshot
|
// TODO(b/190533363): More closely mirror the collectHeadersForSnapshot
|
||||||
// implementation.
|
// implementation.
|
||||||
i.(*libraryDecorator).collectedSnapshotHeaders = android.Paths{}
|
i.(*libraryDecorator).collectedSnapshotHeaders = android.Paths{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (library *libraryDecorator) setFlagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) {
|
||||||
|
flagExporterInfo := flagExporterInfoFromCcInfo(ctx, ccInfo)
|
||||||
|
// flag exporters consolidates properties like includes, flags, dependencies that should be
|
||||||
|
// exported from this module to other modules
|
||||||
|
ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfo)
|
||||||
|
// Store flag info to be passed along to androidmk
|
||||||
|
// TODO(b/184387147): Androidmk should be done in Bazel, not Soong.
|
||||||
|
library.flagExporterInfo = &flagExporterInfo
|
||||||
|
}
|
||||||
|
|
||||||
func GlobHeadersForSnapshot(ctx android.ModuleContext, paths android.Paths) android.Paths {
|
func GlobHeadersForSnapshot(ctx android.ModuleContext, paths android.Paths) android.Paths {
|
||||||
ret := android.Paths{}
|
ret := android.Paths{}
|
||||||
|
|
||||||
|
@@ -73,13 +73,7 @@ func (h *libraryHeaderBazelHander) generateBazelBuildActions(ctx android.ModuleC
|
|||||||
// HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library
|
// HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library
|
||||||
ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
|
ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
|
||||||
|
|
||||||
flagExporterInfo := flagExporterInfoFromCcInfo(ctx, ccInfo)
|
h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
|
||||||
// Store flag info to be passed along to androimk
|
|
||||||
// TODO(b/184387147): Androidmk should be done in Bazel, not Soong.
|
|
||||||
h.library.flagExporterInfo = &flagExporterInfo
|
|
||||||
// flag exporters consolidates properties like includes, flags, dependencies that should be
|
|
||||||
// exported from this module to other modules
|
|
||||||
ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfo)
|
|
||||||
|
|
||||||
// Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
|
// Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
|
||||||
// validation will fail. For now, set this to an empty list.
|
// validation will fail. For now, set this to an empty list.
|
||||||
|
@@ -19,6 +19,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"android/soong/bazel/cquery"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLibraryReuse(t *testing.T) {
|
func TestLibraryReuse(t *testing.T) {
|
||||||
@@ -240,3 +241,48 @@ func TestStubsVersions_ParseError(t *testing.T) {
|
|||||||
|
|
||||||
testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp)
|
testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCcLibraryWithBazel(t *testing.T) {
|
||||||
|
bp := `
|
||||||
|
cc_library {
|
||||||
|
name: "foo",
|
||||||
|
srcs: ["foo.cc"],
|
||||||
|
bazel_module: { label: "//foo/bar:bar" },
|
||||||
|
}`
|
||||||
|
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
|
||||||
|
config.BazelContext = android.MockBazelContext{
|
||||||
|
OutputBaseDir: "outputbase",
|
||||||
|
LabelToCcInfo: map[string]cquery.CcInfo{
|
||||||
|
"//foo/bar:bar": cquery.CcInfo{
|
||||||
|
CcObjectFiles: []string{"foo.o"},
|
||||||
|
Includes: []string{"include"},
|
||||||
|
SystemIncludes: []string{"system_include"},
|
||||||
|
RootStaticArchives: []string{"foo.a"},
|
||||||
|
RootDynamicLibraries: []string{"foo.so"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctx := testCcWithConfig(t, config)
|
||||||
|
|
||||||
|
staticFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
|
||||||
|
outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.a"}
|
||||||
|
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
|
||||||
|
|
||||||
|
sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
|
||||||
|
outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
|
||||||
|
}
|
||||||
|
expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
|
||||||
|
android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
|
||||||
|
|
||||||
|
entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0]
|
||||||
|
expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"}
|
||||||
|
gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"]
|
||||||
|
android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags)
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user