Support cc_library_shared for mixed builds am: 94a0bba5a9
am: e6819aa944
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1727935 Change-Id: I30b6643b74dfb74b4dd7a118b1c392ec7a62aa74
This commit is contained in:
43
cc/cc.go
43
cc/cc.go
@@ -1673,10 +1673,6 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
|
||||
c.makeLinkType = GetMakeLinkType(actx, c)
|
||||
|
||||
if c.maybeGenerateBazelActions(actx) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := &moduleContext{
|
||||
ModuleContext: actx,
|
||||
moduleContextImpl: moduleContextImpl{
|
||||
@@ -1685,6 +1681,11 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
}
|
||||
ctx.ctx = ctx
|
||||
|
||||
if c.maybeGenerateBazelActions(actx) {
|
||||
c.maybeInstall(ctx, apexInfo)
|
||||
return
|
||||
}
|
||||
|
||||
deps := c.depsToPaths(ctx)
|
||||
if ctx.Failed() {
|
||||
return
|
||||
@@ -1772,19 +1773,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
}
|
||||
c.outputFile = android.OptionalPathForPath(outputFile)
|
||||
|
||||
// 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
|
||||
}
|
||||
c.maybeUnhideFromMake()
|
||||
|
||||
// glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
|
||||
// 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 the module has been specifically configure to not be installed then
|
||||
// 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/bazel"
|
||||
"android/soong/bazel/cquery"
|
||||
"android/soong/cc/config"
|
||||
)
|
||||
|
||||
@@ -579,22 +580,10 @@ type ccLibraryBazelHandler struct {
|
||||
module *Module
|
||||
}
|
||||
|
||||
func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
|
||||
if !handler.module.static() {
|
||||
// TODO(cparsons): Support shared libraries.
|
||||
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
|
||||
}
|
||||
// generateStaticBazelBuildActions constructs the StaticLibraryInfo Soong
|
||||
// provider from a Bazel shared library's CcInfo provider.
|
||||
func (handler *ccLibraryBazelHandler) generateStaticBazelBuildActions(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) bool {
|
||||
rootStaticArchives := ccInfo.RootStaticArchives
|
||||
objPaths := ccInfo.CcObjectFiles
|
||||
if len(rootStaticArchives) != 1 {
|
||||
ctx.ModuleErrorf("expected exactly one root archive file for '%s', but got %s", label, rootStaticArchives)
|
||||
return false
|
||||
@@ -602,6 +591,7 @@ func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.Modu
|
||||
outputFilePath := android.PathForBazelOut(ctx, rootStaticArchives[0])
|
||||
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
|
||||
|
||||
objPaths := ccInfo.CcObjectFiles
|
||||
objFiles := make(android.Paths, len(objPaths))
|
||||
for i, objPath := range objPaths {
|
||||
objFiles[i] = android.PathForBazelOut(ctx, objPath)
|
||||
@@ -615,26 +605,110 @@ func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.Modu
|
||||
ReuseObjects: 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.
|
||||
TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL).
|
||||
Direct(outputFilePath).
|
||||
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 {
|
||||
// Dependencies on this library will expect collectedSnapshotHeaders to
|
||||
// be set, otherwise validation will fail. For now, set this to an empty
|
||||
// list.
|
||||
// TODO(cparsons): More closely mirror the collectHeadersForSnapshot
|
||||
// TODO(b/190533363): More closely mirror the collectHeadersForSnapshot
|
||||
// implementation.
|
||||
i.(*libraryDecorator).collectedSnapshotHeaders = android.Paths{}
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
|
||||
|
||||
flagExporterInfo := flagExporterInfoFromCcInfo(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)
|
||||
h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
|
||||
|
||||
// Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
|
||||
// validation will fail. For now, set this to an empty list.
|
||||
|
@@ -19,6 +19,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"android/soong/android"
|
||||
"android/soong/bazel/cquery"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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