diff --git a/android/apex.go b/android/apex.go index c01b71692..3039e7944 100644 --- a/android/apex.go +++ b/android/apex.go @@ -145,11 +145,6 @@ type ApexModule interface { // check-platform-availability mutator in the apex package. SetNotAvailableForPlatform() - // Returns the highest version which is <= maxSdkVersion. - // For example, with maxSdkVersion is 10 and versionList is [9,11] - // it returns 9 as string - ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error) - // List of APEXes that this module tests. The module has access to // the private part of the listed APEXes even when it is not included in the // APEXes. @@ -310,20 +305,6 @@ func (m *ApexModuleBase) DepIsInSameApex(ctx BaseModuleContext, dep Module) bool return true } -func (m *ApexModuleBase) ChooseSdkVersion(ctx BaseModuleContext, versionList []string, maxSdkVersion ApiLevel) (string, error) { - for i := range versionList { - version := versionList[len(versionList)-i-1] - ver, err := ApiLevelFromUser(ctx, version) - if err != nil { - return "", err - } - if ver.LessThanOrEqualTo(maxSdkVersion) { - return version, nil - } - } - return "", fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion, versionList) -} - func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { for _, n := range m.ApexProperties.Apex_available { if n == AvailableToPlatform || n == AvailableToAnyApex || n == AvailableToGkiApex { diff --git a/android/depset.go b/android/depset.go index f70709423..60ebcacc8 100644 --- a/android/depset.go +++ b/android/depset.go @@ -71,24 +71,26 @@ func (o DepSetOrder) String() string { // NewDepSet returns an immutable DepSet with the given order, direct and transitive contents. func NewDepSet(order DepSetOrder, direct Paths, transitive []*DepSet) *DepSet { var directCopy Paths - var transitiveCopy []*DepSet + transitiveCopy := make([]*DepSet, 0, len(transitive)) + + for _, dep := range transitive { + if dep != nil { + if dep.order != order { + panic(fmt.Errorf("incompatible order, new DepSet is %s but transitive DepSet is %s", + order, dep.order)) + } + transitiveCopy = append(transitiveCopy, dep) + } + } + if order == TOPOLOGICAL { directCopy = ReversePaths(direct) - transitiveCopy = reverseDepSets(transitive) + reverseDepSetsInPlace(transitiveCopy) } else { // Use copy instead of append(nil, ...) to make a slice that is exactly the size of the input // slice. The DepSet is immutable, there is no need for additional capacity. directCopy = make(Paths, len(direct)) copy(directCopy, direct) - transitiveCopy = make([]*DepSet, len(transitive)) - copy(transitiveCopy, transitive) - } - - for _, dep := range transitive { - if dep.order != order { - panic(fmt.Errorf("incompatible order, new DepSet is %s but transitive DepSet is %s", - order, dep.order)) - } } return &DepSet{ @@ -157,6 +159,9 @@ func (d *DepSet) walk(visit func(Paths)) { // its transitive dependencies, in which case the ordering of the duplicated element is not // guaranteed). func (d *DepSet) ToList() Paths { + if d == nil { + return nil + } var list Paths d.walk(func(paths Paths) { list = append(list, paths...) @@ -181,10 +186,9 @@ func reversePathsInPlace(list Paths) { } } -func reverseDepSets(list []*DepSet) []*DepSet { - ret := make([]*DepSet, len(list)) - for i := range list { - ret[i] = list[len(list)-1-i] +func reverseDepSetsInPlace(list []*DepSet) { + for i, j := 0, len(list)-1; i < j; i, j = i+1, j-1 { + list[i], list[j] = list[j], list[i] } - return ret + } diff --git a/apex/apex_test.go b/apex/apex_test.go index cf2c9533b..96a7a575a 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -1319,6 +1319,7 @@ func TestApexWithSystemLibsStubs(t *testing.T) { cc_library { name: "mylib", srcs: ["mylib.cpp"], + system_shared_libs: ["libc", "libm"], shared_libs: ["libdl#27"], stl: "none", apex_available: [ "myapex" ], diff --git a/cc/androidmk.go b/cc/androidmk.go index a2549b8e7..899d3398a 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -186,17 +186,17 @@ func makeOverrideModuleNames(ctx AndroidMkContext, overrides []string) []string } func (library *libraryDecorator) androidMkWriteExportedFlags(entries *android.AndroidMkEntries) { - exportedFlags := library.exportedFlags() - for _, dir := range library.exportedDirs() { + exportedFlags := library.flagExporter.flags + for _, dir := range library.flagExporter.dirs { exportedFlags = append(exportedFlags, "-I"+dir.String()) } - for _, dir := range library.exportedSystemDirs() { + for _, dir := range library.flagExporter.systemDirs { exportedFlags = append(exportedFlags, "-isystem "+dir.String()) } if len(exportedFlags) > 0 { entries.AddStrings("LOCAL_EXPORT_CFLAGS", exportedFlags...) } - exportedDeps := library.exportedDeps() + exportedDeps := library.flagExporter.deps if len(exportedDeps) > 0 { entries.AddStrings("LOCAL_EXPORT_C_INCLUDE_DEPS", exportedDeps.Strings()...) } diff --git a/cc/cc.go b/cc/cc.go index 81885509b..8560042ca 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -130,6 +130,9 @@ type PathDeps struct { // Paths to .a files StaticLibs, LateStaticLibs, WholeStaticLibs android.Paths + // Transitive static library dependencies of static libraries for use in ordering. + TranstiveStaticLibrariesForOrdering *android.DepSet + // Paths to .o files Objs Objects // Paths to .o files in dependencies that provide them. Note that these lists @@ -546,9 +549,7 @@ var ( dataLibDepTag = dependencyTag{name: "data lib"} runtimeDepTag = dependencyTag{name: "runtime lib"} testPerSrcDepTag = dependencyTag{name: "test_per_src"} - testForDepTag = dependencyTag{name: "test for apex"} - - stubImplDepTag = copyDirectlyInAnyApexDependencyTag{name: "stub_impl"} + stubImplDepTag = dependencyTag{name: "stub_impl"} ) type copyDirectlyInAnyApexDependencyTag dependencyTag @@ -618,13 +619,8 @@ type Module struct { // Flags used to compile this module flags Flags - // When calling a linker, if module A depends on module B, then A must precede B in its command - // line invocation. depsInLinkOrder stores the proper ordering of all of the transitive - // deps of this module - depsInLinkOrder android.Paths - // only non-nil when this is a shared library that reuses the objects of a static library - staticVariant LinkableInterface + staticAnalogue *StaticLibraryInfo makeLinkType string // Kythe (source file indexer) paths for this compilation module @@ -722,34 +718,6 @@ func (c *Module) AlwaysSdk() bool { return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only) } -func (c *Module) IncludeDirs() 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 { @@ -1156,41 +1124,6 @@ func (c *Module) isSnapshotPrebuilt() bool { return false } -func (c *Module) ExportedIncludeDirs() android.Paths { - if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok { - return flagsProducer.exportedDirs() - } - return nil -} - -func (c *Module) ExportedSystemIncludeDirs() android.Paths { - if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok { - return flagsProducer.exportedSystemDirs() - } - return nil -} - -func (c *Module) ExportedFlags() []string { - if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok { - return flagsProducer.exportedFlags() - } - return nil -} - -func (c *Module) ExportedDeps() android.Paths { - if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok { - return flagsProducer.exportedDeps() - } - return nil -} - -func (c *Module) ExportedGeneratedHeaders() android.Paths { - if flagsProducer, ok := c.linker.(exportedFlagsProducer); ok { - return flagsProducer.exportedGeneratedHeaders() - } - return nil -} - func (c *Module) ExcludeFromVendorSnapshot() bool { return Bool(c.Properties.Exclude_from_vendor_snapshot) } @@ -1454,65 +1387,6 @@ func (c *Module) Symlinks() []string { return nil } -// orderDeps reorders dependencies into a list such that if module A depends on B, then -// A will precede B in the resultant list. -// This is convenient for passing into a linker. -// Note that directSharedDeps should be the analogous static library for each shared lib dep -func orderDeps(directStaticDeps []android.Path, directSharedDeps []android.Path, allTransitiveDeps map[android.Path][]android.Path) (orderedAllDeps []android.Path, orderedDeclaredDeps []android.Path) { - // If A depends on B, then - // Every list containing A will also contain B later in the list - // So, after concatenating all lists, the final instance of B will have come from the same - // original list as the final instance of A - // So, the final instance of B will be later in the concatenation than the final A - // So, keeping only the final instance of A and of B ensures that A is earlier in the output - // list than B - for _, dep := range directStaticDeps { - orderedAllDeps = append(orderedAllDeps, dep) - orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...) - } - for _, dep := range directSharedDeps { - orderedAllDeps = append(orderedAllDeps, dep) - orderedAllDeps = append(orderedAllDeps, allTransitiveDeps[dep]...) - } - - orderedAllDeps = android.LastUniquePaths(orderedAllDeps) - - // We don't want to add any new dependencies into directStaticDeps (to allow the caller to - // intentionally exclude or replace any unwanted transitive dependencies), so we limit the - // resultant list to only what the caller has chosen to include in directStaticDeps - _, orderedDeclaredDeps = android.FilterPathList(orderedAllDeps, directStaticDeps) - - return orderedAllDeps, orderedDeclaredDeps -} - -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 { - // The OutputFile may not be valid for a variant not present, and the AllowMissingDependencies flag is set. - if dep.OutputFile().Valid() { - allTransitiveDeps[dep.OutputFile().Path()] = dep.GetDepsInLinkOrder() - staticDepFiles = append(staticDepFiles, dep.OutputFile().Path()) - } - } - sharedDepFiles := []android.Path{} - for _, sharedDep := range sharedDeps { - 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 - depsInLinkOrder, results = orderDeps(staticDepFiles, sharedDepFiles, allTransitiveDeps) - module.SetDepsInLinkOrder(depsInLinkOrder) - - return results -} - func (c *Module) IsTestPerSrcAllTestsVariation() bool { test, ok := c.linker.(testPerSrc) return ok && test.isAllTestsVariation() @@ -1896,29 +1770,11 @@ func (c *Module) addSharedLibDependenciesWithVersions(ctx android.BottomUpMutato variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version}) depTag.explicitlyVersioned = true } - var deps []blueprint.Module - if far { - deps = ctx.AddFarVariationDependencies(variations, depTag, name) - } else { - deps = ctx.AddVariationDependencies(variations, depTag, name) - } - // If the version is not specified, add dependency to all stubs libraries. - // The stubs library will be used when the depending module is built for APEX and - // the dependent module is not in the same APEX. - if version == "" && CanBeOrLinkAgainstVersionVariants(c) { - if dep, ok := deps[0].(*Module); ok { - for _, ver := range dep.AllStubsVersions() { - // Note that depTag.ExplicitlyVersioned is false in this case. - versionVariations := append(variations, - blueprint.Variation{Mutator: "version", Variation: ver}) - if far { - ctx.AddFarVariationDependencies(versionVariations, depTag, name) - } else { - ctx.AddVariationDependencies(versionVariations, depTag, name) - } - } - } + if far { + ctx.AddFarVariationDependencies(variations, depTag, name) + } else { + ctx.AddVariationDependencies(variations, depTag, name) } } @@ -2384,19 +2240,49 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { } } +// Returns the highest version which is <= maxSdkVersion. +// For example, with maxSdkVersion is 10 and versionList is [9,11] +// it returns 9 as string. The list of stubs must be in order from +// oldest to newest. +func (c *Module) chooseSdkVersion(ctx android.PathContext, stubsInfo []SharedLibraryStubsInfo, + maxSdkVersion android.ApiLevel) (SharedLibraryStubsInfo, error) { + + for i := range stubsInfo { + stubInfo := stubsInfo[len(stubsInfo)-i-1] + var ver android.ApiLevel + if stubInfo.Version == "" { + ver = android.FutureApiLevel + } else { + var err error + ver, err = android.ApiLevelFromUser(ctx, stubInfo.Version) + if err != nil { + return SharedLibraryStubsInfo{}, err + } + } + if ver.LessThanOrEqualTo(maxSdkVersion) { + return stubInfo, nil + } + } + var versionList []string + for _, stubInfo := range stubsInfo { + versionList = append(versionList, stubInfo.Version) + } + return SharedLibraryStubsInfo{}, fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion.String(), versionList) +} + // Convert dependencies to paths. Returns a PathDeps containing paths func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { var depPaths PathDeps - directStaticDeps := []LinkableInterface{} - directSharedDeps := []LinkableInterface{} + var directStaticDeps []StaticLibraryInfo + var directSharedDeps []SharedLibraryInfo - reexportExporter := func(exporter exportedFlagsProducer) { - depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.exportedDirs()...) - depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.exportedSystemDirs()...) - depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.exportedFlags()...) - depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.exportedDeps()...) - depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.exportedGeneratedHeaders()...) + reexportExporter := func(exporter FlagExporterInfo) { + depPaths.ReexportedDirs = append(depPaths.ReexportedDirs, exporter.IncludeDirs...) + depPaths.ReexportedSystemDirs = append(depPaths.ReexportedSystemDirs, exporter.SystemIncludeDirs...) + depPaths.ReexportedFlags = append(depPaths.ReexportedFlags, exporter.Flags...) + depPaths.ReexportedDeps = append(depPaths.ReexportedDeps, exporter.Deps...) + depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.GeneratedHeaders...) } // For the dependency from platform to apex, use the latest stubs @@ -2481,24 +2367,14 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - // re-exporting flags if depTag == reuseObjTag { // reusing objects only make sense for cc.Modules. - if ccReuseDep, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() { - c.staticVariant = ccDep - objs, exporter := ccReuseDep.compiler.(libraryInterface).reuseObjs() - depPaths.Objs = depPaths.Objs.Append(objs) - reexportExporter(exporter) - return - } - } - - if depTag == staticVariantTag { - // staticVariants are a cc.Module specific concept. - if _, ok := ccDep.(*Module); ok && ccDep.CcLibraryInterface() { - c.staticVariant = ccDep - return - } + staticAnalogue := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo) + objs := staticAnalogue.ReuseObjects + depPaths.Objs = depPaths.Objs.Append(objs) + depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo) + reexportExporter(depExporterInfo) + return } checkLinkType(ctx, c, ccDep, depTag) @@ -2511,103 +2387,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return } - if ccDep.CcLibrary() && !libDepTag.static() { - depIsStubs := ccDep.BuildStubs() - depHasStubs := CanBeOrLinkAgainstVersionVariants(c) && ccDep.HasStubsVariants() - depInSameApexes := android.DirectlyInAllApexes(apexInfo, depName) - depInPlatform := !dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() - - var useThisDep bool - if depIsStubs && libDepTag.explicitlyVersioned { - // Always respect dependency to the versioned stubs (i.e. libX#10) - useThisDep = true - } else if !depHasStubs { - // Use non-stub variant if that is the only choice - // (i.e. depending on a lib without stubs.version property) - useThisDep = true - } else if apexInfo.IsForPlatform() { - // If not building for APEX, use stubs only when it is from - // an APEX (and not from platform) - useThisDep = (depInPlatform != depIsStubs) - if c.bootstrap() { - // However, for host, ramdisk, recovery or bootstrap modules, - // always link to non-stub variant - useThisDep = !depIsStubs - } - // Another exception: if this module is bundled with an APEX, then - // it is linked with the non-stub variant of a module in the APEX - // as if this is part of the APEX. - testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo) - for _, apexContents := range testFor.ApexContents { - if apexContents.DirectlyInApex(depName) { - useThisDep = !depIsStubs - break - } - } - } else { - // If building for APEX, use stubs when the parent is in any APEX that - // the child is not in. - useThisDep = (depInSameApexes != depIsStubs) - } - - // when to use (unspecified) stubs, check min_sdk_version and choose the right one - if useThisDep && depIsStubs && !libDepTag.explicitlyVersioned { - versionToUse, err := c.ChooseSdkVersion(ctx, ccDep.StubsVersions(), c.apexSdkVersion) - if err != nil { - ctx.OtherModuleErrorf(dep, err.Error()) - return - } - if versionToUse != ccDep.StubsVersion() { - useThisDep = false - } - } - - if !useThisDep { - return // stop processing this dep - } - } - if c.UseVndk() { - if m, ok := ccDep.(*Module); ok && m.IsStubs() { // LLNDK - // by default, use current version of LLNDK - versionToUse := "" - versions := m.AllStubsVersions() - if apexInfo.ApexVariationName != "" && len(versions) > 0 { - // if this is for use_vendor apex && dep has stubsVersions - // apply the same rule of apex sdk enforcement to choose right version - var err error - versionToUse, err = c.ChooseSdkVersion(ctx, versions, c.apexSdkVersion) - if err != nil { - ctx.OtherModuleErrorf(dep, err.Error()) - return - } - } - if versionToUse != ccDep.StubsVersion() { - return - } - } - } - - depPaths.IncludeDirs = append(depPaths.IncludeDirs, ccDep.IncludeDirs()...) - - // Exporting flags only makes sense for cc.Modules - if _, ok := ccDep.(*Module); ok { - if i, ok := ccDep.(*Module).linker.(exportedFlagsProducer); ok { - depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, i.exportedSystemDirs()...) - depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, i.exportedDeps()...) - depPaths.Flags = append(depPaths.Flags, i.exportedFlags()...) - - if libDepTag.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()...) - } - } - } + depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo) var ptr *android.Paths var depPtr *android.Paths @@ -2618,6 +2398,64 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { case libDepTag.header(): // nothing case libDepTag.shared(): + if !ctx.OtherModuleHasProvider(dep, SharedLibraryInfoProvider) { + if !ctx.Config().AllowMissingDependencies() { + ctx.ModuleErrorf("module %q is not a shared library", depName) + } else { + ctx.AddMissingDependencies([]string{depName}) + } + return + } + sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo) + sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryImplementationStubsInfoProvider).(SharedLibraryImplementationStubsInfo) + + if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedLibraryStubsInfos) > 0 { + useStubs := false + if m, ok := ccDep.(*Module); ok && m.IsStubs() && c.UseVndk() { // LLNDK + if !apexInfo.IsForPlatform() { + // For platform libraries, use current version of LLNDK + // If this is for use_vendor apex we will apply the same rules + // of apex sdk enforcement below to choose right version. + useStubs = true + } + } else if apexInfo.IsForPlatform() { + // If not building for APEX, use stubs only when it is from + // an APEX (and not from platform) + // However, for host, ramdisk, recovery or bootstrap modules, + // always link to non-stub variant + useStubs = dep.(android.ApexModule).AnyVariantDirectlyInAnyApex() && !c.bootstrap() + // Another exception: if this module is bundled with an APEX, then + // it is linked with the non-stub variant of a module in the APEX + // as if this is part of the APEX. + testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo) + for _, apexContents := range testFor.ApexContents { + if apexContents.DirectlyInApex(depName) { + useStubs = false + break + } + } + } else { + // If building for APEX, use stubs when the parent is in any APEX that + // the child is not in. + useStubs = !android.DirectlyInAllApexes(apexInfo, depName) + } + + // when to use (unspecified) stubs, check min_sdk_version and choose the right one + if useStubs { + sharedLibraryStubsInfo, err := + c.chooseSdkVersion(ctx, sharedLibraryStubsInfo.SharedLibraryStubsInfos, c.apexSdkVersion) + if err != nil { + ctx.OtherModuleErrorf(dep, err.Error()) + return + } + sharedLibraryInfo = sharedLibraryStubsInfo.SharedLibraryInfo + depExporterInfo = sharedLibraryStubsInfo.FlagExporterInfo + } + } + + linkFile = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary) + depFile = sharedLibraryInfo.TableOfContents + ptr = &depPaths.SharedLibs switch libDepTag.Order { case earlyLibraryDependency: @@ -2626,47 +2464,41 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { case normalLibraryDependency: ptr = &depPaths.SharedLibs depPtr = &depPaths.SharedLibsDeps - directSharedDeps = append(directSharedDeps, ccDep) + directSharedDeps = append(directSharedDeps, sharedLibraryInfo) case lateLibraryDependency: ptr = &depPaths.LateSharedLibs depPtr = &depPaths.LateSharedLibsDeps default: panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order)) } - depFile = ccDep.Toc() case libDepTag.static(): + if !ctx.OtherModuleHasProvider(dep, StaticLibraryInfoProvider) { + if !ctx.Config().AllowMissingDependencies() { + ctx.ModuleErrorf("module %q is not a static library", depName) + } else { + ctx.AddMissingDependencies([]string{depName}) + } + return + } + staticLibraryInfo := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo) + linkFile = android.OptionalPathForPath(staticLibraryInfo.StaticLibrary) if libDepTag.wholeStatic { ptr = &depPaths.WholeStaticLibs - if !ccDep.CcLibraryInterface() || !ccDep.Static() { - ctx.ModuleErrorf("module %q not a static library", depName) - return - } - - // 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 objs := staticLib.objs(); len(objs.objFiles) > 0 { - depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(objs) - } 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 len(staticLibraryInfo.Objects.objFiles) > 0 { + depPaths.WholeStaticLibObjs = depPaths.WholeStaticLibObjs.Append(staticLibraryInfo.Objects) } else { - ctx.ModuleErrorf( - "non-cc.Modules cannot be included as whole static libraries.", depName) - return + // 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()) } - } else { switch libDepTag.Order { case earlyLibraryDependency: @@ -2675,7 +2507,7 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // static dependencies will be handled separately so they can be ordered // using transitive dependencies. ptr = nil - directStaticDeps = append(directStaticDeps, ccDep) + directStaticDeps = append(directStaticDeps, staticLibraryInfo) case lateLibraryDependency: ptr = &depPaths.LateStaticLibs default: @@ -2699,10 +2531,10 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { staticLib.objs().coverageFiles...) depPaths.StaticLibObjs.sAbiDumpFiles = append(depPaths.StaticLibObjs.sAbiDumpFiles, staticLib.objs().sAbiDumpFiles...) - } else if c, ok := ccDep.(LinkableInterface); ok { + } else { // Handle non-CC modules here depPaths.StaticLibObjs.coverageFiles = append(depPaths.StaticLibObjs.coverageFiles, - c.CoverageFiles()...) + ccDep.CoverageFiles()...) } } @@ -2726,6 +2558,22 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { *depPtr = append(*depPtr, dep.Path()) } + depPaths.IncludeDirs = append(depPaths.IncludeDirs, depExporterInfo.IncludeDirs...) + depPaths.SystemIncludeDirs = append(depPaths.SystemIncludeDirs, depExporterInfo.SystemIncludeDirs...) + depPaths.GeneratedDeps = append(depPaths.GeneratedDeps, depExporterInfo.Deps...) + depPaths.Flags = append(depPaths.Flags, depExporterInfo.Flags...) + + if libDepTag.reexportFlags { + reexportExporter(depExporterInfo) + // 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, depExporterInfo.IncludeDirs.Strings()...) + } + makeLibName := c.makeLibName(ctx, ccDep, depName) + libDepTag.makeSuffix switch { case libDepTag.header(): @@ -2779,7 +2627,9 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { }) // use the ordered dependencies as this module's dependencies - depPaths.StaticLibs = append(depPaths.StaticLibs, orderStaticModuleDeps(c, directStaticDeps, directSharedDeps)...) + orderedStaticPaths, transitiveStaticLibs := orderStaticModuleDeps(directStaticDeps, directSharedDeps) + depPaths.TranstiveStaticLibrariesForOrdering = transitiveStaticLibs + depPaths.StaticLibs = append(depPaths.StaticLibs, orderedStaticPaths...) // Dedup exported flags from dependencies depPaths.Flags = android.FirstUniqueStrings(depPaths.Flags) @@ -2799,6 +2649,38 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { return depPaths } +// orderStaticModuleDeps rearranges the order of the static library dependencies of the module +// to match the topological order of the dependency tree, including any static analogues of +// direct shared libraries. It returns the ordered static dependencies, and an android.DepSet +// of the transitive dependencies. +func orderStaticModuleDeps(staticDeps []StaticLibraryInfo, sharedDeps []SharedLibraryInfo) (ordered android.Paths, transitive *android.DepSet) { + transitiveStaticLibsBuilder := android.NewDepSetBuilder(android.TOPOLOGICAL) + var staticPaths android.Paths + for _, staticDep := range staticDeps { + staticPaths = append(staticPaths, staticDep.StaticLibrary) + transitiveStaticLibsBuilder.Transitive(staticDep.TransitiveStaticLibrariesForOrdering) + } + for _, sharedDep := range sharedDeps { + if sharedDep.StaticAnalogue != nil { + transitiveStaticLibsBuilder.Transitive(sharedDep.StaticAnalogue.TransitiveStaticLibrariesForOrdering) + } + } + transitiveStaticLibs := transitiveStaticLibsBuilder.Build() + + orderedTransitiveStaticLibs := transitiveStaticLibs.ToList() + + // reorder the dependencies based on transitive dependencies + staticPaths = android.FirstUniquePaths(staticPaths) + _, orderedStaticPaths := android.FilterPathList(orderedTransitiveStaticLibs, staticPaths) + + if len(orderedStaticPaths) != len(staticPaths) { + missing, _ := android.FilterPathList(staticPaths, orderedStaticPaths) + panic(fmt.Errorf("expected %d ordered static paths , got %d, missing %q %q %q", len(staticPaths), len(orderedStaticPaths), missing, orderedStaticPaths, staticPaths)) + } + + return orderedStaticPaths, transitiveStaticLibs +} + // baseLibName trims known prefixes and suffixes func baseLibName(depName string) string { libName := strings.TrimSuffix(depName, llndkLibrarySuffix) @@ -3096,8 +2978,8 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return false } } - if depTag == llndkImplDep { - // We don't track beyond LLNDK + if depTag == stubImplDepTag || depTag == llndkImplDep { + // We don't track beyond LLNDK or from an implementation library to its stubs. return false } return true diff --git a/cc/cc_test.go b/cc/cc_test.go index e0d464093..d1780cd70 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -20,7 +20,6 @@ import ( "os" "path/filepath" "reflect" - "sort" "strings" "testing" @@ -2890,59 +2889,6 @@ func parseModuleDeps(text string) (modulesInOrder []android.Path, allDeps map[an return modulesInOrder, allDeps } -func TestLinkReordering(t *testing.T) { - for _, testCase := range staticLinkDepOrderTestCases { - errs := []string{} - - // parse testcase - _, givenTransitiveDeps := parseModuleDeps(testCase.inStatic) - expectedModuleNames, expectedTransitiveDeps := parseModuleDeps(testCase.outOrdered) - if testCase.allOrdered == "" { - // allow the test case to skip specifying allOrdered - testCase.allOrdered = testCase.outOrdered - } - _, expectedAllDeps := parseModuleDeps(testCase.allOrdered) - _, givenAllSharedDeps := parseModuleDeps(testCase.inShared) - - // For each module whose post-reordered dependencies were specified, validate that - // reordering the inputs produces the expected outputs. - for _, moduleName := range expectedModuleNames { - moduleDeps := givenTransitiveDeps[moduleName] - givenSharedDeps := givenAllSharedDeps[moduleName] - orderedAllDeps, orderedDeclaredDeps := orderDeps(moduleDeps, givenSharedDeps, givenTransitiveDeps) - - correctAllOrdered := expectedAllDeps[moduleName] - if !reflect.DeepEqual(orderedAllDeps, correctAllOrdered) { - errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedAllDeps."+ - "\nin static:%q"+ - "\nin shared:%q"+ - "\nmodule: %v"+ - "\nexpected: %s"+ - "\nactual: %s", - testCase.inStatic, testCase.inShared, moduleName, correctAllOrdered, orderedAllDeps)) - } - - correctOutputDeps := expectedTransitiveDeps[moduleName] - if !reflect.DeepEqual(correctOutputDeps, orderedDeclaredDeps) { - errs = append(errs, fmt.Sprintf("orderDeps returned incorrect orderedDeclaredDeps."+ - "\nin static:%q"+ - "\nin shared:%q"+ - "\nmodule: %v"+ - "\nexpected: %s"+ - "\nactual: %s", - testCase.inStatic, testCase.inShared, moduleName, correctOutputDeps, orderedDeclaredDeps)) - } - } - - if len(errs) > 0 { - sort.Strings(errs) - for _, err := range errs { - t.Error(err) - } - } - } -} - func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) { for _, moduleName := range moduleNames { module := ctx.ModuleForTests(moduleName, variant).Module().(*Module) @@ -2977,8 +2923,8 @@ func TestStaticLibDepReordering(t *testing.T) { variant := "android_arm64_armv8-a_static" moduleA := ctx.ModuleForTests("a", variant).Module().(*Module) - actual := moduleA.depsInLinkOrder - expected := getOutputPaths(ctx, variant, []string{"c", "b", "d"}) + actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList() + expected := getOutputPaths(ctx, variant, []string{"a", "c", "b", "d"}) if !reflect.DeepEqual(actual, expected) { t.Errorf("staticDeps orderings were not propagated correctly"+ @@ -3011,8 +2957,8 @@ func TestStaticLibDepReorderingWithShared(t *testing.T) { variant := "android_arm64_armv8-a_static" moduleA := ctx.ModuleForTests("a", variant).Module().(*Module) - actual := moduleA.depsInLinkOrder - expected := getOutputPaths(ctx, variant, []string{"c", "b"}) + actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).TransitiveStaticLibrariesForOrdering.ToList() + expected := getOutputPaths(ctx, variant, []string{"a", "c", "b"}) if !reflect.DeepEqual(actual, expected) { t.Errorf("staticDeps orderings did not account for shared libs"+ @@ -3048,12 +2994,12 @@ func TestLlndkLibrary(t *testing.T) { `) actual := ctx.ModuleVariantsForTests("libllndk.llndk") expected := []string{ - "android_vendor.VER_arm64_armv8-a_shared", "android_vendor.VER_arm64_armv8-a_shared_1", "android_vendor.VER_arm64_armv8-a_shared_2", - "android_vendor.VER_arm_armv7-a-neon_shared", + "android_vendor.VER_arm64_armv8-a_shared", "android_vendor.VER_arm_armv7-a-neon_shared_1", "android_vendor.VER_arm_armv7-a-neon_shared_2", + "android_vendor.VER_arm_armv7-a-neon_shared", } checkEquals(t, "variants for llndk stubs", expected, actual) @@ -3582,7 +3528,7 @@ func TestStaticDepsOrderWithStubs(t *testing.T) { cc_binary { name: "mybin", srcs: ["foo.c"], - static_libs: ["libfooB"], + static_libs: ["libfooC", "libfooB"], static_executable: true, stl: "none", } @@ -3603,8 +3549,8 @@ func TestStaticDepsOrderWithStubs(t *testing.T) { }, }`) - mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Module().(*Module) - actual := mybin.depsInLinkOrder + mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Rule("ld") + actual := mybin.Implicits[:2] expected := getOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"}) if !reflect.DeepEqual(actual, expected) { diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go index 796de6269..9ea988a42 100644 --- a/cc/kernel_headers.go +++ b/cc/kernel_headers.go @@ -26,6 +26,7 @@ func (stub *kernelHeadersDecorator) link(ctx ModuleContext, flags Flags, deps Pa if ctx.Device() { f := &stub.libraryDecorator.flagExporter f.reexportSystemDirs(android.PathsForSource(ctx, ctx.DeviceConfig().DeviceKernelHeaderDirs())...) + f.setProvider(ctx) } return stub.libraryDecorator.linkStatic(ctx, flags, deps, objs) } diff --git a/cc/library.go b/cc/library.go index 35828aa71..3a46b1137 100644 --- a/cc/library.go +++ b/cc/library.go @@ -291,36 +291,16 @@ func (f *flagExporter) addExportedGeneratedHeaders(headers ...android.Path) { f.headers = append(f.headers, headers...) } -func (f *flagExporter) exportedDirs() android.Paths { - return f.dirs +func (f *flagExporter) setProvider(ctx android.ModuleContext) { + ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{ + IncludeDirs: f.dirs, + SystemIncludeDirs: f.systemDirs, + Flags: f.flags, + Deps: f.deps, + GeneratedHeaders: f.headers, + }) } -func (f *flagExporter) exportedSystemDirs() android.Paths { - return f.systemDirs -} - -func (f *flagExporter) exportedFlags() []string { - return f.flags -} - -func (f *flagExporter) exportedDeps() android.Paths { - return f.deps -} - -func (f *flagExporter) exportedGeneratedHeaders() android.Paths { - return f.headers -} - -type exportedFlagsProducer interface { - exportedDirs() android.Paths - exportedSystemDirs() android.Paths - exportedFlags() []string - exportedDeps() android.Paths - exportedGeneratedHeaders() android.Paths -} - -var _ exportedFlagsProducer = (*flagExporter)(nil) - // libraryDecorator wraps baseCompiler, baseLinker and baseInstaller to provide library-specific // functionality: static vs. shared linkage, reusing object files for shared libraries type libraryDecorator struct { @@ -396,7 +376,7 @@ func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) // can't be globbed, and they should be manually collected. // So, we first filter out intermediate directories (which contains generated headers) // from exported directories, and then glob headers under remaining directories. - for _, path := range append(l.exportedDirs(), l.exportedSystemDirs()...) { + for _, path := range append(android.CopyOfPaths(l.flagExporter.dirs), l.flagExporter.systemDirs...) { dir := path.String() // Skip if dir is for generated headers if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) { @@ -448,7 +428,7 @@ func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) } // Collect generated headers - for _, header := range append(l.exportedGeneratedHeaders(), l.exportedDeps()...) { + for _, header := range append(android.CopyOfPaths(l.flagExporter.headers), l.flagExporter.deps...) { // TODO(b/148123511): remove exportedDeps after cleaning up genrule if strings.HasSuffix(header.Base(), "-phony") { continue @@ -681,7 +661,7 @@ type libraryInterface interface { static() bool shared() bool objs() Objects - reuseObjs() (Objects, exportedFlagsProducer) + reuseObjs() Objects toc() android.OptionalPath // Returns true if the build options for the module have selected a static or shared build @@ -886,6 +866,17 @@ func (library *libraryDecorator) linkStatic(ctx ModuleContext, ctx.CheckbuildFile(outputFile) + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: outputFile, + ReuseObjects: library.reuseObjects, + Objects: library.objects, + + TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder(android.TOPOLOGICAL). + Direct(outputFile). + Transitive(deps.TranstiveStaticLibrariesForOrdering). + Build(), + }) + return outputFile } @@ -930,7 +921,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, fileName := library.getLibName(ctx) + flags.Toolchain.ShlibSuffix() outputFile := android.PathForModuleOut(ctx, fileName) - ret := outputFile + unstrippedOutputFile := outputFile var implicitOutputs android.WritablePaths if ctx.Windows() { @@ -1012,9 +1003,42 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, objs.sAbiDumpFiles = append(objs.sAbiDumpFiles, deps.WholeStaticLibObjs.sAbiDumpFiles...) library.coverageOutputFile = TransformCoverageFilesToZip(ctx, objs, library.getLibName(ctx)) - library.linkSAbiDumpFiles(ctx, objs, fileName, ret) + library.linkSAbiDumpFiles(ctx, objs, fileName, unstrippedOutputFile) - return ret + var staticAnalogue *StaticLibraryInfo + if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 { + s := ctx.OtherModuleProvider(static[0], StaticLibraryInfoProvider).(StaticLibraryInfo) + staticAnalogue = &s + } + + ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ + TableOfContents: android.OptionalPathForPath(tocFile), + SharedLibrary: unstrippedOutputFile, + UnstrippedSharedLibrary: library.unstrippedOutputFile, + CoverageSharedLibrary: library.coverageOutputFile, + StaticAnalogue: staticAnalogue, + }) + + stubs := ctx.GetDirectDepsWithTag(stubImplDepTag) + if len(stubs) > 0 { + var stubsInfo []SharedLibraryStubsInfo + for _, stub := range stubs { + stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo) + flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo) + stubsInfo = append(stubsInfo, SharedLibraryStubsInfo{ + Version: stub.(*Module).StubsVersion(), + SharedLibraryInfo: stubInfo, + FlagExporterInfo: flagInfo, + }) + } + ctx.SetProvider(SharedLibraryImplementationStubsInfoProvider, SharedLibraryImplementationStubsInfo{ + SharedLibraryStubsInfos: stubsInfo, + + IsLLNDK: ctx.isLlndk(ctx.Config()), + }) + } + + return unstrippedOutputFile } func (library *libraryDecorator) unstrippedOutputFilePath() android.Path { @@ -1162,6 +1186,8 @@ func (library *libraryDecorator) link(ctx ModuleContext, library.reexportFlags("-D" + versioningMacroName(ctx.ModuleName()) + "=" + library.stubsVersion()) } + library.flagExporter.setProvider(ctx) + return out } @@ -1179,8 +1205,8 @@ func (library *libraryDecorator) objs() Objects { return library.objects } -func (library *libraryDecorator) reuseObjs() (Objects, exportedFlagsProducer) { - return library.reuseObjects, &library.flagExporter +func (library *libraryDecorator) reuseObjs() Objects { + return library.reuseObjects } func (library *libraryDecorator) toc() android.OptionalPath { @@ -1423,10 +1449,10 @@ func reuseStaticLibrary(mctx android.BottomUpMutatorContext, static, shared *Mod sharedCompiler.baseCompiler.Properties.Srcs sharedCompiler.baseCompiler.Properties.Srcs = nil sharedCompiler.baseCompiler.Properties.Generated_sources = nil - } else { - // This dep is just to reference static variant from shared variant - mctx.AddInterVariantDependency(staticVariantTag, shared, static) } + + // This dep is just to reference static variant from shared variant + mctx.AddInterVariantDependency(staticVariantTag, shared, static) } } @@ -1525,15 +1551,15 @@ func normalizeVersions(ctx android.BaseModuleContext, versions []string) { func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) { // "" is for the non-stubs (implementation) variant. - variants := append([]string{""}, versions...) + variants := append(android.CopyOf(versions), "") modules := mctx.CreateLocalVariations(variants...) for i, m := range modules { if variants[i] != "" { m.(LinkableInterface).SetBuildStubs() m.(LinkableInterface).SetStubsVersion(variants[i]) - // The stubs depend on the implementation - mctx.AddInterVariantDependency(stubImplDepTag, modules[i], modules[0]) + // The implementation depends on the stubs + mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i]) } } mctx.AliasVariation("") @@ -1570,9 +1596,7 @@ func CanBeVersionVariant(module interface { // and propagates the value from implementation libraries to llndk libraries with the same name. func versionSelectorMutator(mctx android.BottomUpMutatorContext) { if library, ok := mctx.Module().(LinkableInterface); ok && CanBeVersionVariant(library) { - - if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 && - !library.IsSdkVariant() { + if library.CcLibrary() && library.BuildSharedVariant() && len(library.StubsVersions()) > 0 { versions := library.StubsVersions() normalizeVersions(mctx, versions) diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go index 765fe710f..fcf6069c8 100644 --- a/cc/library_sdk_member.go +++ b/cc/library_sdk_member.go @@ -391,10 +391,12 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte p.outputFile = getRequiredMemberOutputFile(ctx, ccModule) } + exportedInfo := ctx.SdkModuleContext().OtherModuleProvider(variant, FlagExporterInfoProvider).(FlagExporterInfo) + // Separate out the generated include dirs (which are arch specific) from the // include dirs (which may not be). exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate( - ccModule.ExportedIncludeDirs(), isGeneratedHeaderDirectory) + exportedInfo.IncludeDirs, isGeneratedHeaderDirectory) p.name = variant.Name() p.archType = ccModule.Target().Arch.ArchType.String() @@ -405,10 +407,10 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte // Take a copy before filtering out duplicates to avoid changing the slice owned by the // ccModule. - dirs := append(android.Paths(nil), ccModule.ExportedSystemIncludeDirs()...) + dirs := append(android.Paths(nil), exportedInfo.SystemIncludeDirs...) p.ExportedSystemIncludeDirs = android.FirstUniquePaths(dirs) - p.ExportedFlags = ccModule.ExportedFlags() + p.ExportedFlags = exportedInfo.Flags if ccModule.linker != nil { specifiedDeps := specifiedDeps{} specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps) @@ -419,7 +421,7 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte } p.SystemSharedLibs = specifiedDeps.systemSharedLibs } - p.exportedGeneratedHeaders = ccModule.ExportedGeneratedHeaders() + p.exportedGeneratedHeaders = exportedInfo.GeneratedHeaders if ccModule.HasStubsVariants() { // TODO(b/169373910): 1. Only output the specific version (from diff --git a/cc/linkable.go b/cc/linkable.go index a67cd4e4c..21e6f9b4e 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -14,13 +14,6 @@ type LinkableInterface interface { OutputFile() android.OptionalPath CoverageFiles() android.Paths - IncludeDirs() android.Paths - SetDepsInLinkOrder([]android.Path) - GetDepsInLinkOrder() []android.Path - - HasStaticVariant() bool - GetStaticVariant() LinkableInterface - NonCcVariants() bool StubsVersions() []string @@ -80,3 +73,54 @@ func SharedDepTag() blueprint.DependencyTag { func StaticDepTag() blueprint.DependencyTag { return libraryDependencyTag{Kind: staticLibraryDependency} } + +type SharedLibraryInfo struct { + SharedLibrary android.Path + UnstrippedSharedLibrary android.Path + + TableOfContents android.OptionalPath + CoverageSharedLibrary android.OptionalPath + + StaticAnalogue *StaticLibraryInfo +} + +var SharedLibraryInfoProvider = blueprint.NewProvider(SharedLibraryInfo{}) + +type SharedLibraryImplementationStubsInfo struct { + SharedLibraryStubsInfos []SharedLibraryStubsInfo + + IsLLNDK bool +} + +var SharedLibraryImplementationStubsInfoProvider = blueprint.NewProvider(SharedLibraryImplementationStubsInfo{}) + +type SharedLibraryStubsInfo struct { + Version string + SharedLibraryInfo SharedLibraryInfo + FlagExporterInfo FlagExporterInfo +} + +var SharedLibraryStubsInfoProvider = blueprint.NewProvider(SharedLibraryStubsInfo{}) + +type StaticLibraryInfo struct { + StaticLibrary android.Path + Objects Objects + ReuseObjects Objects + + // This isn't the actual transitive DepSet, shared library dependencies have been + // converted into static library analogues. It is only used to order the static + // library dependencies that were specified for the current module. + TransitiveStaticLibrariesForOrdering *android.DepSet +} + +var StaticLibraryInfoProvider = blueprint.NewProvider(StaticLibraryInfo{}) + +type FlagExporterInfo struct { + IncludeDirs android.Paths + SystemIncludeDirs android.Paths + Flags []string + Deps android.Paths + GeneratedHeaders android.Paths +} + +var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{}) diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go index acdc581a2..793ab37fb 100644 --- a/cc/ndk_prebuilt.go +++ b/cc/ndk_prebuilt.go @@ -166,7 +166,7 @@ func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, ctx.ModuleErrorf("NDK prebuilt libraries must have an ndk_lib prefixed name") } - ndk.exportIncludesAsSystem(ctx) + ndk.libraryDecorator.flagExporter.exportIncludesAsSystem(ctx) libName := strings.TrimPrefix(ctx.ModuleName(), "ndk_") libExt := flags.Toolchain.ShlibSuffix() @@ -175,5 +175,23 @@ func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, } libDir := getNdkStlLibDir(ctx) - return libDir.Join(ctx, libName+libExt) + lib := libDir.Join(ctx, libName+libExt) + + ndk.libraryDecorator.flagExporter.setProvider(ctx) + + if ndk.static() { + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(lib).Build() + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: lib, + + TransitiveStaticLibrariesForOrdering: depSet, + }) + } else { + ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ + SharedLibrary: lib, + UnstrippedSharedLibrary: lib, + }) + } + + return lib } diff --git a/cc/prebuilt.go b/cc/prebuilt.go index 9d1b01608..f21e4a943 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -97,12 +97,14 @@ func (p *prebuiltLibraryLinker) linkerProps() []interface{} { func (p *prebuiltLibraryLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { - p.libraryDecorator.exportIncludes(ctx) - p.libraryDecorator.reexportDirs(deps.ReexportedDirs...) - p.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...) - p.libraryDecorator.reexportFlags(deps.ReexportedFlags...) - p.libraryDecorator.reexportDeps(deps.ReexportedDeps...) - p.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...) + p.libraryDecorator.flagExporter.exportIncludes(ctx) + p.libraryDecorator.flagExporter.reexportDirs(deps.ReexportedDirs...) + p.libraryDecorator.flagExporter.reexportSystemDirs(deps.ReexportedSystemDirs...) + p.libraryDecorator.flagExporter.reexportFlags(deps.ReexportedFlags...) + p.libraryDecorator.flagExporter.reexportDeps(deps.ReexportedDeps...) + p.libraryDecorator.flagExporter.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...) + + p.libraryDecorator.flagExporter.setProvider(ctx) // TODO(ccross): verify shared library dependencies srcs := p.prebuiltSrcs() @@ -117,6 +119,12 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, in := android.PathForModuleSrc(ctx, srcs[0]) if p.static() { + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build() + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: in, + + TransitiveStaticLibrariesForOrdering: depSet, + }) return in } @@ -170,6 +178,13 @@ func (p *prebuiltLibraryLinker) link(ctx ModuleContext, }, }) + ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ + SharedLibrary: outputFile, + UnstrippedSharedLibrary: p.unstrippedOutputFile, + + TableOfContents: p.tocFile, + }) + return outputFile } } diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go index b72af4405..238508dc9 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -22,7 +22,6 @@ var ( ) type snapshotLibraryInterface interface { - exportedFlagsProducer libraryInterface collectHeadersForSnapshot(ctx android.ModuleContext) snapshotHeaders() android.Paths diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go index 19f5ea4f7..8c546c51f 100644 --- a/cc/toolchain_library.go +++ b/cc/toolchain_library.go @@ -84,24 +84,31 @@ func (library *toolchainLibraryDecorator) link(ctx ModuleContext, } srcPath := android.PathForSource(ctx, *library.Properties.Src) - - if library.stripper.StripProperties.Strip.Keep_symbols_list != nil { - fileName := ctx.ModuleName() + staticLibraryExtension - outputFile := android.PathForModuleOut(ctx, fileName) - stripFlags := flagsToStripFlags(flags) - library.stripper.StripStaticLib(ctx, srcPath, outputFile, stripFlags) - return outputFile - } + outputFile := android.Path(srcPath) if library.Properties.Repack_objects_to_keep != nil { fileName := ctx.ModuleName() + staticLibraryExtension - outputFile := android.PathForModuleOut(ctx, fileName) - TransformArchiveRepack(ctx, srcPath, outputFile, library.Properties.Repack_objects_to_keep) - - return outputFile + repackedPath := android.PathForModuleOut(ctx, fileName) + TransformArchiveRepack(ctx, outputFile, repackedPath, library.Properties.Repack_objects_to_keep) + outputFile = repackedPath } - return srcPath + if library.stripper.StripProperties.Strip.Keep_symbols_list != nil { + fileName := ctx.ModuleName() + staticLibraryExtension + strippedPath := android.PathForModuleOut(ctx, fileName) + stripFlags := flagsToStripFlags(flags) + library.stripper.StripStaticLib(ctx, outputFile, strippedPath, stripFlags) + outputFile = strippedPath + } + + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build() + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: outputFile, + + TransitiveStaticLibrariesForOrdering: depSet, + }) + + return outputFile } func (library *toolchainLibraryDecorator) nativeCoverage() bool { diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 529ed600e..4c206e6d2 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -223,6 +223,22 @@ func (p *vendorSnapshotLibraryDecorator) link(ctx ModuleContext, tocFile := android.PathForModuleOut(ctx, libName+".toc") p.tocFile = android.OptionalPathForPath(tocFile) TransformSharedObjectToToc(ctx, in, tocFile, builderFlags) + + ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ + SharedLibrary: in, + UnstrippedSharedLibrary: p.unstrippedOutputFile, + + TableOfContents: p.tocFile, + }) + } + + if p.static() { + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(in).Build() + ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{ + StaticLibrary: in, + + TransitiveStaticLibrariesForOrdering: depSet, + }) } return in @@ -735,13 +751,14 @@ func (c *vendorSnapshotSingleton) GenerateBuildActions(ctx android.SingletonCont var propOut string if l, ok := m.linker.(snapshotLibraryInterface); ok { + exporterInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo) // library flags - prop.ExportedFlags = l.exportedFlags() - for _, dir := range l.exportedDirs() { + prop.ExportedFlags = exporterInfo.Flags + for _, dir := range exporterInfo.IncludeDirs { prop.ExportedDirs = append(prop.ExportedDirs, filepath.Join("include", dir.String())) } - for _, dir := range l.exportedSystemDirs() { + for _, dir := range exporterInfo.SystemIncludeDirs { prop.ExportedSystemDirs = append(prop.ExportedSystemDirs, filepath.Join("include", dir.String())) } // shared libs dependencies aren't meaningful on static or header libs diff --git a/cc/vndk.go b/cc/vndk.go index 4169e2129..981e039ec 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -620,7 +620,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex var headers android.Paths - installVndkSnapshotLib := func(m *Module, l snapshotLibraryInterface, vndkType string) (android.Paths, bool) { + installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) { var ret android.Paths targetArch := "arch-" + m.Target().Arch.ArchType.String() @@ -639,9 +639,10 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex ExportedFlags []string `json:",omitempty"` RelativeInstallPath string `json:",omitempty"` }{} - prop.ExportedFlags = l.exportedFlags() - prop.ExportedDirs = l.exportedDirs().Strings() - prop.ExportedSystemDirs = l.exportedSystemDirs().Strings() + exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo) + prop.ExportedFlags = exportedInfo.Flags + prop.ExportedDirs = exportedInfo.IncludeDirs.Strings() + prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings() prop.RelativeInstallPath = m.RelativeInstallPath() propOut := snapshotLibOut + ".json" @@ -671,7 +672,7 @@ func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContex // install .so files for appropriate modules. // Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS - libs, ok := installVndkSnapshotLib(m, l, vndkType) + libs, ok := installVndkSnapshotLib(m, vndkType) if !ok { return } diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go index 94847601e..7c47ef42a 100644 --- a/cc/vndk_prebuilt.go +++ b/cc/vndk_prebuilt.go @@ -162,6 +162,13 @@ func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext, p.androidMkSuffix = "" } + ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{ + SharedLibrary: in, + UnstrippedSharedLibrary: p.unstrippedOutputFile, + + TableOfContents: p.tocFile, + }) + return in } diff --git a/rust/library.go b/rust/library.go index 3bba089e6..ae33f0fdd 100644 --- a/rust/library.go +++ b/rust/library.go @@ -20,6 +20,7 @@ import ( "strings" "android/soong/android" + "android/soong/cc" ) var ( @@ -484,11 +485,35 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa library.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, library.getStem(ctx)) if library.rlib() || library.dylib() { - library.exportLinkDirs(deps.linkDirs...) - library.exportDepFlags(deps.depFlags...) - library.exportLinkObjects(deps.linkObjects...) + library.flagExporter.exportLinkDirs(deps.linkDirs...) + library.flagExporter.exportDepFlags(deps.depFlags...) + library.flagExporter.exportLinkObjects(deps.linkObjects...) } + if library.static() || library.shared() { + ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{ + IncludeDirs: library.includeDirs, + }) + } + + if library.shared() { + ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{ + SharedLibrary: outputFile, + UnstrippedSharedLibrary: outputFile, + }) + } + + if library.static() { + depSet := android.NewDepSetBuilder(android.TOPOLOGICAL).Direct(outputFile).Build() + ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{ + StaticLibrary: outputFile, + + TransitiveStaticLibrariesForOrdering: depSet, + }) + } + + library.flagExporter.setProvider(ctx) + return outputFile } diff --git a/rust/prebuilt.go b/rust/prebuilt.go index f9c8934d6..94fe1e546 100644 --- a/rust/prebuilt.go +++ b/rust/prebuilt.go @@ -93,7 +93,8 @@ func (prebuilt *prebuiltLibraryDecorator) compilerProps() []interface{} { } func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path { - prebuilt.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) + prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...) + prebuilt.flagExporter.setProvider(ctx) srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs()) if len(paths) > 0 { diff --git a/rust/rust.go b/rust/rust.go index ba8673c94..29606fafa 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -302,9 +302,6 @@ type compiler interface { } type exportedFlagsProducer interface { - exportedLinkDirs() []string - exportedDepFlags() []string - exportedLinkObjects() []string exportLinkDirs(...string) exportDepFlags(...string) exportLinkObjects(...string) @@ -316,18 +313,6 @@ type flagExporter struct { linkObjects []string } -func (flagExporter *flagExporter) exportedLinkDirs() []string { - return flagExporter.linkDirs -} - -func (flagExporter *flagExporter) exportedDepFlags() []string { - return flagExporter.depFlags -} - -func (flagExporter *flagExporter) exportedLinkObjects() []string { - return flagExporter.linkObjects -} - func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) } @@ -340,16 +325,28 @@ func (flagExporter *flagExporter) exportLinkObjects(flags ...string) { flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...)) } +func (flagExporter *flagExporter) setProvider(ctx ModuleContext) { + ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{ + Flags: flagExporter.depFlags, + LinkDirs: flagExporter.linkDirs, + LinkObjects: flagExporter.linkObjects, + }) +} + var _ exportedFlagsProducer = (*flagExporter)(nil) func NewFlagExporter() *flagExporter { - return &flagExporter{ - depFlags: []string{}, - linkDirs: []string{}, - linkObjects: []string{}, - } + return &flagExporter{} } +type FlagExporterInfo struct { + Flags []string + LinkDirs []string // TODO: this should be android.Paths + LinkObjects []string // TODO: this should be android.Paths +} + +var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{}) + func (mod *Module) isCoverageVariant() bool { return mod.coverage.Properties.IsCoverageVariant } @@ -499,17 +496,6 @@ func (mod *Module) BuildSharedVariant() bool { 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 } @@ -532,12 +518,6 @@ 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 -} func (mod *Module) CoverageFiles() android.Paths { if mod.compiler != nil { @@ -701,11 +681,6 @@ func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { if mod.compiler.(libraryInterface).source() { mod.sourceProvider.GenerateSource(ctx, deps) mod.sourceProvider.setSubName(ctx.ModuleSubDir()) - if lib, ok := mod.compiler.(*libraryDecorator); ok { - lib.flagExporter.linkDirs = nil - lib.flagExporter.linkObjects = nil - lib.flagExporter.depFlags = nil - } } else { sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag) sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator) @@ -846,10 +821,11 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { } //Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS - if lib, ok := rustDep.compiler.(exportedFlagsProducer); ok && depTag != procMacroDepTag { - depPaths.linkDirs = append(depPaths.linkDirs, lib.exportedLinkDirs()...) - depPaths.depFlags = append(depPaths.depFlags, lib.exportedDepFlags()...) - depPaths.linkObjects = append(depPaths.linkObjects, lib.exportedLinkObjects()...) + if depTag != procMacroDepTag { + exportedInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo) + depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...) + depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...) + depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...) } if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag { @@ -889,24 +865,22 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { case cc.IsStaticDepTag(depTag): depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) - depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...) - if mod, ok := ccDep.(*cc.Module); ok { - depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...) - depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...) - depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, mod.ExportedGeneratedHeaders()...) - } + exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo) + depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) + depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) + depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) + depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...) directStaticLibDeps = append(directStaticLibDeps, ccDep) mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName) case cc.IsSharedDepTag(depTag): depPaths.linkDirs = append(depPaths.linkDirs, linkPath) depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) - depPaths.depIncludePaths = append(depPaths.depIncludePaths, ccDep.IncludeDirs()...) - if mod, ok := ccDep.(*cc.Module); ok { - depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, mod.ExportedSystemIncludeDirs()...) - depPaths.depClangFlags = append(depPaths.depClangFlags, mod.ExportedFlags()...) - depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, mod.ExportedGeneratedHeaders()...) - } + exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo) + depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) + depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) + depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...) + depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...) directSharedLibDeps = append(directSharedLibDeps, ccDep) mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName) exportDep = true