diff --git a/Android.bp b/Android.bp index 714ce372e..05972fd36 100644 --- a/Android.bp +++ b/Android.bp @@ -157,6 +157,7 @@ bootstrap_go_package { "cc/check.go", "cc/coverage.go", "cc/gen.go", + "cc/linkable.go", "cc/lto.go", "cc/makevars.go", "cc/pgo.go", diff --git a/cc/androidmk.go b/cc/androidmk.go index f278d6f41..54cd722f4 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -36,10 +36,10 @@ type AndroidMkContext interface { Arch() android.Arch Os() android.OsType Host() bool - useVndk() bool + UseVndk() bool vndkVersion() string static() bool - inRecovery() bool + InRecovery() bool } type subAndroidMkProvider interface { @@ -89,9 +89,9 @@ func (c *Module) AndroidMk() android.AndroidMkData { fmt.Fprintln(w, "LOCAL_WHOLE_STATIC_LIBRARIES := "+strings.Join(c.Properties.AndroidMkWholeStaticLibs, " ")) } fmt.Fprintln(w, "LOCAL_SOONG_LINK_TYPE :=", c.makeLinkType) - if c.useVndk() { + if c.UseVndk() { fmt.Fprintln(w, "LOCAL_USE_VNDK := true") - if c.isVndk() && !c.static() { + if c.IsVndk() && !c.static() { fmt.Fprintln(w, "LOCAL_SOONG_VNDK_VERSION := "+c.vndkVersion()) } } @@ -224,7 +224,7 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An }) } if len(library.Properties.Stubs.Versions) > 0 && - android.DirectlyInAnyApex(ctx, ctx.Name()) && !ctx.inRecovery() && !ctx.useVndk() && + android.DirectlyInAnyApex(ctx, ctx.Name()) && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() { if !library.buildStubs() { ret.SubName = ".bootstrap" diff --git a/cc/cc.go b/cc/cc.go index 67132e4f0..f90f1e84c 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -338,81 +338,50 @@ type installer interface { relativeInstallPath() string } -type dependencyTag struct { - blueprint.BaseDependencyTag - name string - library bool - shared bool - - reexportFlags bool - - explicitlyVersioned bool -} - type xref interface { XrefCcFiles() android.Paths } var ( - sharedDepTag = dependencyTag{name: "shared", library: true, shared: true} - sharedExportDepTag = dependencyTag{name: "shared", library: true, shared: true, reexportFlags: true} - earlySharedDepTag = dependencyTag{name: "early_shared", library: true, shared: true} - lateSharedDepTag = dependencyTag{name: "late shared", library: true, shared: true} - staticDepTag = dependencyTag{name: "static", library: true} - staticExportDepTag = dependencyTag{name: "static", library: true, reexportFlags: true} - lateStaticDepTag = dependencyTag{name: "late static", library: true} - wholeStaticDepTag = dependencyTag{name: "whole static", library: true, reexportFlags: true} - headerDepTag = dependencyTag{name: "header", library: true} - headerExportDepTag = dependencyTag{name: "header", library: true, reexportFlags: true} - genSourceDepTag = dependencyTag{name: "gen source"} - genHeaderDepTag = dependencyTag{name: "gen header"} - genHeaderExportDepTag = dependencyTag{name: "gen header", reexportFlags: true} - objDepTag = dependencyTag{name: "obj"} - crtBeginDepTag = dependencyTag{name: "crtbegin"} - crtEndDepTag = dependencyTag{name: "crtend"} - linkerFlagsDepTag = dependencyTag{name: "linker flags file"} - dynamicLinkerDepTag = dependencyTag{name: "dynamic linker"} - reuseObjTag = dependencyTag{name: "reuse objects"} - staticVariantTag = dependencyTag{name: "static variant"} - ndkStubDepTag = dependencyTag{name: "ndk stub", library: true} - ndkLateStubDepTag = dependencyTag{name: "ndk late stub", library: true} - vndkExtDepTag = dependencyTag{name: "vndk extends", library: true} - runtimeDepTag = dependencyTag{name: "runtime lib"} - coverageDepTag = dependencyTag{name: "coverage"} - testPerSrcDepTag = dependencyTag{name: "test_per_src"} + sharedExportDepTag = DependencyTag{Name: "shared", Library: true, Shared: true, ReexportFlags: true} + earlySharedDepTag = DependencyTag{Name: "early_shared", Library: true, Shared: true} + lateSharedDepTag = DependencyTag{Name: "late shared", Library: true, Shared: true} + staticExportDepTag = DependencyTag{Name: "static", Library: true, ReexportFlags: true} + lateStaticDepTag = DependencyTag{Name: "late static", Library: true} + wholeStaticDepTag = DependencyTag{Name: "whole static", Library: true, ReexportFlags: true} + headerDepTag = DependencyTag{Name: "header", Library: true} + headerExportDepTag = DependencyTag{Name: "header", Library: true, ReexportFlags: true} + genSourceDepTag = DependencyTag{Name: "gen source"} + genHeaderDepTag = DependencyTag{Name: "gen header"} + genHeaderExportDepTag = DependencyTag{Name: "gen header", ReexportFlags: true} + objDepTag = DependencyTag{Name: "obj"} + linkerFlagsDepTag = DependencyTag{Name: "linker flags file"} + dynamicLinkerDepTag = DependencyTag{Name: "dynamic linker"} + reuseObjTag = DependencyTag{Name: "reuse objects"} + staticVariantTag = DependencyTag{Name: "static variant"} + ndkStubDepTag = DependencyTag{Name: "ndk stub", Library: true} + ndkLateStubDepTag = DependencyTag{Name: "ndk late stub", Library: true} + vndkExtDepTag = DependencyTag{Name: "vndk extends", Library: true} + runtimeDepTag = DependencyTag{Name: "runtime lib"} + coverageDepTag = DependencyTag{Name: "coverage"} + testPerSrcDepTag = DependencyTag{Name: "test_per_src"} ) func IsSharedDepTag(depTag blueprint.DependencyTag) bool { - ccDepTag, ok := depTag.(dependencyTag) - return ok && ccDepTag.shared + ccDepTag, ok := depTag.(DependencyTag) + return ok && ccDepTag.Shared } func IsRuntimeDepTag(depTag blueprint.DependencyTag) bool { - ccDepTag, ok := depTag.(dependencyTag) + ccDepTag, ok := depTag.(DependencyTag) return ok && ccDepTag == runtimeDepTag } func IsTestPerSrcDepTag(depTag blueprint.DependencyTag) bool { - ccDepTag, ok := depTag.(dependencyTag) + ccDepTag, ok := depTag.(DependencyTag) return ok && ccDepTag == testPerSrcDepTag } -func SharedDepTag() dependencyTag { - return sharedDepTag -} - -func StaticDepTag() dependencyTag { - return staticDepTag -} - -func CrtBeginDepTag() dependencyTag { - return crtBeginDepTag -} - -func CrtEndDepTag() dependencyTag { - return crtEndDepTag -} - // Module contains the properties and members used by all C/C++ module types, and implements // the blueprint.Module interface. It delegates to compiler, linker, and installer interfaces // to construct the output file. Behavior can be customized with a Customizer interface @@ -460,17 +429,212 @@ type Module struct { depsInLinkOrder android.Paths // only non-nil when this is a shared library that reuses the objects of a static library - staticVariant *Module + staticVariant LinkableInterface makeLinkType string // Kythe (source file indexer) paths for this compilation module kytheFiles android.Paths } +func (c *Module) Toc() android.OptionalPath { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + return library.toc() + } + } + panic(fmt.Errorf("Toc() called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) ApiLevel() string { + if c.linker != nil { + if stub, ok := c.linker.(*stubDecorator); ok { + return stub.properties.ApiLevel + } + } + panic(fmt.Errorf("ApiLevel() called on non-stub library module: %q", c.BaseModuleName())) +} + +func (c *Module) Static() bool { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + return library.static() + } + } + panic(fmt.Errorf("Static() called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) Shared() bool { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + return library.shared() + } + } + panic(fmt.Errorf("Shared() called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) SelectedStl() string { + return c.stl.Properties.SelectedStl +} + +func (c *Module) ToolchainLibrary() bool { + if _, ok := c.linker.(*toolchainLibraryDecorator); ok { + return true + } + return false +} + +func (c *Module) NdkPrebuiltStl() bool { + if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok { + return true + } + return false +} + +func (c *Module) StubDecorator() bool { + if _, ok := c.linker.(*stubDecorator); ok { + return true + } + return false +} + +func (c *Module) SdkVersion() string { + return String(c.Properties.Sdk_version) +} + +func (c *Module) IncludeDirs(ctx android.BaseModuleContext) android.Paths { + if c.linker != nil { + if library, ok := c.linker.(exportedFlagsProducer); ok { + return library.exportedDirs() + } + } + panic(fmt.Errorf("IncludeDirs called on non-exportedFlagsProducer module: %q", c.BaseModuleName())) +} + +func (c *Module) HasStaticVariant() bool { + if c.staticVariant != nil { + return true + } + return false +} + +func (c *Module) GetStaticVariant() LinkableInterface { + return c.staticVariant +} + +func (c *Module) SetDepsInLinkOrder(depsInLinkOrder []android.Path) { + c.depsInLinkOrder = depsInLinkOrder +} + +func (c *Module) GetDepsInLinkOrder() []android.Path { + return c.depsInLinkOrder +} + +func (c *Module) StubsVersions() []string { + if c.linker != nil { + if library, ok := c.linker.(*libraryDecorator); ok { + return library.Properties.Stubs.Versions + } + } + panic(fmt.Errorf("StubsVersions called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) CcLibrary() bool { + if c.linker != nil { + if _, ok := c.linker.(*libraryDecorator); ok { + return true + } + } + return false +} + +func (c *Module) CcLibraryInterface() bool { + if _, ok := c.linker.(libraryInterface); ok { + return true + } + return false +} + +func (c *Module) SetBuildStubs() { + if c.linker != nil { + if library, ok := c.linker.(*libraryDecorator); ok { + library.MutatedProperties.BuildStubs = true + c.Properties.HideFromMake = true + c.sanitize = nil + c.stl = nil + c.Properties.PreventInstall = true + return + } + } + panic(fmt.Errorf("SetBuildStubs called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) BuildStubs() bool { + if c.linker != nil { + if library, ok := c.linker.(*libraryDecorator); ok { + return library.buildStubs() + } + } + panic(fmt.Errorf("BuildStubs called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) SetStubsVersions(version string) { + if c.linker != nil { + if library, ok := c.linker.(*libraryDecorator); ok { + library.MutatedProperties.StubsVersion = version + return + } + } + panic(fmt.Errorf("SetStubsVersions called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) SetStatic() { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + library.setStatic() + return + } + } + panic(fmt.Errorf("SetStatic called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) SetShared() { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + library.setShared() + return + } + } + panic(fmt.Errorf("SetShared called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) BuildStaticVariant() bool { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + return library.buildStatic() + } + } + panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) BuildSharedVariant() bool { + if c.linker != nil { + if library, ok := c.linker.(libraryInterface); ok { + return library.buildShared() + } + } + panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", c.BaseModuleName())) +} + +func (c *Module) Module() android.Module { + return c +} + func (c *Module) OutputFile() android.OptionalPath { return c.outputFile } +var _ LinkableInterface = (*Module)(nil) + func (c *Module) UnstrippedOutputFile() android.Path { if c.linker != nil { return c.linker.unstrippedOutputFilePath() @@ -567,7 +731,7 @@ func (c *Module) isDependencyRoot() bool { return false } -func (c *Module) useVndk() bool { +func (c *Module) UseVndk() bool { return c.Properties.VndkVersion != "" } @@ -594,7 +758,7 @@ func (c *Module) isVndkPrivate(config android.Config) bool { return inList(c.BaseModuleName(), *vndkPrivateLibraries(config)) } -func (c *Module) isVndk() bool { +func (c *Module) IsVndk() bool { if vndkdep := c.vndkdep; vndkdep != nil { return vndkdep.isVndk() } @@ -633,7 +797,7 @@ func (c *Module) isVndkExt() bool { return false } -func (c *Module) mustUseVendorVariant() bool { +func (c *Module) MustUseVendorVariant() bool { return c.isVndkSp() || c.Properties.MustUseVendorVariant } @@ -646,15 +810,15 @@ func (c *Module) getVndkExtendsModuleName() string { // Returns true only when this module is configured to have core and vendor // variants. -func (c *Module) hasVendorVariant() bool { - return c.isVndk() || Bool(c.VendorProperties.Vendor_available) +func (c *Module) HasVendorVariant() bool { + return c.IsVndk() || Bool(c.VendorProperties.Vendor_available) } -func (c *Module) inRecovery() bool { +func (c *Module) InRecovery() bool { return c.Properties.InRecovery || c.ModuleBase.InstallInRecovery() } -func (c *Module) onlyInRecovery() bool { +func (c *Module) OnlyInRecovery() bool { return c.ModuleBase.InstallInRecovery() } @@ -725,7 +889,7 @@ type moduleContext struct { func (ctx *moduleContext) SocSpecific() bool { return ctx.ModuleContext.SocSpecific() || - (ctx.mod.hasVendorVariant() && ctx.mod.useVndk() && !ctx.mod.isVndk()) + (ctx.mod.HasVendorVariant() && ctx.mod.UseVndk() && !ctx.mod.IsVndk()) } type moduleContextImpl struct { @@ -775,7 +939,7 @@ func (ctx *moduleContextImpl) sdkVersion() string { } func (ctx *moduleContextImpl) useVndk() bool { - return ctx.mod.useVndk() + return ctx.mod.UseVndk() } func (ctx *moduleContextImpl) isNdk() bool { @@ -795,7 +959,7 @@ func (ctx *moduleContextImpl) isVndkPrivate(config android.Config) bool { } func (ctx *moduleContextImpl) isVndk() bool { - return ctx.mod.isVndk() + return ctx.mod.IsVndk() } func (ctx *moduleContextImpl) isPgoCompile() bool { @@ -815,11 +979,11 @@ func (ctx *moduleContextImpl) isVndkExt() bool { } func (ctx *moduleContextImpl) mustUseVendorVariant() bool { - return ctx.mod.mustUseVendorVariant() + return ctx.mod.MustUseVendorVariant() } func (ctx *moduleContextImpl) inRecovery() bool { - return ctx.mod.inRecovery() + return ctx.mod.InRecovery() } // Check whether ABI dumps should be created for this module. @@ -971,25 +1135,27 @@ func orderDeps(directStaticDeps []android.Path, directSharedDeps []android.Path, return orderedAllDeps, orderedDeclaredDeps } -func orderStaticModuleDeps(module *Module, staticDeps []*Module, sharedDeps []*Module) (results []android.Path) { +func orderStaticModuleDeps(module LinkableInterface, staticDeps []LinkableInterface, sharedDeps []LinkableInterface) (results []android.Path) { // convert Module to Path + var depsInLinkOrder []android.Path allTransitiveDeps := make(map[android.Path][]android.Path, len(staticDeps)) staticDepFiles := []android.Path{} for _, dep := range staticDeps { - allTransitiveDeps[dep.outputFile.Path()] = dep.depsInLinkOrder - staticDepFiles = append(staticDepFiles, dep.outputFile.Path()) + allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder() + staticDepFiles = append(staticDepFiles, dep.OutputFile().Path()) } sharedDepFiles := []android.Path{} for _, sharedDep := range sharedDeps { - staticAnalogue := sharedDep.staticVariant - if staticAnalogue != nil { - allTransitiveDeps[staticAnalogue.outputFile.Path()] = staticAnalogue.depsInLinkOrder - sharedDepFiles = append(sharedDepFiles, staticAnalogue.outputFile.Path()) + if sharedDep.HasStaticVariant() { + staticAnalogue := sharedDep.GetStaticVariant() + allTransitiveDeps[staticAnalogue.OutputFile().Path()] = staticAnalogue.GetDepsInLinkOrder() + sharedDepFiles = append(sharedDepFiles, staticAnalogue.OutputFile().Path()) } } // reorder the dependencies based on transitive dependencies - module.depsInLinkOrder, results = orderDeps(staticDepFiles, sharedDepFiles, allTransitiveDeps) + depsInLinkOrder, results = orderDeps(staticDepFiles, sharedDepFiles, allTransitiveDeps) + module.SetDepsInLinkOrder(depsInLinkOrder) return results } @@ -1022,7 +1188,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // .vendor suffix is added for backward compatibility with VNDK snapshot whose names with // such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp. c.Properties.SubName += vendorSuffix - } else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.useVndk() && c.hasVendorVariant()) { + } else if _, ok := c.linker.(*llndkStubDecorator); ok || (c.UseVndk() && c.HasVendorVariant()) { // .vendor.{version} suffix is added only when we will have two variants: core and vendor. // The suffix is not added for vendor-only module. c.Properties.SubName += vendorSuffix @@ -1033,7 +1199,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if c.Properties.VndkVersion != vendorVersion { c.Properties.SubName += "." + c.Properties.VndkVersion } - } else if c.inRecovery() && !c.onlyInRecovery() { + } else if c.InRecovery() && !c.OnlyInRecovery() { c.Properties.SubName += recoverySuffix } @@ -1143,7 +1309,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { // module is marked with 'bootstrap: true'). if c.HasStubsVariants() && android.DirectlyInAnyApex(ctx, ctx.baseModuleName()) && - !c.inRecovery() && !c.useVndk() && !c.static() && !c.isCoverageVariant() && + !c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() && c.IsStubs() { c.Properties.HideFromMake = false // unhide // Note: this is still non-installable @@ -1411,7 +1577,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { } for _, lib := range deps.StaticLibs { - depTag := staticDepTag + depTag := StaticDepTag if inList(lib, deps.ReexportStaticLibHeaders) { depTag = staticExportDepTag } @@ -1429,14 +1595,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { {Mutator: "link", Variation: "static"}, }, lateStaticDepTag, deps.LateStaticLibs...) - addSharedLibDependencies := func(depTag dependencyTag, name string, version string) { + addSharedLibDependencies := func(depTag DependencyTag, name string, version string) { var variations []blueprint.Variation variations = append(variations, blueprint.Variation{Mutator: "link", Variation: "shared"}) - versionVariantAvail := !ctx.useVndk() && !c.inRecovery() + versionVariantAvail := !ctx.useVndk() && !c.InRecovery() if version != "" && versionVariantAvail { // Version is explicitly specified. i.e. libFoo#30 variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version}) - depTag.explicitlyVersioned = true + depTag.ExplicitlyVersioned = true } actx.AddVariationDependencies(variations, depTag, name) @@ -1449,7 +1615,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { {Mutator: "link", Variation: "shared"}, {Mutator: "version", Variation: latestVersion}, }, depTag, name) - // Note that depTag.explicitlyVersioned is false in this case. + // Note that depTag.ExplicitlyVersioned is false in this case. } } @@ -1457,7 +1623,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { var sharedLibNames []string for _, lib := range deps.SharedLibs { - depTag := sharedDepTag + depTag := SharedDepTag if inList(lib, deps.ReexportSharedLibHeaders) { depTag = sharedExportDepTag } @@ -1499,10 +1665,10 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { actx.AddVariationDependencies(nil, objDepTag, deps.ObjFiles...) if deps.CrtBegin != "" { - actx.AddVariationDependencies(nil, crtBeginDepTag, deps.CrtBegin) + actx.AddVariationDependencies(nil, CrtBeginDepTag, deps.CrtBegin) } if deps.CrtEnd != "" { - actx.AddVariationDependencies(nil, crtEndDepTag, deps.CrtEnd) + actx.AddVariationDependencies(nil, CrtEndDepTag, deps.CrtEnd) } if deps.LinkerFlagsFile != "" { actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile) @@ -1545,52 +1711,58 @@ func BeginMutator(ctx android.BottomUpMutatorContext) { // Whether a module can link to another module, taking into // account NDK linking. -func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag dependencyTag) { - if from.Target().Os != android.Android { +func checkLinkType(ctx android.ModuleContext, from LinkableInterface, to LinkableInterface, tag DependencyTag) { + if from.Module().Target().Os != android.Android { // Host code is not restricted return } - if from.useVndk() { + + // VNDK is cc.Module supported only for now. + if ccFrom, ok := from.(*Module); ok && from.UseVndk() { // Though vendor code is limited by the vendor mutator, // each vendor-available module needs to check // link-type for VNDK. - if from.vndkdep != nil { - from.vndkdep.vndkCheckLinkType(ctx, to, tag) + if ccTo, ok := to.(*Module); ok { + if ccFrom.vndkdep != nil { + ccFrom.vndkdep.vndkCheckLinkType(ctx, ccTo, tag) + } + } else { + ctx.ModuleErrorf("Attempting to link VNDK cc.Module with unsupported module type") } return } - if String(from.Properties.Sdk_version) == "" { + if from.SdkVersion() == "" { // Platform code can link to anything return } - if from.inRecovery() { + if from.InRecovery() { // Recovery code is not NDK return } - if _, ok := to.linker.(*toolchainLibraryDecorator); ok { + if to.ToolchainLibrary() { // These are always allowed return } - if _, ok := to.linker.(*ndkPrebuiltStlLinker); ok { + if to.NdkPrebuiltStl() { // These are allowed, but they don't set sdk_version return } - if _, ok := to.linker.(*stubDecorator); ok { + if to.StubDecorator() { // These aren't real libraries, but are the stub shared libraries that are included in // the NDK. return } - if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Name() == "libc++" { + if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" { // Bug: http://b/121358700 - Allow libclang_rt.* shared libraries (with sdk_version) // to link to libc++ (non-NDK and without sdk_version). return } - if String(to.Properties.Sdk_version) == "" { + if to.SdkVersion() == "" { // NDK code linking to platform code is never okay. ctx.ModuleErrorf("depends on non-NDK-built library %q", - ctx.OtherModuleName(to)) + ctx.OtherModuleName(to.Module())) return } @@ -1600,36 +1772,36 @@ func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag depe // APIs. // Current can link against anything. - if String(from.Properties.Sdk_version) != "current" { + if from.SdkVersion() != "current" { // Otherwise we need to check. - if String(to.Properties.Sdk_version) == "current" { + if to.SdkVersion() == "current" { // Current can't be linked against by anything else. ctx.ModuleErrorf("links %q built against newer API version %q", - ctx.OtherModuleName(to), "current") + ctx.OtherModuleName(to.Module()), "current") } else { - fromApi, err := strconv.Atoi(String(from.Properties.Sdk_version)) + fromApi, err := strconv.Atoi(from.SdkVersion()) if err != nil { ctx.PropertyErrorf("sdk_version", "Invalid sdk_version value (must be int or current): %q", - String(from.Properties.Sdk_version)) + from.SdkVersion()) } - toApi, err := strconv.Atoi(String(to.Properties.Sdk_version)) + toApi, err := strconv.Atoi(to.SdkVersion()) if err != nil { ctx.PropertyErrorf("sdk_version", "Invalid sdk_version value (must be int or current): %q", - String(to.Properties.Sdk_version)) + to.SdkVersion()) } if toApi > fromApi { ctx.ModuleErrorf("links %q built against newer API version %q", - ctx.OtherModuleName(to), String(to.Properties.Sdk_version)) + ctx.OtherModuleName(to.Module()), to.SdkVersion()) } } } // Also check that the two STL choices are compatible. - fromStl := from.stl.Properties.SelectedStl - toStl := to.stl.Properties.SelectedStl + fromStl := from.SelectedStl() + toStl := to.SelectedStl() if fromStl == "" || toStl == "" { // Libraries that don't use the STL are unrestricted. } else if fromStl == "ndk_system" || toStl == "ndk_system" { @@ -1638,8 +1810,8 @@ func checkLinkType(ctx android.ModuleContext, from *Module, to *Module, tag depe // using either libc++ or nothing. } else if getNdkStlFamily(from) != getNdkStlFamily(to) { ctx.ModuleErrorf("uses %q and depends on %q which uses incompatible %q", - from.stl.Properties.SelectedStl, ctx.OtherModuleName(to), - to.stl.Properties.SelectedStl) + from.SelectedStl(), ctx.OtherModuleName(to.Module()), + to.SelectedStl()) } } @@ -1661,7 +1833,7 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { } // if target lib has no vendor variant, keep checking dependency graph - if !to.hasVendorVariant() { + if !to.HasVendorVariant() { return true } @@ -1691,8 +1863,8 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var depPaths PathDeps - directStaticDeps := []*Module{} - directSharedDeps := []*Module{} + directStaticDeps := []LinkableInterface{} + directSharedDeps := []LinkableInterface{} llndkLibraries := llndkLibraries(ctx.Config()) vendorPublicLibraries := vendorPublicLibraries(ctx.Config()) @@ -1708,8 +1880,9 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { depName := ctx.OtherModuleName(dep) depTag := ctx.OtherModuleDependencyTag(dep) - ccDep, _ := dep.(*Module) - if ccDep == nil { + ccDep, ok := dep.(LinkableInterface) + if !ok { + // handling for a few module types that aren't cc Module but that are also supported switch depTag { case genSourceDepTag: @@ -1767,9 +1940,10 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // re-exporting flags if depTag == reuseObjTag { - if l, ok := ccDep.compiler.(libraryInterface); ok { + // reusing objects only make sense for cc.Modules. + if ccReuseDep, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() { c.staticVariant = ccDep - objs, exporter := l.reuseObjs() + objs, exporter := ccReuseDep.compiler.(libraryInterface).reuseObjs() depPaths.Objs = depPaths.Objs.Append(objs) reexportExporter(exporter) return @@ -1777,30 +1951,31 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } if depTag == staticVariantTag { - if _, ok := ccDep.compiler.(libraryInterface); ok { + // staticVariants are a cc.Module specific concept. + if _, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() { c.staticVariant = ccDep return } } - // Extract explicitlyVersioned field from the depTag and reset it inside the struct. - // Otherwise, sharedDepTag and lateSharedDepTag with explicitlyVersioned set to true - // won't be matched to sharedDepTag and lateSharedDepTag. + // Extract ExplicitlyVersioned field from the depTag and reset it inside the struct. + // Otherwise, SharedDepTag and lateSharedDepTag with ExplicitlyVersioned set to true + // won't be matched to SharedDepTag and lateSharedDepTag. explicitlyVersioned := false - if t, ok := depTag.(dependencyTag); ok { - explicitlyVersioned = t.explicitlyVersioned - t.explicitlyVersioned = false + if t, ok := depTag.(DependencyTag); ok { + explicitlyVersioned = t.ExplicitlyVersioned + t.ExplicitlyVersioned = false depTag = t } - if t, ok := depTag.(dependencyTag); ok && t.library { + if t, ok := depTag.(DependencyTag); ok && t.Library { depIsStatic := false switch depTag { - case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag: + case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag: depIsStatic = true } - if dependentLibrary, ok := ccDep.linker.(*libraryDecorator); ok && !depIsStatic { - depIsStubs := dependentLibrary.buildStubs() + if ccDep.CcLibrary() && !depIsStatic { + depIsStubs := ccDep.BuildStubs() depHasStubs := ccDep.HasStubsVariants() depInSameApex := android.DirectlyInApex(c.ApexName(), depName) depInPlatform := !android.DirectlyInAnyApex(ctx, depName) @@ -1817,7 +1992,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // If not building for APEX, use stubs only when it is from // an APEX (and not from platform) useThisDep = (depInPlatform != depIsStubs) - if c.inRecovery() || c.bootstrap() { + if c.InRecovery() || c.bootstrap() { // However, for recovery or bootstrap modules, // always link to non-stub variant useThisDep = !depIsStubs @@ -1833,85 +2008,95 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } - if i, ok := ccDep.linker.(exportedFlagsProducer); ok { - depPaths.IncludeDirs = append(depPaths.IncludeDirs, i.exportedDirs()...) - depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...) - depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedDeps()...) - depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...) + // Exporting flags only makes sense for cc.Modules + if _, ok := ccDep.(*Module); ok { + if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok { + depPaths.IncludeDirs = append(depPaths.IncludeDirs, i.exportedDirs()...) + depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...) + depPaths.GeneratedHeaders = append(depPaths.GeneratedHeaders, i.exportedDeps()...) + depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...) - if t.reexportFlags { - reexportExporter(i) - // Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library. - // Re-exported shared library headers must be included as well since they can help us with type information - // about template instantiations (instantiated from their headers). - // -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version - // scripts. - c.sabi.Properties.ReexportedIncludes = append( - c.sabi.Properties.ReexportedIncludes, i.exportedDirs().Strings()...) + if t.ReexportFlags { + reexportExporter(i) + // Add these re-exported flags to help header-abi-dumper to infer the abi exported by a library. + // Re-exported shared library headers must be included as well since they can help us with type information + // about template instantiations (instantiated from their headers). + // -isystem headers are not included since for bionic libraries, abi-filtering is taken care of by version + // scripts. + c.sabi.Properties.ReexportedIncludes = append( + c.sabi.Properties.ReexportedIncludes, i.exportedDirs().Strings()...) + } } } - checkLinkType(ctx, c, ccDep, t) } var ptr *android.Paths var depPtr *android.Paths - linkFile := ccDep.outputFile + linkFile := ccDep.OutputFile() depFile := android.OptionalPath{} switch depTag { - case ndkStubDepTag, sharedDepTag, sharedExportDepTag: + case ndkStubDepTag, SharedDepTag, sharedExportDepTag: ptr = &depPaths.SharedLibs depPtr = &depPaths.SharedLibsDeps - depFile = ccDep.linker.(libraryInterface).toc() + depFile = ccDep.Toc() directSharedDeps = append(directSharedDeps, ccDep) + case earlySharedDepTag: ptr = &depPaths.EarlySharedLibs depPtr = &depPaths.EarlySharedLibsDeps - depFile = ccDep.linker.(libraryInterface).toc() + depFile = ccDep.Toc() directSharedDeps = append(directSharedDeps, ccDep) case lateSharedDepTag, ndkLateStubDepTag: ptr = &depPaths.LateSharedLibs depPtr = &depPaths.LateSharedLibsDeps - depFile = ccDep.linker.(libraryInterface).toc() - case staticDepTag, staticExportDepTag: + depFile = ccDep.Toc() + case StaticDepTag, staticExportDepTag: ptr = nil directStaticDeps = append(directStaticDeps, ccDep) case lateStaticDepTag: ptr = &depPaths.LateStaticLibs case wholeStaticDepTag: ptr = &depPaths.WholeStaticLibs - staticLib, ok := ccDep.linker.(libraryInterface) - if !ok || !staticLib.static() { + if !ccDep.CcLibraryInterface() || !ccDep.Static() { ctx.ModuleErrorf("module %q not a static library", depName) return } - if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil { - postfix := " (required by " + ctx.OtherModuleName(dep) + ")" - for i := range missingDeps { - missingDeps[i] += postfix + // Because the static library objects are included, this only makes sense + // in the context of proper cc.Modules. + if ccWholeStaticLib, ok := ccDep.(*Module); ok { + staticLib := ccWholeStaticLib.linker.(libraryInterface) + if missingDeps := staticLib.getWholeStaticMissingDeps(); missingDeps != nil { + postfix := " (required by " + ctx.OtherModuleName(dep) + ")" + for i := range missingDeps { + missingDeps[i] += postfix + } + ctx.AddMissingDependencies(missingDeps) } - ctx.AddMissingDependencies(missingDeps) + depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) + } else { + ctx.ModuleErrorf( + "non-cc.Modules cannot be included as whole static libraries.", depName) + return } - depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLib.objs()) case headerDepTag: // Nothing case objDepTag: depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path()) - case crtBeginDepTag: + case CrtBeginDepTag: depPaths.CrtBegin = linkFile - case crtEndDepTag: + case CrtEndDepTag: depPaths.CrtEnd = linkFile case dynamicLinkerDepTag: depPaths.DynamicLinker = linkFile } switch depTag { - case staticDepTag, staticExportDepTag, lateStaticDepTag: - staticLib, ok := ccDep.linker.(libraryInterface) - if !ok || !staticLib.static() { + case StaticDepTag, staticExportDepTag, lateStaticDepTag: + if !ccDep.CcLibraryInterface() || !ccDep.Static() { ctx.ModuleErrorf("module %q not a static library", depName) return } @@ -1919,11 +2104,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // When combining coverage files for shared libraries and executables, coverage files // in static libraries act as if they were whole static libraries. The same goes for // source based Abi dump files. - depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, - staticLib.objs().coverageFiles...) - depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles, - staticLib.objs().sAbiDumpFiles...) - + // This should only be done for cc.Modules + if c, ok := ccDep.(*Module); ok { + staticLib := c.linker.(libraryInterface) + depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, + staticLib.objs().coverageFiles...) + depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles, + staticLib.objs().sAbiDumpFiles...) + } } if ptr != nil { @@ -1952,13 +2140,13 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { libName = strings.TrimPrefix(libName, "prebuilt_") isLLndk := inList(libName, *llndkLibraries) isVendorPublicLib := inList(libName, *vendorPublicLibraries) - bothVendorAndCoreVariantsExist := ccDep.hasVendorVariant() || isLLndk + bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk - if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.isVndk() && !ccDep.mustUseVendorVariant() && !c.inRecovery() { + if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() && !c.InRecovery() { // The vendor module is a no-vendor-variant VNDK library. Depend on the // core module instead. return libName - } else if c.useVndk() && bothVendorAndCoreVariantsExist { + } else if c.UseVndk() && bothVendorAndCoreVariantsExist { // The vendor module in Make will have been renamed to not conflict with the core // module, so update the dependency name here accordingly. ret := libName + vendorSuffix @@ -1972,9 +2160,9 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return ret } else if (ctx.Platform() || ctx.ProductSpecific()) && isVendorPublicLib { return libName + vendorPublicLibrarySuffix - } else if ccDep.inRecovery() && !ccDep.onlyInRecovery() { + } else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() { return libName + recoverySuffix - } else if ccDep.Target().NativeBridge == android.NativeBridgeEnabled { + } else if ccDep.Module().Target().NativeBridge == android.NativeBridgeEnabled { return libName + nativeBridgeSuffix } else { return libName @@ -1983,9 +2171,9 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // Export the shared libs to Make. switch depTag { - case sharedDepTag, sharedExportDepTag, lateSharedDepTag, earlySharedDepTag: - if dependentLibrary, ok := ccDep.linker.(*libraryDecorator); ok { - if dependentLibrary.buildStubs() && android.InAnyApex(depName) { + case SharedDepTag, sharedExportDepTag, lateSharedDepTag, earlySharedDepTag: + if ccDep.CcLibrary() { + if ccDep.BuildStubs() && android.InAnyApex(depName) { // Add the dependency to the APEX(es) providing the library so that // m can trigger building the APEXes as well. for _, an := range android.GetApexesForModule(depName) { @@ -2000,11 +2188,10 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { c.Properties.AndroidMkSharedLibs = append( c.Properties.AndroidMkSharedLibs, makeLibName(depName)) case ndkStubDepTag, ndkLateStubDepTag: - ndkStub := ccDep.linker.(*stubDecorator) c.Properties.AndroidMkSharedLibs = append( c.Properties.AndroidMkSharedLibs, - depName+"."+ndkStub.properties.ApiLevel) - case staticDepTag, staticExportDepTag, lateStaticDepTag: + depName+"."+ccDep.ApiLevel()) + case StaticDepTag, staticExportDepTag, lateStaticDepTag: c.Properties.AndroidMkStaticLibs = append( c.Properties.AndroidMkStaticLibs, makeLibName(depName)) case runtimeDepTag: @@ -2054,7 +2241,7 @@ func (c *Module) InstallInSanitizerDir() bool { } func (c *Module) InstallInRecovery() bool { - return c.inRecovery() + return c.InRecovery() } func (c *Module) HostToolPath() android.OptionalPath { @@ -2108,28 +2295,28 @@ func (c *Module) header() bool { } func (c *Module) getMakeLinkType(actx android.ModuleContext) string { - if c.useVndk() { + if c.UseVndk() { if lib, ok := c.linker.(*llndkStubDecorator); ok { if Bool(lib.Properties.Vendor_available) { return "native:vndk" } return "native:vndk_private" } - if c.isVndk() && !c.isVndkExt() { + if c.IsVndk() && !c.isVndkExt() { if Bool(c.VendorProperties.Vendor_available) { return "native:vndk" } return "native:vndk_private" } return "native:vendor" - } else if c.inRecovery() { + } else if c.InRecovery() { return "native:recovery" } else if c.Target().Os == android.Android && String(c.Properties.Sdk_version) != "" { return "native:ndk:none:none" // TODO(b/114741097): use the correct ndk stl once build errors have been fixed //family, link := getNdkStlFamilyAndLinkType(c) //return fmt.Sprintf("native:ndk:%s:%s", family, link) - } else if actx.DeviceConfig().VndkUseCoreVariant() && !c.mustUseVendorVariant() { + } else if actx.DeviceConfig().VndkUseCoreVariant() && !c.MustUseVendorVariant() { return "native:platform_vndk" } else { return "native:platform" @@ -2164,9 +2351,9 @@ func (c *Module) installable() bool { } func (c *Module) imageVariation() string { - if c.useVndk() { + if c.UseVndk() { return vendorMode + "." + c.Properties.VndkVersion - } else if c.inRecovery() { + } else if c.InRecovery() { return recoveryMode } return coreMode @@ -2189,8 +2376,8 @@ func (c *Module) AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w io.Write } func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool { - if depTag, ok := ctx.OtherModuleDependencyTag(dep).(dependencyTag); ok { - if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.shared { + if depTag, ok := ctx.OtherModuleDependencyTag(dep).(DependencyTag); ok { + if cc, ok := dep.(*Module); ok && cc.IsStubs() && depTag.Shared { // dynamic dep to a stubs lib crosses APEX boundary return false } @@ -2341,8 +2528,16 @@ func ImageMutator(mctx android.BottomUpMutatorContext) { } } + //TODO When LinkableInterface supports VNDK, this should be mctx.Module().(LinkableInterface) m, ok := mctx.Module().(*Module) if !ok { + if linkable, ok := mctx.Module().(LinkableInterface); ok { + variations := []string{coreMode} + if linkable.InRecovery() { + variations = append(variations, recoveryMode) + } + mctx.CreateVariations(variations...) + } return } @@ -2432,12 +2627,12 @@ func ImageMutator(mctx android.BottomUpMutatorContext) { // Make vendor variants only for the versions in BOARD_VNDK_VERSION and // PRODUCT_EXTRA_VNDK_VERSIONS. vendorVariants = append(vendorVariants, lib.version()) - } else if m.hasVendorVariant() && !vendorSpecific { + } else if m.HasVendorVariant() && !vendorSpecific { // This will be available in both /system and /vendor // or a /system directory that is available to vendor. coreVariantNeeded = true vendorVariants = append(vendorVariants, platformVndkVersion) - if m.isVndk() { + if m.IsVndk() { vendorVariants = append(vendorVariants, deviceVndkVersion) } } else if vendorSpecific && String(m.Properties.Sdk_version) == "" { diff --git a/cc/cc_test.go b/cc/cc_test.go index 635e7d0af..064b1a25c 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -213,7 +213,7 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string t.Helper() mod := ctx.ModuleForTests(name, vendorVariant).Module().(*Module) - if !mod.hasVendorVariant() { + if !mod.HasVendorVariant() { t.Errorf("%q must have vendor variant", name) } @@ -230,8 +230,8 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string if mod.vndkdep == nil { t.Fatalf("%q must have `vndkdep`", name) } - if !mod.isVndk() { - t.Errorf("%q isVndk() must equal to true", name) + if !mod.IsVndk() { + t.Errorf("%q IsVndk() must equal to true", name) } if mod.isVndkSp() != isVndkSp { t.Errorf("%q isVndkSp() must equal to %t", name, isVndkSp) diff --git a/cc/fuzz.go b/cc/fuzz.go index 4d3852684..2c3b973e4 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -245,7 +245,7 @@ func (s *fuzzPackager) GenerateBuildActions(ctx android.SingletonContext) { // Discard vendor-NDK-linked modules, they're duplicates of fuzz targets // we're going to package anyway. - if ccModule.useVndk() || !ccModule.Enabled() { + if ccModule.UseVndk() || !ccModule.Enabled() { return } diff --git a/cc/library.go b/cc/library.go index 1943e89b5..5a08879a5 100644 --- a/cc/library.go +++ b/cc/library.go @@ -1227,45 +1227,59 @@ func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Mod } func LinkageMutator(mctx android.BottomUpMutatorContext) { + cc_prebuilt := false if m, ok := mctx.Module().(*Module); ok && m.linker != nil { - switch library := m.linker.(type) { - case prebuiltLibraryInterface: - // Always create both the static and shared variants for prebuilt libraries, and then disable the one - // that is not being used. This allows them to share the name of a cc_library module, which requires that - // all the variants of the cc_library also exist on the prebuilt. - modules := mctx.CreateLocalVariations("static", "shared") - static := modules[0].(*Module) - shared := modules[1].(*Module) + _, cc_prebuilt = m.linker.(prebuiltLibraryInterface) + } + if cc_prebuilt { + library := mctx.Module().(*Module).linker.(prebuiltLibraryInterface) - static.linker.(prebuiltLibraryInterface).setStatic() - shared.linker.(prebuiltLibraryInterface).setShared() + // Always create both the static and shared variants for prebuilt libraries, and then disable the one + // that is not being used. This allows them to share the name of a cc_library module, which requires that + // all the variants of the cc_library also exist on the prebuilt. + modules := mctx.CreateLocalVariations("static", "shared") + static := modules[0].(*Module) + shared := modules[1].(*Module) - if !library.buildStatic() { - static.linker.(prebuiltLibraryInterface).disablePrebuilt() - } - if !library.buildShared() { - shared.linker.(prebuiltLibraryInterface).disablePrebuilt() - } + static.linker.(prebuiltLibraryInterface).setStatic() + shared.linker.(prebuiltLibraryInterface).setShared() - case libraryInterface: - if library.buildStatic() && library.buildShared() { - modules := mctx.CreateLocalVariations("static", "shared") - static := modules[0].(*Module) - shared := modules[1].(*Module) - - static.linker.(libraryInterface).setStatic() - shared.linker.(libraryInterface).setShared() - - reuseStaticLibrary(mctx, static, shared) - - } else if library.buildStatic() { - modules := mctx.CreateLocalVariations("static") - modules[0].(*Module).linker.(libraryInterface).setStatic() - } else if library.buildShared() { - modules := mctx.CreateLocalVariations("shared") - modules[0].(*Module).linker.(libraryInterface).setShared() - } + if !library.buildStatic() { + static.linker.(prebuiltLibraryInterface).disablePrebuilt() } + if !library.buildShared() { + shared.linker.(prebuiltLibraryInterface).disablePrebuilt() + } + } else if library, ok := mctx.Module().(LinkableInterface); ok && library.CcLibraryInterface() { + if library.BuildStaticVariant() && library.BuildSharedVariant() { + variations := []string{"static", "shared"} + + // Non-cc.Modules need an empty variant for their mutators. + if _, ok := mctx.Module().(*Module); !ok { + variations = append(variations, "") + } + + modules := mctx.CreateLocalVariations(variations...) + static := modules[0].(LinkableInterface) + shared := modules[1].(LinkableInterface) + + static.SetStatic() + shared.SetShared() + + if _, ok := library.(*Module); ok { + reuseStaticLibrary(mctx, static.(*Module), shared.(*Module)) + } + } else if library.BuildStaticVariant() { + modules := mctx.CreateLocalVariations("static") + modules[0].(LinkableInterface).SetStatic() + } else if library.BuildSharedVariant() { + modules := mctx.CreateLocalVariations("shared") + modules[0].(LinkableInterface).SetShared() + } else if _, ok := mctx.Module().(*Module); !ok { + // Non-cc.Modules need an empty variant for their mutators. + mctx.CreateLocalVariations("") + } + } } @@ -1292,11 +1306,10 @@ func latestStubsVersionFor(config android.Config, name string) string { // Version mutator splits a module into the mandatory non-stubs variant // (which is unnamed) and zero or more stubs variants. func VersionMutator(mctx android.BottomUpMutatorContext) { - if m, ok := mctx.Module().(*Module); ok && !m.inRecovery() && m.linker != nil { - if library, ok := m.linker.(*libraryDecorator); ok && library.buildShared() && - len(library.Properties.Stubs.Versions) > 0 { + if library, ok := mctx.Module().(LinkableInterface); ok && !library.InRecovery() { + if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 { versions := []string{} - for _, v := range library.Properties.Stubs.Versions { + for _, v := range library.StubsVersions() { if _, err := strconv.Atoi(v); err != nil { mctx.PropertyErrorf("versions", "%q is not a number", v) } @@ -1320,14 +1333,9 @@ func VersionMutator(mctx android.BottomUpMutatorContext) { modules := mctx.CreateVariations(versions...) for i, m := range modules { - l := m.(*Module).linker.(*libraryDecorator) if versions[i] != "" { - l.MutatedProperties.BuildStubs = true - l.MutatedProperties.StubsVersion = versions[i] - m.(*Module).Properties.HideFromMake = true - m.(*Module).sanitize = nil - m.(*Module).stl = nil - m.(*Module).Properties.PreventInstall = true + m.(LinkableInterface).SetBuildStubs() + m.(LinkableInterface).SetStubsVersions(versions[i]) } } } else { @@ -1353,7 +1361,7 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu injectBoringSSLHash := Bool(inject) ctx.VisitDirectDeps(func(dep android.Module) { tag := ctx.OtherModuleDependencyTag(dep) - if tag == staticDepTag || tag == staticExportDepTag || tag == wholeStaticDepTag || tag == lateStaticDepTag { + if tag == StaticDepTag || tag == staticExportDepTag || tag == wholeStaticDepTag || tag == lateStaticDepTag { if cc, ok := dep.(*Module); ok { if library, ok := cc.linker.(*libraryDecorator); ok { if Bool(library.Properties.Inject_bssl_hash) { diff --git a/cc/linkable.go b/cc/linkable.go new file mode 100644 index 000000000..cfbaffe30 --- /dev/null +++ b/cc/linkable.go @@ -0,0 +1,71 @@ +package cc + +import ( + "github.com/google/blueprint" + + "android/soong/android" +) + +type LinkableInterface interface { + Module() android.Module + CcLibrary() bool + CcLibraryInterface() bool + + OutputFile() android.OptionalPath + + IncludeDirs(ctx android.BaseModuleContext) android.Paths + SetDepsInLinkOrder([]android.Path) + GetDepsInLinkOrder() []android.Path + + HasStaticVariant() bool + GetStaticVariant() LinkableInterface + + StubsVersions() []string + BuildStubs() bool + SetBuildStubs() + SetStubsVersions(string) + HasStubsVariants() bool + SelectedStl() string + ApiLevel() string + + BuildStaticVariant() bool + BuildSharedVariant() bool + SetStatic() + SetShared() + Static() bool + Shared() bool + Toc() android.OptionalPath + + InRecovery() bool + OnlyInRecovery() bool + + UseVndk() bool + MustUseVendorVariant() bool + IsVndk() bool + HasVendorVariant() bool + + SdkVersion() string + + ToolchainLibrary() bool + NdkPrebuiltStl() bool + StubDecorator() bool +} + +type DependencyTag struct { + blueprint.BaseDependencyTag + Name string + Library bool + Shared bool + + ReexportFlags bool + + ExplicitlyVersioned bool +} + +var ( + SharedDepTag = DependencyTag{Name: "shared", Library: true, Shared: true} + StaticDepTag = DependencyTag{Name: "static", Library: true} + + CrtBeginDepTag = DependencyTag{Name: "crtbegin"} + CrtEndDepTag = DependencyTag{Name: "crtend"} +) diff --git a/cc/lto.go b/cc/lto.go index 431d70d94..580bb090b 100644 --- a/cc/lto.go +++ b/cc/lto.go @@ -148,7 +148,7 @@ func ltoDepsMutator(mctx android.TopDownMutatorContext) { mctx.WalkDeps(func(dep android.Module, parent android.Module) bool { tag := mctx.OtherModuleDependencyTag(dep) switch tag { - case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag: + case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag: if dep, ok := dep.(*Module); ok && dep.lto != nil && !dep.lto.Disabled() { if full && !Bool(dep.lto.Properties.Lto.Full) { diff --git a/cc/sabi.go b/cc/sabi.go index 099915151..8a9eff026 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -78,12 +78,12 @@ func (sabimod *sabi) flags(ctx ModuleContext, flags Flags) Flags { func sabiDepsMutator(mctx android.TopDownMutatorContext) { if c, ok := mctx.Module().(*Module); ok && - ((c.isVndk() && c.useVndk()) || inList(c.Name(), *llndkLibraries(mctx.Config())) || + ((c.IsVndk() && c.UseVndk()) || inList(c.Name(), *llndkLibraries(mctx.Config())) || (c.sabi != nil && c.sabi.Properties.CreateSAbiDumps)) { mctx.VisitDirectDeps(func(m android.Module) { tag := mctx.OtherModuleDependencyTag(m) switch tag { - case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag: + case StaticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag: cc, _ := m.(*Module) if cc == nil { diff --git a/cc/sanitize.go b/cc/sanitize.go index 3f0f0f498..e4c6b1c06 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -678,8 +678,8 @@ func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { } func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool { - t, ok := tag.(dependencyTag) - return ok && t.library || t == reuseObjTag || t == objDepTag + t, ok := tag.(DependencyTag) + return ok && t.Library || t == reuseObjTag || t == objDepTag } // Propagate sanitizer requirements down from binaries @@ -873,7 +873,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { } if mctx.Device() && runtimeLibrary != "" { - if inList(runtimeLibrary, *llndkLibraries(mctx.Config())) && !c.static() && c.useVndk() { + if inList(runtimeLibrary, *llndkLibraries(mctx.Config())) && !c.static() && c.UseVndk() { runtimeLibrary = runtimeLibrary + llndkLibrarySuffix } @@ -889,7 +889,7 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ {Mutator: "link", Variation: "static"}, {Mutator: "image", Variation: c.imageVariation()}, - }...), staticDepTag, append([]string{runtimeLibrary}, extraStaticDeps...)...) + }...), StaticDepTag, append([]string{runtimeLibrary}, extraStaticDeps...)...) } else if !c.static() && !c.header() { // dynamic executable and shared libs get shared runtime libs mctx.AddFarVariationDependencies(append(mctx.Target().Variations(), []blueprint.Variation{ @@ -963,7 +963,7 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { if t == cfi { appendStringSync(c.Name(), cfiStaticLibs(mctx.Config()), &cfiStaticLibsMutex) } else if t == hwasan { - if c.useVndk() { + if c.UseVndk() { appendStringSync(c.Name(), hwasanVendorStaticLibs(mctx.Config()), &hwasanStaticLibsMutex) } else { diff --git a/cc/stl.go b/cc/stl.go index f9273e1a5..101519b05 100644 --- a/cc/stl.go +++ b/cc/stl.go @@ -20,13 +20,13 @@ import ( "strconv" ) -func getNdkStlFamily(m *Module) string { +func getNdkStlFamily(m LinkableInterface) string { family, _ := getNdkStlFamilyAndLinkType(m) return family } -func getNdkStlFamilyAndLinkType(m *Module) (string, string) { - stl := m.stl.Properties.SelectedStl +func getNdkStlFamilyAndLinkType(m LinkableInterface) (string, string) { + stl := m.SelectedStl() switch stl { case "ndk_libc++_shared": return "libc++", "shared" diff --git a/cc/vndk.go b/cc/vndk.go index 299720417..ec8f023c2 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -98,7 +98,7 @@ func (vndk *vndkdep) typeName() string { return "native:vendor:vndkspext" } -func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag dependencyTag) { +func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, tag DependencyTag) { if to.linker == nil { return } @@ -125,7 +125,7 @@ func (vndk *vndkdep) vndkCheckLinkType(ctx android.ModuleContext, to *Module, ta // Other (static and LL-NDK) libraries are allowed to link. return } - if !to.useVndk() { + if !to.UseVndk() { ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library", vndk.typeName(), to.Name()) return @@ -352,7 +352,7 @@ func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { useCoreVariant := m.vndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() && mctx.DeviceConfig().VndkUseCoreVariant() && !inList(m.BaseModuleName(), config.VndkMustUseVendorVariantList) - return lib.shared() && m.useVndk() && m.isVndk() && !m.isVndkExt() && !useCoreVariant + return lib.shared() && m.UseVndk() && m.IsVndk() && !m.isVndkExt() && !useCoreVariant } return false } @@ -536,7 +536,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex if m.Target().NativeBridge == android.NativeBridgeEnabled { return nil, "", false } - if !m.useVndk() || !m.IsForPlatform() || !m.installable() { + if !m.UseVndk() || !m.IsForPlatform() || !m.installable() { return nil, "", false } l, ok := m.linker.(vndkSnapshotLibraryInterface) @@ -699,7 +699,7 @@ func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.Singleton if c.isVndkPrivate(config) { vndkprivate = append(vndkprivate, filename) } - } else if c.vndkVersion() == vndkVersion && c.isVndk() && !c.isVndkExt() { + } else if c.vndkVersion() == vndkVersion && c.IsVndk() && !c.isVndkExt() { if c.isVndkSp() { vndksp = append(vndksp, filename) } else { @@ -708,7 +708,7 @@ func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.Singleton if c.isVndkPrivate(config) { vndkprivate = append(vndkprivate, filename) } - if ctx.DeviceConfig().VndkUseCoreVariant() && !c.mustUseVendorVariant() { + if ctx.DeviceConfig().VndkUseCoreVariant() && !c.MustUseVendorVariant() { vndkcorevariant = append(vndkcorevariant, filename) } } diff --git a/rust/androidmk.go b/rust/androidmk.go index a6208dbcd..f933cfbcf 100644 --- a/rust/androidmk.go +++ b/rust/androidmk.go @@ -92,7 +92,12 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An ret.Class = "RLIB_LIBRARIES" } else if library.dylib() { ret.Class = "DYLIB_LIBRARIES" + } else if library.static() { + ret.Class = "STATIC_LIBRARIES" + } else if library.shared() { + ret.Class = "SHARED_LIBRARIES" } + ret.DistFile = library.distFile ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { if !library.rlib() { diff --git a/rust/builder.go b/rust/builder.go index 104313f8a..2a7643d62 100644 --- a/rust/builder.go +++ b/rust/builder.go @@ -53,6 +53,14 @@ func TransformSrctoDylib(ctx android.ModuleContext, mainSrc android.Path, deps P transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "dylib", includeDirs) } +func TransformSrctoStatic(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { + transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "staticlib", includeDirs) +} + +func TransformSrctoShared(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { + transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "cdylib", includeDirs) +} + func TransformSrctoProcMacro(ctx android.ModuleContext, mainSrc android.Path, deps PathDeps, flags Flags, outputFile android.WritablePath, includeDirs []string) { transformSrctoCrate(ctx, mainSrc, deps.RLibs, deps.DyLibs, deps.ProcMacros, deps.StaticLibs, deps.SharedLibs, deps.CrtBegin, deps.CrtEnd, flags, outputFile, "proc-macro", includeDirs) } diff --git a/rust/config/toolchain.go b/rust/config/toolchain.go index 328bca3b9..616d88b89 100644 --- a/rust/config/toolchain.go +++ b/rust/config/toolchain.go @@ -95,7 +95,7 @@ func (toolchainBase) RlibSuffix() string { return ".rlib" } func (toolchainBase) DylibSuffix() string { - return ".so" + return ".dylib.so" } func (toolchainBase) ProcMacroSuffix() string { diff --git a/rust/library.go b/rust/library.go index c831727c5..273a3ce16 100644 --- a/rust/library.go +++ b/rust/library.go @@ -25,8 +25,10 @@ func init() { android.RegisterModuleType("rust_library_host", RustLibraryHostFactory) android.RegisterModuleType("rust_library_host_dylib", RustLibraryDylibHostFactory) android.RegisterModuleType("rust_library_host_rlib", RustLibraryRlibHostFactory) - - //TODO: Add support for generating standard shared/static libraries. + android.RegisterModuleType("rust_library_shared", RustLibrarySharedFactory) + android.RegisterModuleType("rust_library_static", RustLibraryStaticFactory) + android.RegisterModuleType("rust_library_host_shared", RustLibrarySharedHostFactory) + android.RegisterModuleType("rust_library_host_static", RustLibraryStaticHostFactory) } type VariantLibraryProperties struct { @@ -34,25 +36,36 @@ type VariantLibraryProperties struct { } type LibraryCompilerProperties struct { - Rlib VariantLibraryProperties `android:"arch_variant"` - Dylib VariantLibraryProperties `android:"arch_variant"` + Rlib VariantLibraryProperties `android:"arch_variant"` + Dylib VariantLibraryProperties `android:"arch_variant"` + Shared VariantLibraryProperties `android:"arch_variant"` + Static VariantLibraryProperties `android:"arch_variant"` // path to the source file that is the main entry point of the program (e.g. src/lib.rs) Srcs []string `android:"path,arch_variant"` + + // path to include directories to pass to cc_* modules, only relevant for static/shared variants. + Include_dirs []string `android:"path,arch_variant"` } type LibraryMutatedProperties struct { - VariantName string `blueprint:"mutated"` - // Build a dylib variant BuildDylib bool `blueprint:"mutated"` // Build an rlib variant BuildRlib bool `blueprint:"mutated"` + // Build a shared library variant + BuildShared bool `blueprint:"mutated"` + // Build a static library variant + BuildStatic bool `blueprint:"mutated"` // This variant is a dylib VariantIsDylib bool `blueprint:"mutated"` // This variant is an rlib VariantIsRlib bool `blueprint:"mutated"` + // This variant is a shared library + VariantIsShared bool `blueprint:"mutated"` + // This variant is a static library + VariantIsStatic bool `blueprint:"mutated"` } type libraryDecorator struct { @@ -67,14 +80,26 @@ type libraryDecorator struct { type libraryInterface interface { rlib() bool dylib() bool + static() bool + shared() bool // Returns true if the build options for the module have selected a particular build type buildRlib() bool buildDylib() bool + buildShared() bool + buildStatic() bool // Sets a particular variant type setRlib() setDylib() + setShared() + setStatic() + + // Build a specific library variant + BuildOnlyRlib() + BuildOnlyDylib() + BuildOnlyStatic() + BuildOnlyShared() } func (library *libraryDecorator) exportedDirs() []string { @@ -101,6 +126,14 @@ func (library *libraryDecorator) dylib() bool { return library.MutatedProperties.VariantIsDylib } +func (library *libraryDecorator) shared() bool { + return library.MutatedProperties.VariantIsShared +} + +func (library *libraryDecorator) static() bool { + return library.MutatedProperties.VariantIsStatic +} + func (library *libraryDecorator) buildRlib() bool { return library.MutatedProperties.BuildRlib && BoolDefault(library.Properties.Rlib.Enabled, true) } @@ -109,17 +142,44 @@ func (library *libraryDecorator) buildDylib() bool { return library.MutatedProperties.BuildDylib && BoolDefault(library.Properties.Dylib.Enabled, true) } +func (library *libraryDecorator) buildShared() bool { + return library.MutatedProperties.BuildShared && BoolDefault(library.Properties.Shared.Enabled, true) +} + +func (library *libraryDecorator) buildStatic() bool { + return library.MutatedProperties.BuildStatic && BoolDefault(library.Properties.Static.Enabled, true) +} + func (library *libraryDecorator) setRlib() { library.MutatedProperties.VariantIsRlib = true library.MutatedProperties.VariantIsDylib = false + library.MutatedProperties.VariantIsStatic = false + library.MutatedProperties.VariantIsShared = false } func (library *libraryDecorator) setDylib() { library.MutatedProperties.VariantIsRlib = false library.MutatedProperties.VariantIsDylib = true + library.MutatedProperties.VariantIsStatic = false + library.MutatedProperties.VariantIsShared = false +} + +func (library *libraryDecorator) setShared() { + library.MutatedProperties.VariantIsStatic = false + library.MutatedProperties.VariantIsShared = true + library.MutatedProperties.VariantIsRlib = false + library.MutatedProperties.VariantIsDylib = false +} + +func (library *libraryDecorator) setStatic() { + library.MutatedProperties.VariantIsStatic = true + library.MutatedProperties.VariantIsShared = false + library.MutatedProperties.VariantIsRlib = false + library.MutatedProperties.VariantIsDylib = false } var _ compiler = (*libraryDecorator)(nil) +var _ libraryInterface = (*libraryDecorator)(nil) // rust_library produces all variants. func RustLibraryFactory() android.Module { @@ -141,6 +201,20 @@ func RustLibraryRlibFactory() android.Module { return module.Init() } +// rust_library_shared produces a shared library. +func RustLibrarySharedFactory() android.Module { + module, library := NewRustLibrary(android.HostAndDeviceSupported) + library.BuildOnlyShared() + return module.Init() +} + +// rust_library_static produces a static library. +func RustLibraryStaticFactory() android.Module { + module, library := NewRustLibrary(android.HostAndDeviceSupported) + library.BuildOnlyStatic() + return module.Init() +} + // rust_library_host produces all variants. func RustLibraryHostFactory() android.Module { module, _ := NewRustLibrary(android.HostSupported) @@ -161,12 +235,44 @@ func RustLibraryRlibHostFactory() android.Module { return module.Init() } +// rust_library_static_host produces a static library. +func RustLibraryStaticHostFactory() android.Module { + module, library := NewRustLibrary(android.HostSupported) + library.BuildOnlyStatic() + return module.Init() +} + +// rust_library_shared_host produces an shared library. +func RustLibrarySharedHostFactory() android.Module { + module, library := NewRustLibrary(android.HostSupported) + library.BuildOnlyShared() + return module.Init() +} + func (library *libraryDecorator) BuildOnlyDylib() { library.MutatedProperties.BuildRlib = false + library.MutatedProperties.BuildShared = false + library.MutatedProperties.BuildStatic = false + } func (library *libraryDecorator) BuildOnlyRlib() { library.MutatedProperties.BuildDylib = false + library.MutatedProperties.BuildShared = false + library.MutatedProperties.BuildStatic = false +} + +func (library *libraryDecorator) BuildOnlyStatic() { + library.MutatedProperties.BuildShared = false + library.MutatedProperties.BuildRlib = false + library.MutatedProperties.BuildDylib = false + +} + +func (library *libraryDecorator) BuildOnlyShared() { + library.MutatedProperties.BuildStatic = false + library.MutatedProperties.BuildRlib = false + library.MutatedProperties.BuildDylib = false } func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) { @@ -174,8 +280,10 @@ func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorat library := &libraryDecorator{ MutatedProperties: LibraryMutatedProperties{ - BuildDylib: true, - BuildRlib: true, + BuildDylib: true, + BuildRlib: true, + BuildShared: true, + BuildStatic: true, }, baseCompiler: NewBaseCompiler("lib", "lib64"), } @@ -194,7 +302,7 @@ func (library *libraryDecorator) compilerProps() []interface{} { func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { deps = library.baseCompiler.compilerDeps(ctx, deps) - if ctx.toolchain().Bionic() && library.dylib() { + if ctx.toolchain().Bionic() && (library.dylib() || library.shared()) { deps = library.baseCompiler.bionicDeps(ctx, deps) } @@ -208,6 +316,13 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa flags.RustFlags = append(flags.RustFlags, deps.depFlags...) + if library.dylib() || library.shared() { + // We need prefer-dynamic for now to avoid linking in the static stdlib. See: + // https://github.com/rust-lang/rust/issues/19680 + // https://github.com/rust-lang/rust/issues/34909 + flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic") + } + if library.rlib() { fileName := library.getStem(ctx) + ctx.toolchain().RlibSuffix() outputFile = android.PathForModuleOut(ctx, fileName) @@ -217,16 +332,23 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa fileName := library.getStem(ctx) + ctx.toolchain().DylibSuffix() outputFile = android.PathForModuleOut(ctx, fileName) - // We need prefer-dynamic for now to avoid linking in the static stdlib. See: - // https://github.com/rust-lang/rust/issues/19680 - // https://github.com/rust-lang/rust/issues/34909 - flags.RustFlags = append(flags.RustFlags, "-C prefer-dynamic") - TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs) + } else if library.static() { + fileName := library.getStem(ctx) + ctx.toolchain().StaticLibSuffix() + outputFile = android.PathForModuleOut(ctx, fileName) + + TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs) + } else if library.shared() { + fileName := library.getStem(ctx) + ctx.toolchain().SharedLibSuffix() + outputFile = android.PathForModuleOut(ctx, fileName) + + TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs) } - library.reexportDirs(deps.linkDirs...) - library.reexportDepFlags(deps.depFlags...) + if library.rlib() || library.dylib() { + library.reexportDirs(deps.linkDirs...) + library.reexportDepFlags(deps.depFlags...) + } library.unstrippedOutputFile = outputFile return outputFile @@ -236,19 +358,25 @@ func LibraryMutator(mctx android.BottomUpMutatorContext) { if m, ok := mctx.Module().(*Module); ok && m.compiler != nil { switch library := m.compiler.(type) { case libraryInterface: - if library.buildRlib() && library.buildDylib() { - modules := mctx.CreateLocalVariations("rlib", "dylib") - rlib := modules[0].(*Module) - dylib := modules[1].(*Module) - rlib.compiler.(libraryInterface).setRlib() - dylib.compiler.(libraryInterface).setDylib() - } else if library.buildRlib() { - modules := mctx.CreateLocalVariations("rlib") - modules[0].(*Module).compiler.(libraryInterface).setRlib() - } else if library.buildDylib() { - modules := mctx.CreateLocalVariations("dylib") - modules[0].(*Module).compiler.(libraryInterface).setDylib() + // We only build the rust library variants here. This assumes that + // LinkageMutator runs first and there's an empty variant + // if rust variants are required. + if !library.static() && !library.shared() { + if library.buildRlib() && library.buildDylib() { + modules := mctx.CreateLocalVariations("rlib", "dylib") + rlib := modules[0].(*Module) + dylib := modules[1].(*Module) + + rlib.compiler.(libraryInterface).setRlib() + dylib.compiler.(libraryInterface).setDylib() + } else if library.buildRlib() { + modules := mctx.CreateLocalVariations("rlib") + modules[0].(*Module).compiler.(libraryInterface).setRlib() + } else if library.buildDylib() { + modules := mctx.CreateLocalVariations("dylib") + modules[0].(*Module).compiler.(libraryInterface).setDylib() + } } } } diff --git a/rust/library_test.go b/rust/library_test.go index bf8643efb..66bcd20fb 100644 --- a/rust/library_test.go +++ b/rust/library_test.go @@ -29,19 +29,37 @@ func TestLibraryVariants(t *testing.T) { crate_name: "foo", }`) - // Test both variants are being built. + // Test all variants are being built. libfooRlib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_rlib").Output("libfoo.rlib") - libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.so") + libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.dylib.so") + libfooStatic := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_static").Output("libfoo.a") + libfooShared := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_shared").Output("libfoo.so") + + rlibCrateType := "rlib" + dylibCrateType := "dylib" + sharedCrateType := "cdylib" + staticCrateType := "static" // Test crate type for rlib is correct. - if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type=rlib") { - t.Errorf("missing crate-type for libfoo rlib, rustcFlags: %#v", libfooRlib.Args["rustcFlags"]) + if !strings.Contains(libfooRlib.Args["rustcFlags"], "crate-type="+rlibCrateType) { + t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", rlibCrateType, libfooRlib.Args["rustcFlags"]) } // Test crate type for dylib is correct. - if !strings.Contains(libfooDylib.Args["rustcFlags"], "crate-type=dylib") { - t.Errorf("missing crate-type for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) + if !strings.Contains(libfooDylib.Args["rustcFlags"], "crate-type="+dylibCrateType) { + t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", dylibCrateType, libfooDylib.Args["rustcFlags"]) } + + // Test crate type for C static libraries is correct. + if !strings.Contains(libfooStatic.Args["rustcFlags"], "crate-type="+staticCrateType) { + t.Errorf("missing crate-type for static variant, expecting %#v, rustcFlags: %#v", staticCrateType, libfooStatic.Args["rustcFlags"]) + } + + // Test crate type for C shared libraries is correct. + if !strings.Contains(libfooShared.Args["rustcFlags"], "crate-type="+sharedCrateType) { + t.Errorf("missing crate-type for shared variant, expecting %#v, got rustcFlags: %#v", sharedCrateType, libfooShared.Args["rustcFlags"]) + } + } // Test that dylibs are not statically linking the standard library. @@ -53,7 +71,7 @@ func TestDylibPreferDynamic(t *testing.T) { crate_name: "foo", }`) - libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.so") + libfooDylib := ctx.ModuleForTests("libfoo", "linux_glibc_x86_64_dylib").Output("libfoo.dylib.so") if !strings.Contains(libfooDylib.Args["rustcFlags"], "prefer-dynamic") { t.Errorf("missing prefer-dynamic flag for libfoo dylib, rustcFlags: %#v", libfooDylib.Args["rustcFlags"]) diff --git a/rust/rust.go b/rust/rust.go index 707de4b91..ce81b9152 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -15,6 +15,7 @@ package rust import ( + "fmt" "strings" "github.com/google/blueprint" @@ -74,6 +75,85 @@ type Module struct { outputFile android.OptionalPath } +func (mod *Module) BuildStubs() bool { + return false +} + +func (mod *Module) HasStubsVariants() bool { + return false +} + +func (mod *Module) SelectedStl() string { + return "" +} + +func (mod *Module) ApiLevel() string { + panic(fmt.Errorf("Called ApiLevel on Rust module %q; stubs libraries are not yet supported.", mod.BaseModuleName())) +} + +func (mod *Module) Static() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + return library.static() + } + } + panic(fmt.Errorf("Static called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) Shared() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + return library.static() + } + } + panic(fmt.Errorf("Shared called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) Toc() android.OptionalPath { + if mod.compiler != nil { + if _, ok := mod.compiler.(libraryInterface); ok { + return android.OptionalPath{} + } + } + panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) OnlyInRecovery() bool { + return false +} + +func (mod *Module) UseVndk() bool { + return false +} + +func (mod *Module) MustUseVendorVariant() bool { + return false +} + +func (mod *Module) IsVndk() bool { + return false +} + +func (mod *Module) HasVendorVariant() bool { + return false +} + +func (mod *Module) SdkVersion() string { + return "" +} + +func (mod *Module) ToolchainLibrary() bool { + return false +} + +func (mod *Module) NdkPrebuiltStl() bool { + return false +} + +func (mod *Module) StubDecorator() bool { + return false +} + type Deps struct { Dylibs []string Rlibs []string @@ -150,6 +230,121 @@ func (mod *Module) CrateName() string { return strings.Replace(mod.BaseModuleName(), "-", "_", -1) } +func (mod *Module) CcLibrary() bool { + if mod.compiler != nil { + if _, ok := mod.compiler.(*libraryDecorator); ok { + return true + } + } + return false +} + +func (mod *Module) CcLibraryInterface() bool { + if mod.compiler != nil { + if _, ok := mod.compiler.(libraryInterface); ok { + return true + } + } + return false +} + +func (mod *Module) IncludeDirs(ctx android.BaseModuleContext) android.Paths { + if mod.compiler != nil { + if library, ok := mod.compiler.(*libraryDecorator); ok { + return android.PathsForSource(ctx, library.Properties.Include_dirs) + } + } + panic(fmt.Errorf("IncludeDirs called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) SetStatic() { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + library.setStatic() + return + } + } + panic(fmt.Errorf("SetStatic called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) SetShared() { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + library.setShared() + return + } + } + panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) SetBuildStubs() { + panic("SetBuildStubs not yet implemented for rust modules") +} + +func (mod *Module) SetStubsVersions(string) { + panic("SetStubsVersions not yet implemented for rust modules") +} + +func (mod *Module) BuildStaticVariant() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + return library.buildStatic() + } + } + panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) BuildSharedVariant() bool { + if mod.compiler != nil { + if library, ok := mod.compiler.(libraryInterface); ok { + return library.buildShared() + } + } + panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName())) +} + +// Rust module deps don't have a link order (?) +func (mod *Module) SetDepsInLinkOrder([]android.Path) {} + +func (mod *Module) GetDepsInLinkOrder() []android.Path { + return []android.Path{} +} + +func (mod *Module) GetStaticVariant() cc.LinkableInterface { + return nil +} + +func (mod *Module) Module() android.Module { + return mod +} + +func (mod *Module) StubsVersions() []string { + // For now, Rust has no stubs versions. + if mod.compiler != nil { + if _, ok := mod.compiler.(*libraryDecorator); ok { + return []string{} + } + } + panic(fmt.Errorf("StubsVersions called on non-library module: %q", mod.BaseModuleName())) +} + +func (mod *Module) OutputFile() android.OptionalPath { + return mod.outputFile +} + +func (mod *Module) InRecovery() bool { + // For now, Rust has no notion of the recovery image + return false +} +func (mod *Module) HasStaticVariant() bool { + if mod.GetStaticVariant() != nil { + return true + } + return false +} + +var _ cc.LinkableInterface = (*Module)(nil) + func (mod *Module) Init() android.Module { mod.AddProperties(&mod.Properties) @@ -311,13 +506,12 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { directRlibDeps := []*Module{} directDylibDeps := []*Module{} directProcMacroDeps := []*Module{} - directSharedLibDeps := []*(cc.Module){} - directStaticLibDeps := []*(cc.Module){} + directSharedLibDeps := [](cc.LinkableInterface){} + directStaticLibDeps := [](cc.LinkableInterface){} ctx.VisitDirectDeps(func(dep android.Module) { depName := ctx.OtherModuleName(dep) depTag := ctx.OtherModuleDependencyTag(dep) - if rustDep, ok := dep.(*Module); ok { //Handle Rust Modules @@ -365,16 +559,19 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } } - } else if ccDep, ok := dep.(*cc.Module); ok { - //Handle C dependencies + } - if ccDep.Target().Os != ctx.Os() { - ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) - return - } - if ccDep.Target().Arch.ArchType != ctx.Arch().ArchType { - ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName) - return + if ccDep, ok := dep.(cc.LinkableInterface); ok { + //Handle C dependencies + if _, ok := ccDep.(*Module); !ok { + if ccDep.Module().Target().Os != ctx.Os() { + ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) + return + } + if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType { + ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName) + return + } } linkFile := ccDep.OutputFile() @@ -387,25 +584,25 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { exportDep := false switch depTag { - case cc.StaticDepTag(): + case cc.StaticDepTag: depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.depFlags = append(depPaths.depFlags, "-l"+libName) directStaticLibDeps = append(directStaticLibDeps, ccDep) mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName) - case cc.SharedDepTag(): + case cc.SharedDepTag: depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.depFlags = append(depPaths.depFlags, "-l"+libName) directSharedLibDeps = append(directSharedLibDeps, ccDep) mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName) exportDep = true - case cc.CrtBeginDepTag(): + case cc.CrtBeginDepTag: depPaths.CrtBegin = linkFile - case cc.CrtEndDepTag(): + case cc.CrtEndDepTag: depPaths.CrtEnd = linkFile } // Make sure these dependencies are propagated - if lib, ok := mod.compiler.(*libraryDecorator); ok && (exportDep || lib.rlib()) { + if lib, ok := mod.compiler.(*libraryDecorator); ok && exportDep { lib.linkDirs = append(lib.linkDirs, linkPath) lib.depFlags = append(lib.depFlags, "-l"+libName) } else if procMacro, ok := mod.compiler.(*procMacroDecorator); ok && exportDep { @@ -457,8 +654,8 @@ func linkPathFromFilePath(filepath android.Path) string { } func libNameFromFilePath(filepath android.Path) string { libName := strings.Split(filepath.Base(), filepath.Ext())[0] - if strings.Contains(libName, "lib") { - libName = strings.Split(libName, "lib")[1] + if strings.HasPrefix(libName, "lib") { + libName = libName[3:] } return libName } @@ -472,23 +669,37 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) { ctx.ctx = ctx deps := mod.deps(ctx) - - actx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}, rlibDepTag, deps.Rlibs...) - actx.AddVariationDependencies([]blueprint.Variation{{Mutator: "rust_libraries", Variation: "dylib"}}, dylibDepTag, deps.Dylibs...) - - ccDepVariations := []blueprint.Variation{} - ccDepVariations = append(ccDepVariations, blueprint.Variation{Mutator: "version", Variation: ""}) + commonDepVariations := []blueprint.Variation{} + commonDepVariations = append(commonDepVariations, + blueprint.Variation{Mutator: "version", Variation: ""}) if !mod.Host() { - ccDepVariations = append(ccDepVariations, blueprint.Variation{Mutator: "image", Variation: "core"}) + commonDepVariations = append(commonDepVariations, + blueprint.Variation{Mutator: "image", Variation: "core"}) } - actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "shared"}), cc.SharedDepTag(), deps.SharedLibs...) - actx.AddVariationDependencies(append(ccDepVariations, blueprint.Variation{Mutator: "link", Variation: "static"}), cc.StaticDepTag(), deps.StaticLibs...) + + actx.AddVariationDependencies( + append(commonDepVariations, []blueprint.Variation{ + {Mutator: "rust_libraries", Variation: "rlib"}, + {Mutator: "link", Variation: ""}}...), + rlibDepTag, deps.Rlibs...) + actx.AddVariationDependencies( + append(commonDepVariations, []blueprint.Variation{ + {Mutator: "rust_libraries", Variation: "dylib"}, + {Mutator: "link", Variation: ""}}...), + dylibDepTag, deps.Dylibs...) + + actx.AddVariationDependencies(append(commonDepVariations, + blueprint.Variation{Mutator: "link", Variation: "shared"}), + cc.SharedDepTag, deps.SharedLibs...) + actx.AddVariationDependencies(append(commonDepVariations, + blueprint.Variation{Mutator: "link", Variation: "static"}), + cc.StaticDepTag, deps.StaticLibs...) if deps.CrtBegin != "" { - actx.AddVariationDependencies(ccDepVariations, cc.CrtBeginDepTag(), deps.CrtBegin) + actx.AddVariationDependencies(commonDepVariations, cc.CrtBeginDepTag, deps.CrtBegin) } if deps.CrtEnd != "" { - actx.AddVariationDependencies(ccDepVariations, cc.CrtEndDepTag(), deps.CrtEnd) + actx.AddVariationDependencies(commonDepVariations, cc.CrtEndDepTag, deps.CrtEnd) } // proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy. diff --git a/rust/rust_test.go b/rust/rust_test.go index 0c8d35586..eb04e7257 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -101,12 +101,20 @@ func testRustError(t *testing.T, pattern string, bp string) { // Test that we can extract the lib name from a lib path. func TestLibNameFromFilePath(t *testing.T) { - barPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so") - libName := libNameFromFilePath(barPath) - expectedResult := "bar" + libBarPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/libbar.so") + libLibPath := android.PathForTesting("out/soong/.intermediates/external/libbar/libbar/linux_glibc_x86_64_shared/liblib.dylib.so") - if libName != expectedResult { - t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libName) + libBarName := libNameFromFilePath(libBarPath) + libLibName := libNameFromFilePath(libLibPath) + + expectedResult := "bar" + if libBarName != expectedResult { + t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libBarName) + } + + expectedResult = "lib.dylib" + if libLibName != expectedResult { + t.Errorf("libNameFromFilePath returned the wrong name; expected '%#v', got '%#v'", expectedResult, libLibPath) } } @@ -140,12 +148,20 @@ func TestDefaultCrateName(t *testing.T) { // Test to make sure dependencies are being picked up correctly. func TestDepsTracking(t *testing.T) { ctx := testRust(t, ` + rust_library_host_static { + name: "libstatic", + srcs: ["foo.rs"], + } + rust_library_host_shared { + name: "libshared", + srcs: ["foo.rs"], + } rust_library_host_dylib { - name: "libfoo", + name: "libdylib", srcs: ["foo.rs"], } rust_library_host_rlib { - name: "libbar", + name: "librlib", srcs: ["foo.rs"], } rust_proc_macro { @@ -154,20 +170,22 @@ func TestDepsTracking(t *testing.T) { } rust_binary_host { name: "fizz-buzz", - dylibs: ["libfoo"], - rlibs: ["libbar"], + dylibs: ["libdylib"], + rlibs: ["librlib"], proc_macros: ["libpm"], + static_libs: ["libstatic"], + shared_libs: ["libshared"], srcs: ["foo.rs"], } `) module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module) // Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up. - if !android.InList("libfoo", module.Properties.AndroidMkDylibs) { + if !android.InList("libdylib", module.Properties.AndroidMkDylibs) { t.Errorf("Dylib dependency not detected (dependency missing from AndroidMkDylibs)") } - if !android.InList("libbar", module.Properties.AndroidMkRlibs) { + if !android.InList("librlib", module.Properties.AndroidMkRlibs) { t.Errorf("Rlib dependency not detected (dependency missing from AndroidMkRlibs)") } @@ -175,6 +193,13 @@ func TestDepsTracking(t *testing.T) { t.Errorf("Proc_macro dependency not detected (dependency missing from AndroidMkProcMacroLibs)") } + if !android.InList("libshared", module.Properties.AndroidMkSharedLibs) { + t.Errorf("Shared library dependency not detected (dependency missing from AndroidMkSharedLibs)") + } + + if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) { + t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)") + } } // Test to make sure proc_macros use host variants when building device modules. diff --git a/rust/testing.go b/rust/testing.go index 92347f1f3..cd6308434 100644 --- a/rust/testing.go +++ b/rust/testing.go @@ -174,18 +174,23 @@ func CreateTestContext(bp string) *android.TestContext { ctx.RegisterModuleType("rust_library_host_dylib", android.ModuleFactoryAdaptor(RustLibraryDylibHostFactory)) ctx.RegisterModuleType("rust_library_rlib", android.ModuleFactoryAdaptor(RustLibraryRlibFactory)) ctx.RegisterModuleType("rust_library_dylib", android.ModuleFactoryAdaptor(RustLibraryDylibFactory)) + ctx.RegisterModuleType("rust_library_shared", android.ModuleFactoryAdaptor(RustLibrarySharedFactory)) + ctx.RegisterModuleType("rust_library_static", android.ModuleFactoryAdaptor(RustLibraryStaticFactory)) + ctx.RegisterModuleType("rust_library_host_shared", android.ModuleFactoryAdaptor(RustLibrarySharedHostFactory)) + ctx.RegisterModuleType("rust_library_host_static", android.ModuleFactoryAdaptor(RustLibraryStaticHostFactory)) ctx.RegisterModuleType("rust_proc_macro", android.ModuleFactoryAdaptor(ProcMacroFactory)) ctx.RegisterModuleType("rust_prebuilt_dylib", android.ModuleFactoryAdaptor(PrebuiltDylibFactory)) ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(cc.ToolchainLibraryFactory)) ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { - ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() - + // cc mutators ctx.BottomUp("image", cc.ImageMutator).Parallel() ctx.BottomUp("link", cc.LinkageMutator).Parallel() ctx.BottomUp("version", cc.VersionMutator).Parallel() ctx.BottomUp("begin", cc.BeginMutator).Parallel() - }) + // rust mutators + ctx.BottomUp("rust_libraries", LibraryMutator).Parallel() + }) bp = bp + GatherRequiredDepsForTest() mockFS := map[string][]byte{