cc/rust: Alias ffi rlib variant for static_libs

Alias the rlib variant to "link: static". This allows declaring
rust_ffi_rlib modules in static_libs. This effectively removes any
distinction between rust_ffi_static and rust_ffi_rlib. Removing the
functionality for building Rust staticlib modules will be cleaned up in
a follow-on CL.

This should have the effect of changing the default linkage for all rust
modules in static_libs from linking individual staticlibs to building a
single staticlib that includes all rust_ffi rlib dependencies.

This removes the static_rlibs property, as we're now handling
the choice dynamically. This also makes rlibs only propagate through
cc_library_static modules if the rlib is included in
whole_static_lib. This both mirrors the expected behavior of
cc libraries and helps control which version of a crate ends up in the
final link (e.g. libdoh_ffi vs libdoh_ffi_for_test).

Bug: 254469782
Test: m
Test: m blueprint_tests
Change-Id: I2925f67f6dc9329dae3dcccafb8560900ac8a6fc
This commit is contained in:
Ivan Lozano
2024-05-17 14:13:41 -04:00
parent 9c067f62d0
commit fd47b1ab6a
15 changed files with 255 additions and 233 deletions

177
cc/cc.go
View File

@@ -99,7 +99,6 @@ type Deps struct {
StaticLibs, LateStaticLibs, WholeStaticLibs []string
HeaderLibs []string
RuntimeLibs []string
Rlibs []string
// UnexportedStaticLibs are static libraries that are also passed to -Wl,--exclude-libs= to
// prevent automatically exporting symbols.
@@ -746,11 +745,6 @@ func (d libraryDependencyTag) static() bool {
return d.Kind == staticLibraryDependency
}
// rlib returns true if the libraryDependencyTag is tagging an rlib dependency.
func (d libraryDependencyTag) rlib() bool {
return d.Kind == rlibLibraryDependency
}
func (d libraryDependencyTag) LicenseAnnotations() []android.LicenseAnnotation {
if d.shared() {
return []android.LicenseAnnotation{android.LicenseAnnotationSharedDependency}
@@ -917,6 +911,8 @@ type Module struct {
hideApexVariantFromMake bool
logtagsPaths android.Paths
WholeRustStaticlib bool
}
func (c *Module) AddJSONData(d *map[string]interface{}) {
@@ -1192,6 +1188,16 @@ func (c *Module) BuildSharedVariant() bool {
panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", c.BaseModuleName()))
}
func (c *Module) BuildRlibVariant() bool {
// cc modules can never build rlib variants
return false
}
func (c *Module) IsRustFFI() bool {
// cc modules are not Rust modules
return false
}
func (c *Module) Module() android.Module {
return c
}
@@ -2267,7 +2273,6 @@ func (c *Module) deps(ctx DepsContext) Deps {
deps.WholeStaticLibs = android.LastUniqueStrings(deps.WholeStaticLibs)
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
deps.LateStaticLibs = android.LastUniqueStrings(deps.LateStaticLibs)
deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
deps.LateSharedLibs = android.LastUniqueStrings(deps.LateSharedLibs)
@@ -2562,28 +2567,20 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
}
for _, lib := range deps.StaticLibs {
// Some dependencies listed in static_libs might actually be rust_ffi rlib variants.
depTag := libraryDependencyTag{Kind: staticLibraryDependency}
if inList(lib, deps.ReexportStaticLibHeaders) {
depTag.reexportFlags = true
}
if inList(lib, deps.ExcludeLibsForApex) {
depTag.excludeInApex = true
}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
}, depTag, lib)
}
for _, lib := range deps.Rlibs {
depTag := libraryDependencyTag{Kind: rlibLibraryDependency}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: ""},
{Mutator: "rust_libraries", Variation: "rlib"},
{Mutator: "rust_stdlinkage", Variation: "rlib-std"},
}, depTag, lib)
}
// staticUnwinderDep is treated as staticDep for Q apexes
// so that native libraries/binaries are linked with static unwinder
// because Q libc doesn't have unwinder APIs
@@ -3171,78 +3168,86 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
}
case libDepTag.rlib():
rlibDep := RustRlibDep{LibPath: linkFile.Path(), CrateName: ccDep.CrateName(), LinkDirs: ccDep.ExportedCrateLinkDirs()}
depPaths.ReexportedRustRlibDeps = append(depPaths.ReexportedRustRlibDeps, rlibDep)
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, rlibDep)
depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...)
depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, depExporterInfo.IncludeDirs...)
case libDepTag.static():
staticLibraryInfo, isStaticLib := android.OtherModuleProvider(ctx, dep, StaticLibraryInfoProvider)
if !isStaticLib {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("module %q is not a static library", depName)
} else {
ctx.AddMissingDependencies([]string{depName})
}
return
}
if ccDep.RustLibraryInterface() {
rlibDep := RustRlibDep{LibPath: linkFile.Path(), CrateName: ccDep.CrateName(), LinkDirs: ccDep.ExportedCrateLinkDirs()}
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, rlibDep)
depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...)
if libDepTag.wholeStatic {
depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, depExporterInfo.IncludeDirs...)
depPaths.ReexportedRustRlibDeps = append(depPaths.ReexportedRustRlibDeps, rlibDep)
// Stubs lib doesn't link to the static lib dependencies. Don't set
// linkFile, depFile, and ptr.
if c.IsStubs() {
break
}
linkFile = android.OptionalPathForPath(staticLibraryInfo.StaticLibrary)
if libDepTag.wholeStatic {
ptr = &depPaths.WholeStaticLibs
if len(staticLibraryInfo.Objects.objFiles) > 0 {
depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLibraryInfo.Objects)
} else {
// This case normally catches prebuilt static
// libraries, but it can also occur when
// AllowMissingDependencies is on and the
// dependencies has no sources of its own
// but has a whole_static_libs dependency
// on a missing library. We want to depend
// on the .a file so that there is something
// in the dependency tree that contains the
// error rule for the missing transitive
// dependency.
depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
// If whole_static, track this as we want to make sure that in a final linkage for a shared library,
// exported functions from the rust generated staticlib still exported.
if c.CcLibrary() && c.Shared() {
c.WholeRustStaticlib = true
}
}
depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts,
staticLibraryInfo.WholeStaticLibsFromPrebuilts...)
} else {
switch libDepTag.Order {
case earlyLibraryDependency:
panic(fmt.Errorf("early static libs not suppported"))
case normalLibraryDependency:
// static dependencies will be handled separately so they can be ordered
// using transitive dependencies.
ptr = nil
directStaticDeps = append(directStaticDeps, staticLibraryInfo)
case lateLibraryDependency:
ptr = &depPaths.LateStaticLibs
default:
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
staticLibraryInfo, isStaticLib := android.OtherModuleProvider(ctx, dep, StaticLibraryInfoProvider)
if !isStaticLib {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("module %q is not a static library", depName)
} else {
ctx.AddMissingDependencies([]string{depName})
}
return
}
}
// We re-export the Rust static_rlibs so rlib dependencies don't need to be redeclared by cc_library_static dependents.
// E.g. libfoo (cc_library_static) depends on libfoo.ffi (a rust_ffi rlib), libbar depending on libfoo shouldn't have to also add libfoo.ffi to static_rlibs.
depPaths.ReexportedRustRlibDeps = append(depPaths.ReexportedRustRlibDeps, depExporterInfo.RustRlibDeps...)
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, depExporterInfo.RustRlibDeps...)
// Stubs lib doesn't link to the static lib dependencies. Don't set
// linkFile, depFile, and ptr.
if c.IsStubs() {
break
}
if libDepTag.unexportedSymbols {
depPaths.LdFlags = append(depPaths.LdFlags,
"-Wl,--exclude-libs="+staticLibraryInfo.StaticLibrary.Base())
linkFile = android.OptionalPathForPath(staticLibraryInfo.StaticLibrary)
if libDepTag.wholeStatic {
ptr = &depPaths.WholeStaticLibs
if len(staticLibraryInfo.Objects.objFiles) > 0 {
depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLibraryInfo.Objects)
} else {
// This case normally catches prebuilt static
// libraries, but it can also occur when
// AllowMissingDependencies is on and the
// dependencies has no sources of its own
// but has a whole_static_libs dependency
// on a missing library. We want to depend
// on the .a file so that there is something
// in the dependency tree that contains the
// error rule for the missing transitive
// dependency.
depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts, linkFile.Path())
}
depPaths.WholeStaticLibsFromPrebuilts = append(depPaths.WholeStaticLibsFromPrebuilts,
staticLibraryInfo.WholeStaticLibsFromPrebuilts...)
} else {
switch libDepTag.Order {
case earlyLibraryDependency:
panic(fmt.Errorf("early static libs not supported"))
case normalLibraryDependency:
// static dependencies will be handled separately so they can be ordered
// using transitive dependencies.
ptr = nil
directStaticDeps = append(directStaticDeps, staticLibraryInfo)
case lateLibraryDependency:
ptr = &depPaths.LateStaticLibs
default:
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
}
}
// Collect any exported Rust rlib deps from static libraries which have been included as whole_static_libs
depPaths.RustRlibDeps = append(depPaths.RustRlibDeps, depExporterInfo.RustRlibDeps...)
if libDepTag.unexportedSymbols {
depPaths.LdFlags = append(depPaths.LdFlags,
"-Wl,--exclude-libs="+staticLibraryInfo.StaticLibrary.Base())
}
}
}
if libDepTag.static() && !libDepTag.wholeStatic {
if libDepTag.static() && !libDepTag.wholeStatic && !ccDep.RustLibraryInterface() {
if !ccDep.CcLibraryInterface() || !ccDep.Static() {
ctx.ModuleErrorf("module %q not a static library", depName)
return
@@ -3329,12 +3334,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
c.Properties.AndroidMkSharedLibs = append(
c.Properties.AndroidMkSharedLibs, makeLibName)
case libDepTag.static():
if libDepTag.wholeStatic {
c.Properties.AndroidMkWholeStaticLibs = append(
c.Properties.AndroidMkWholeStaticLibs, makeLibName)
} else {
c.Properties.AndroidMkStaticLibs = append(
c.Properties.AndroidMkStaticLibs, makeLibName)
if !ccDep.RustLibraryInterface() {
if libDepTag.wholeStatic {
c.Properties.AndroidMkWholeStaticLibs = append(
c.Properties.AndroidMkWholeStaticLibs, makeLibName)
} else {
c.Properties.AndroidMkStaticLibs = append(
c.Properties.AndroidMkStaticLibs, makeLibName)
}
}
}
} else if !c.IsStubs() {