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

Commit b6d77bf6 authored by Spandan Das's avatar Spandan Das Committed by Gerrit Code Review
Browse files

Merge changes from topic "linker_config_product_soong" into main

* changes:
  Create linker_config_srcs for autogenerated product partition
  Dedupe logic to generate linker.config.pb
parents afd8aacf 8fe68dcf
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -599,6 +599,7 @@ type PartitionVariables struct {
	ProductPackages         []string `json:",omitempty"`
	ProductPackagesDebug    []string `json:",omitempty"`
	VendorLinkerConfigSrcs  []string `json:",omitempty"`
	ProductLinkerConfigSrcs []string `json:",omitempty"`

	ProductCopyFiles map[string]string `json:",omitempty"`
}
+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())
+18 −7
Original line number Diff line number Diff line
@@ -474,8 +474,8 @@ func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partiti
		return false
	}

	if partitionType == "vendor" {
		fsProps.Linker_config_srcs = f.createLinkerConfigSourceFilegroups(ctx)
	if partitionType == "vendor" || partitionType == "product" {
		fsProps.Linker_config_srcs = f.createLinkerConfigSourceFilegroups(ctx, partitionType)
	}

	var module android.Module
@@ -509,18 +509,29 @@ func (f *filesystemCreator) createPartition(ctx android.LoadHookContext, partiti
	return true
}

// createLinkerConfigSourceFilegroups creates filegroup modules to generate linker.config.pb for _vendor_
// It creates a filegroup for each file in PRODUCT_VENDOR_LINKER_CONFIG_FRAGMENTS.
// createLinkerConfigSourceFilegroups creates filegroup modules to generate linker.config.pb for the following partitions
// 1. vendor: Using PRODUCT_VENDOR_LINKER_CONFIG_FRAGMENTS (space separated file list)
// 1. product: Using PRODUCT_PRODUCT_LINKER_CONFIG_FRAGMENTS (space separated file list)
// It creates a filegroup for each file in the fragment list
// The filegroup modules are then added to `linker_config_srcs` of the autogenerated vendor `android_filesystem`.
func (f *filesystemCreator) createLinkerConfigSourceFilegroups(ctx android.LoadHookContext) []string {
func (f *filesystemCreator) createLinkerConfigSourceFilegroups(ctx android.LoadHookContext, partitionType string) []string {
	ret := []string{}
	partitionVars := ctx.Config().ProductVariables().PartitionVarsForSoongMigrationOnlyDoNotUse
	if linkerConfigSrcs := android.FirstUniqueStrings(partitionVars.VendorLinkerConfigSrcs); len(linkerConfigSrcs) > 0 {
	var linkerConfigSrcs []string
	if partitionType == "vendor" {
		linkerConfigSrcs = android.FirstUniqueStrings(partitionVars.VendorLinkerConfigSrcs)
	} else if partitionType == "product" {
		linkerConfigSrcs = android.FirstUniqueStrings(partitionVars.ProductLinkerConfigSrcs)
	} else {
		ctx.ModuleErrorf("linker.config.pb is only supported for vendor and product partitions. For system partition, use `android_system_image`")
	}

	if len(linkerConfigSrcs) > 0 {
		// Create a filegroup, and add `:<filegroup_name>` to ret.
		for index, linkerConfigSrc := range linkerConfigSrcs {
			dir := filepath.Dir(linkerConfigSrc)
			base := filepath.Base(linkerConfigSrc)
			fgName := generatedModuleName(ctx.Config(), "vendor-linker-config-src"+strconv.Itoa(index))
			fgName := generatedModuleName(ctx.Config(), fmt.Sprintf("%s-linker-config-src%s", partitionType, strconv.Itoa(index)))
			srcs := []string{base}
			fgProps := &struct {
				Name *string