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

Commit d3348dba authored by Thiébaud Weksteen's avatar Thiébaud Weksteen Committed by Gerrit Code Review
Browse files

Merge "Support multiple sources for prebuilt_etc" into main

parents 7f752454 00e8b31e
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -1648,10 +1648,9 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *sh.ShBinary) apexFil
	return af
}

func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, depName string) apexFile {
func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt prebuilt_etc.PrebuiltEtcModule, outputFile android.Path) apexFile {
	dirInApex := filepath.Join(prebuilt.BaseDir(), prebuilt.SubDir())
	fileToCopy := prebuilt.OutputFile()
	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
	return newApexFile(ctx, outputFile, outputFile.Base(), dirInApex, etc, prebuilt)
}

func apexFileForCompatConfig(ctx android.BaseModuleContext, config java.PlatformCompatConfigIntf, depName string) apexFile {
@@ -2120,7 +2119,10 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
			}
		case prebuiltTag:
			if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
				vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
				filesToCopy, _ := prebuilt.OutputFiles("")
				for _, etcFile := range filesToCopy {
					vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
				}
				addAconfigFiles(vctx, ctx, child)
			} else {
				ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
@@ -2263,7 +2265,10 @@ func (a *apexBundle) depVisitor(vctx *visitorContext, ctx android.ModuleContext,
		// Because APK-in-APEX embeds jni_libs transitively, we don't need to track transitive deps
	} else if java.IsXmlPermissionsFileDepTag(depTag) {
		if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
			vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
			filesToCopy, _ := prebuilt.OutputFiles("")
			for _, etcFile := range filesToCopy {
				vctx.filesInfo = append(vctx.filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, etcFile))
			}
		}
	} else if rust.IsDylibDepTag(depTag) {
		if rustm, ok := child.(*rust.Module); ok && rustm.IsInstallableToApex() {
+118 −55
Original line number Diff line number Diff line
@@ -71,10 +71,15 @@ var PrepareForTestWithPrebuiltEtc = android.FixtureRegisterWithContext(RegisterP

type prebuiltEtcProperties struct {
	// Source file of this prebuilt. Can reference a genrule type module with the ":module" syntax.
	// Mutually exclusive with srcs.
	Src *string `android:"path,arch_variant"`

	// Source files of this prebuilt. Can reference a genrule type module with the ":module" syntax.
	// Mutually exclusive with src. When used, filename_from_src is set to true.
	Srcs []string `android:"path,arch_variant"`

	// Optional name for the installed file. If unspecified, name of the module is used as the file
	// name.
	// name. Only available when using a single source (src).
	Filename *string `android:"arch_variant"`

	// When set to true, and filename property is not set, the name for the installed file
@@ -127,9 +132,9 @@ type PrebuiltEtcModule interface {
	// Returns the sub install directory relative to BaseDir().
	SubDir() string

	// Returns an android.OutputPath to the intermeidate file, which is the renamed prebuilt source
	// Returns an android.OutputPath to the intermediate file, which is the renamed prebuilt source
	// file.
	OutputFile() android.OutputPath
	OutputFiles(tag string) (android.Paths, error)
}

type PrebuiltEtc struct {
@@ -142,8 +147,8 @@ type PrebuiltEtc struct {
	properties       prebuiltEtcProperties
	subdirProperties prebuiltSubdirProperties

	sourceFilePath android.Path
	outputFilePath android.OutputPath
	sourceFilePaths android.Paths
	outputFilePaths android.OutputPaths
	// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
	installDirBase               string
	installDirBase64             string
@@ -246,6 +251,9 @@ func (p *PrebuiltEtc) SetImageVariation(ctx android.BaseModuleContext, variation
}

func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path {
	if len(p.properties.Srcs) > 0 {
		panic(fmt.Errorf("SourceFilePath not available on multi-source prebuilt %q", p.Name()))
	}
	return android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
}

@@ -260,7 +268,10 @@ func (p *PrebuiltEtc) SetAdditionalDependencies(paths android.Paths) {
}

func (p *PrebuiltEtc) OutputFile() android.OutputPath {
	return p.outputFilePath
	if len(p.properties.Srcs) > 0 {
		panic(fmt.Errorf("OutputFile not available on multi-source prebuilt %q", p.Name()))
	}
	return p.outputFilePaths[0]
}

var _ android.OutputFileProducer = (*PrebuiltEtc)(nil)
@@ -268,7 +279,7 @@ var _ android.OutputFileProducer = (*PrebuiltEtc)(nil)
func (p *PrebuiltEtc) OutputFiles(tag string) (android.Paths, error) {
	switch tag {
	case "":
		return android.Paths{p.outputFilePath}, nil
		return p.outputFilePaths.Paths(), nil
	default:
		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
	}
@@ -301,11 +312,44 @@ func (p *PrebuiltEtc) ExcludeFromRecoverySnapshot() bool {
	return false
}

func (p *PrebuiltEtc) installBaseDir(ctx android.ModuleContext) string {
	// If soc install dir was specified and SOC specific is set, set the installDirPath to the
	// specified socInstallDirBase.
	installBaseDir := p.installDirBase
	if p.Target().Arch.ArchType.Multilib == "lib64" && p.installDirBase64 != "" {
		installBaseDir = p.installDirBase64
	}
	if p.SocSpecific() && p.socInstallDirBase != "" {
		installBaseDir = p.socInstallDirBase
	}
	if p.installAvoidMultilibConflict && !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
		installBaseDir = filepath.Join(installBaseDir, ctx.Arch().ArchType.String())
	}
	return installBaseDir
}

func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	var installs []installProperties

	if p.properties.Src != nil && len(p.properties.Srcs) > 0 {
		ctx.PropertyErrorf("src", "src is set. Cannot set srcs")
	}

	// Check that `sub_dir` and `relative_install_path` are not set at the same time.
	if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
		ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
	}
	p.installDirPath = android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir())

	filename := proptools.String(p.properties.Filename)
	filenameFromSrc := proptools.Bool(p.properties.Filename_from_src)
	if p.properties.Src != nil {
		p.sourceFilePath = android.PathForModuleSrc(ctx, proptools.String(p.properties.Src))
		p.sourceFilePaths = android.PathsForModuleSrc(ctx, []string{proptools.String(p.properties.Src)})
		// If the source was not found, set a fake source path to
		// support AllowMissingDependencies executions.
		if len(p.sourceFilePaths) == 0 {
			p.sourceFilePaths = android.Paths{android.PathForModuleSrc(ctx)}
		}

		// Determine the output file basename.
		// If Filename is set, use the name specified by the property.
@@ -317,87 +361,102 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
				return
			}
		} else if filenameFromSrc {
			filename = p.sourceFilePath.Base()
			filename = p.sourceFilePaths[0].Base()
		} else {
			filename = ctx.ModuleName()
		}
		if strings.Contains(filename, "/") {
			ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
			return
		}
		p.outputFilePaths = android.OutputPaths{android.PathForModuleOut(ctx, filename).OutputPath}

		ip := installProperties{
			filename:       filename,
			sourceFilePath: p.sourceFilePaths[0],
			outputFilePath: p.outputFilePaths[0],
			installDirPath: p.installDirPath,
			symlinks:       p.properties.Symlinks,
		}
		installs = append(installs, ip)
	} else if len(p.properties.Srcs) > 0 {
		if filename != "" {
			ctx.PropertyErrorf("filename", "filename cannot be set when using srcs")
		}
		if len(p.properties.Symlinks) > 0 {
			ctx.PropertyErrorf("symlinks", "symlinks cannot be set when using srcs")
		}
		if p.properties.Filename_from_src != nil {
			ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs")
		}
		p.sourceFilePaths = android.PathsForModuleSrc(ctx, p.properties.Srcs)
		for _, src := range p.sourceFilePaths {
			filename := src.Base()
			output := android.PathForModuleOut(ctx, filename).OutputPath
			ip := installProperties{
				filename:       filename,
				sourceFilePath: src,
				outputFilePath: output,
				installDirPath: p.installDirPath,
			}
			p.outputFilePaths = append(p.outputFilePaths, output)
			installs = append(installs, ip)
		}
	} else if ctx.Config().AllowMissingDependencies() {
		// If no srcs was set and AllowMissingDependencies is enabled then
		// mark the module as missing dependencies and set a fake source path
		// and file name.
		ctx.AddMissingDependencies([]string{"MISSING_PREBUILT_SRC_FILE"})
		p.sourceFilePath = android.PathForModuleSrc(ctx)
		p.sourceFilePaths = android.Paths{android.PathForModuleSrc(ctx)}
		if filename == "" {
			filename = ctx.ModuleName()
		}
		p.outputFilePaths = android.OutputPaths{android.PathForModuleOut(ctx, filename).OutputPath}
		ip := installProperties{
			filename:       filename,
			sourceFilePath: p.sourceFilePaths[0],
			outputFilePath: p.outputFilePaths[0],
			installDirPath: p.installDirPath,
		}
		installs = append(installs, ip)
	} else {
		ctx.PropertyErrorf("src", "missing prebuilt source file")
		return
	}

	if strings.Contains(filename, "/") {
		ctx.PropertyErrorf("filename", "filename cannot contain separator '/'")
		return
	}

	// Check that `sub_dir` and `relative_install_path` are not set at the same time.
	if p.subdirProperties.Sub_dir != nil && p.subdirProperties.Relative_install_path != nil {
		ctx.PropertyErrorf("sub_dir", "relative_install_path is set. Cannot set sub_dir")
	}

	// If soc install dir was specified and SOC specific is set, set the installDirPath to the
	// specified socInstallDirBase.
	installBaseDir := p.installDirBase
	if p.Target().Arch.ArchType.Multilib == "lib64" && p.installDirBase64 != "" {
		installBaseDir = p.installDirBase64
	}
	if p.SocSpecific() && p.socInstallDirBase != "" {
		installBaseDir = p.socInstallDirBase
	}
	if p.installAvoidMultilibConflict && !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
		installBaseDir = filepath.Join(installBaseDir, ctx.Arch().ArchType.String())
	// Call InstallFile even when uninstallable to make the module included in the package.
	if !p.Installable() {
		p.SkipInstall()
	}

	p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())

	// Call InstallFile even when uninstallable to make the module included in the package
	ip := installProperties{
		installable:    p.Installable(),
		filename:       filename,
		sourceFilePath: p.sourceFilePath,
		symlinks:       p.properties.Symlinks,
	for _, ip := range installs {
		ip.addInstallRules(ctx)
	}
	p.addInstallRules(ctx, ip)
	android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}

type installProperties struct {
	installable    bool
	filename       string
	sourceFilePath android.Path
	outputFilePath android.OutputPath
	installDirPath android.InstallPath
	symlinks       []string
}

// utility function to add install rules to the build graph.
// Reduces code duplication between Soong and Mixed build analysis
func (p *PrebuiltEtc) addInstallRules(ctx android.ModuleContext, ip installProperties) {
	if !ip.installable {
		p.SkipInstall()
	}

func (ip *installProperties) addInstallRules(ctx android.ModuleContext) {
	// Copy the file from src to a location in out/ with the correct `filename`
	// This ensures that outputFilePath has the correct name for others to
	// use, as the source file may have a different name.
	p.outputFilePath = android.PathForModuleOut(ctx, ip.filename).OutputPath
	ctx.Build(pctx, android.BuildParams{
		Rule:   android.Cp,
		Output: p.outputFilePath,
		Output: ip.outputFilePath,
		Input:  ip.sourceFilePath,
	})

	installPath := ctx.InstallFile(p.installDirPath, ip.filename, p.outputFilePath)
	installPath := ctx.InstallFile(ip.installDirPath, ip.filename, ip.outputFilePath)
	for _, sl := range ip.symlinks {
		ctx.InstallSymlink(p.installDirPath, sl, installPath)
		ctx.InstallSymlink(ip.installDirPath, sl, installPath)
	}
}

@@ -421,15 +480,15 @@ func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries {
		class = "ETC"
	}

	return []android.AndroidMkEntries{android.AndroidMkEntries{
	return []android.AndroidMkEntries{{
		Class:      class,
		SubName:    nameSuffix,
		OutputFile: android.OptionalPathForPath(p.outputFilePath),
		OutputFile: android.OptionalPathForPath(p.outputFilePaths[0]),
		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
				entries.SetString("LOCAL_MODULE_TAGS", "optional")
				entries.SetString("LOCAL_MODULE_PATH", p.installDirPath.String())
				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePath.Base())
				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePaths[0].Base())
				if len(p.properties.Symlinks) > 0 {
					entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...)
				}
@@ -700,7 +759,11 @@ func generatePrebuiltSnapshot(s snapshot.SnapshotSingleton, ctx android.Singleto
		targetArch := "arch-" + m.Target().Arch.ArchType.String()

		snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "etc", m.BaseModuleName())
		snapshotOutputs = append(snapshotOutputs, copyFile(ctx, m.OutputFile(), snapshotLibOut, s.Fake))
		outputs, _ := m.OutputFiles("")
		for _, output := range outputs {
			cp := copyFile(ctx, output, snapshotLibOut, s.Fake)
			snapshotOutputs = append(snapshotOutputs, cp)
		}

		prop := snapshot.SnapshotJsonFlags{}
		propOut := snapshotLibOut + ".json"
+17 −3
Original line number Diff line number Diff line
@@ -96,7 +96,7 @@ func TestPrebuiltEtcOutputPath(t *testing.T) {
	`)

	p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc)
	android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePath.Base())
	android.AssertStringEquals(t, "output file path", "foo.installed.conf", p.outputFilePaths[0].Base())
}

func TestPrebuiltEtcGlob(t *testing.T) {
@@ -113,10 +113,24 @@ func TestPrebuiltEtcGlob(t *testing.T) {
	`)

	p := result.Module("my_foo", "android_arm64_armv8-a").(*PrebuiltEtc)
	android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePath.Base())
	android.AssertStringEquals(t, "my_foo output file path", "my_foo", p.outputFilePaths[0].Base())

	p = result.Module("my_bar", "android_arm64_armv8-a").(*PrebuiltEtc)
	android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePath.Base())
	android.AssertStringEquals(t, "my_bar output file path", "bar.conf", p.outputFilePaths[0].Base())
}

func TestPrebuiltEtcMultipleSrcs(t *testing.T) {
	result := prepareForPrebuiltEtcTest.RunTestWithBp(t, `
		prebuilt_etc {
			name: "foo",
			srcs: ["*.conf"],
		}
	`)

	p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc)
	android.AssertStringEquals(t, "output file path", "bar.conf", p.outputFilePaths[0].Base())
	android.AssertStringEquals(t, "output file path", "baz.conf", p.outputFilePaths[1].Base())
	android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base())
}

func TestPrebuiltEtcAndroidMk(t *testing.T) {
+5 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import (

	"android/soong/android"
	"android/soong/dexpreopt"
	"android/soong/etc"
)

const (
@@ -3174,10 +3175,12 @@ func (module *sdkLibraryXml) SubDir() string {
}

// from android.PrebuiltEtcModule
func (module *sdkLibraryXml) OutputFile() android.OutputPath {
	return module.outputFilePath
func (module *sdkLibraryXml) OutputFiles(tag string) (android.Paths, error) {
	return android.OutputPaths{module.outputFilePath}.Paths(), nil
}

var _ etc.PrebuiltEtcModule = (*sdkLibraryXml)(nil)

// from android.ApexModule
func (module *sdkLibraryXml) AvailableFor(what string) bool {
	return true