Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 918191e3 authored by Spandan Das's avatar Spandan Das
Browse files

Dedupe logic to generate linker.config.pb

Between android_filesystem and generic_system_image.
`getLibsForLinkerConfig` will return a list of provideLibs and
requireLibs for the fileystem. `linkerConfig.BuildLinkerConfig` will
then filer out the non-stub libraries.

For `android_filesystem`, requireLibs is ignored for now to match the
logic in the kati built vendor.img

Test: m nothing --no-skip-soong-tests
Test: no diff in out/soong/.intermediates/build/make/target/product/generic/generic_system_image/android_common/gen/root-extra/system/etc/linker.config.pb
paste of cmd: https://diff.googleplex.com/#key=KAqqP9bhKZMD

Change-Id: I1f1d626a3a161fb2e12597909fd287533cbb8482
parent 3ab5fcd2
Loading
Loading
Loading
Loading
+47 −16
Original line number Diff line number Diff line
@@ -690,27 +690,13 @@ func (f *filesystem) buildEventLogtagsFile(ctx android.ModuleContext, builder *a
}

func (f *filesystem) buildLinkerConfigFile(ctx android.ModuleContext, builder *android.RuleBuilder, rebasedDir android.OutputPath) {
	getCStubLibs := func() []android.Module {
		// Determine the list of C stub libraries that are part of this filesystem.
		// These will be added to `provideLibs`.
		// The current implementation assumes that stub libraries are listed explicitly in `deps`
		// (direct deps). If this is not true, ctx.VisitDeps will need to be replaced by ctx.WalkDeps.
		ret := []android.Module{}
		ctx.VisitDirectDeps(func(child android.Module) {
			if c, ok := child.(*cc.Module); ok && c.HasStubsVariants() {
				ret = append(ret, c)
			}
		})
		return ret
	}

	if len(f.properties.Linker_config_srcs) == 0 {
		return
	}

	// cp to the final output
	provideModules, _ := f.getLibsForLinkerConfig(ctx)
	output := rebasedDir.Join(ctx, "etc", "linker.config.pb")
	linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config_srcs), getCStubLibs(), nil, output)
	linkerconfig.BuildLinkerConfig(ctx, builder, android.PathsForModuleSrc(ctx, f.properties.Linker_config_srcs), provideModules, nil, output)

	f.appendToEntry(ctx, output)
}
@@ -823,3 +809,48 @@ var _ partition = (*filesystemDefaults)(nil)
func (f *filesystemDefaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	validatePartitionType(ctx, f)
}

// getLibsForLinkerConfig returns
// 1. A list of libraries installed in this filesystem
// 2. A list of dep libraries _not_ installed in this filesystem
//
// `linkerconfig.BuildLinkerConfig` will convert these two to a linker.config.pb for the filesystem
// (1) will be added to --provideLibs if they are C libraries with a stable interface (has stubs)
// (2) will be added to --requireLibs if they are C libraries with a stable interface (has stubs)
func (f *filesystem) getLibsForLinkerConfig(ctx android.ModuleContext) ([]android.Module, []android.Module) {
	// we need "Module"s for packaging items
	modulesInPackageByModule := make(map[android.Module]bool)
	modulesInPackageByName := make(map[string]bool)

	deps := f.gatherFilteredPackagingSpecs(ctx)
	ctx.WalkDeps(func(child, parent android.Module) bool {
		for _, ps := range android.OtherModuleProviderOrDefault(
			ctx, child, android.InstallFilesProvider).PackagingSpecs {
			if _, ok := deps[ps.RelPathInPackage()]; ok {
				modulesInPackageByModule[child] = true
				modulesInPackageByName[child.Name()] = true
				return true
			}
		}
		return true
	})

	provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
	for mod := range modulesInPackageByModule {
		provideModules = append(provideModules, mod)
	}

	var requireModules []android.Module
	ctx.WalkDeps(func(child, parent android.Module) bool {
		_, parentInPackage := modulesInPackageByModule[parent]
		_, childInPackageName := modulesInPackageByName[child.Name()]

		// When parent is in the package, and child (or its variant) is not, this can be from an interface.
		if parentInPackage && !childInPackageName {
			requireModules = append(requireModules, child)
		}
		return true
	})

	return provideModules, requireModules
}
+6 −3
Original line number Diff line number Diff line
@@ -670,18 +670,21 @@ func TestInstallLinkerConfigFile(t *testing.T) {
android_filesystem {
    name: "myfilesystem",
    deps: ["libfoo_has_no_stubs", "libfoo_has_stubs"],
    linker_config_srcs: ["linker.config.json"]
    linker_config_srcs: ["linker.config.json"],
    partition_type: "vendor",
}
cc_library {
    name: "libfoo_has_no_stubs",
    vendor: true,
}
cc_library {
    name: "libfoo_has_stubs",
    stubs: {symbol_file: "libfoo.map.txt"},
    vendor: true,
}
	`)

	linkerConfigCmd := result.ModuleForTests("myfilesystem", "android_common").Rule("build_filesystem_image").RuleParams.Command
	android.AssertStringDoesContain(t, "", linkerConfigCmd, "conv_linker_config proto --force -s linker.config.json")
	android.AssertStringDoesContain(t, "", linkerConfigCmd, "--key provideLibs --value libfoo_has_stubs.so")
	android.AssertStringDoesContain(t, "Could not find linker.config.json file in cmd", linkerConfigCmd, "conv_linker_config proto --force -s linker.config.json")
	android.AssertStringDoesContain(t, "Could not find stub in `provideLibs`", linkerConfigCmd, "--key provideLibs --value libfoo_has_stubs.so")
}
+1 −34
Original line number Diff line number Diff line
@@ -59,40 +59,7 @@ func (s *systemImage) buildLinkerConfigFile(ctx android.ModuleContext, root andr
	input := android.PathForModuleSrc(ctx, android.String(s.properties.Linker_config_src))
	output := root.Join(ctx, "system", "etc", "linker.config.pb")

	// we need "Module"s for packaging items
	modulesInPackageByModule := make(map[android.Module]bool)
	modulesInPackageByName := make(map[string]bool)

	deps := s.gatherFilteredPackagingSpecs(ctx)
	ctx.WalkDeps(func(child, parent android.Module) bool {
		for _, ps := range android.OtherModuleProviderOrDefault(
			ctx, child, android.InstallFilesProvider).PackagingSpecs {
			if _, ok := deps[ps.RelPathInPackage()]; ok {
				modulesInPackageByModule[child] = true
				modulesInPackageByName[child.Name()] = true
				return true
			}
		}
		return true
	})

	provideModules := make([]android.Module, 0, len(modulesInPackageByModule))
	for mod := range modulesInPackageByModule {
		provideModules = append(provideModules, mod)
	}

	var requireModules []android.Module
	ctx.WalkDeps(func(child, parent android.Module) bool {
		_, parentInPackage := modulesInPackageByModule[parent]
		_, childInPackageName := modulesInPackageByName[child.Name()]

		// When parent is in the package, and child (or its variant) is not, this can be from an interface.
		if parentInPackage && !childInPackageName {
			requireModules = append(requireModules, child)
		}
		return true
	})

	provideModules, requireModules := s.getLibsForLinkerConfig(ctx)
	builder := android.NewRuleBuilder(pctx, ctx)
	linkerconfig.BuildLinkerConfig(ctx, builder, android.Paths{input}, provideModules, requireModules, output)
	builder.Build("conv_linker_config", "Generate linker config protobuf "+output.String())