diff options
| -rw-r--r-- | etc/prebuilt_etc.go | 57 | ||||
| -rw-r--r-- | etc/prebuilt_etc_test.go | 135 |
2 files changed, 167 insertions, 25 deletions
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go index fc6d1f74e..fbe24d1da 100644 --- a/etc/prebuilt_etc.go +++ b/etc/prebuilt_etc.go @@ -78,9 +78,16 @@ type prebuiltEtcProperties struct { Src proptools.Configurable[string] `android:"path,arch_variant,replace_instead_of_append"` // 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. + // Mutually exclusive with src. When used, filename_from_src is set to true unless dsts is also + // set. May use globs in filenames. Srcs proptools.Configurable[[]string] `android:"path,arch_variant"` + // Destination files of this prebuilt. Requires srcs to be used and causes srcs not to implicitly + // set filename_from_src. This can be used to install each source file to a different directory + // and/or change filenames when files are installed. Must be exactly one entry per source file, + // which means care must be taken if srcs has globs. + Dsts proptools.Configurable[[]string] `android:"path,arch_variant"` + // Optional name for the installed file. If unspecified, name of the module is used as the file // name. Only available when using a single source (src). Filename *string `android:"arch_variant"` @@ -166,7 +173,7 @@ type PrebuiltEtc struct { // The base install location when soc_specific property is set to true, e.g. "firmware" for // prebuilt_firmware. socInstallDirBase string - installDirPath android.InstallPath + installDirPaths []android.InstallPath additionalDependencies *android.Paths usedSrcsProperty bool @@ -279,7 +286,10 @@ func (p *PrebuiltEtc) SourceFilePath(ctx android.ModuleContext) android.Path { } func (p *PrebuiltEtc) InstallDirPath() android.InstallPath { - return p.installDirPath + if len(p.installDirPaths) != 1 { + panic(fmt.Errorf("InstallDirPath not available on multi-source prebuilt %q", p.Name())) + } + return p.installDirPaths[0] } // This allows other derivative modules (e.g. prebuilt_etc_xml) to perform @@ -338,12 +348,16 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { if srcProperty.IsPresent() && len(srcsProperty) > 0 { ctx.PropertyErrorf("src", "src is set. Cannot set srcs") } + dstsProperty := p.properties.Dsts.GetOrDefault(ctx, nil) + if len(dstsProperty) > 0 && len(srcsProperty) == 0 { + ctx.PropertyErrorf("dsts", "dsts is set. Must use 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()) + baseInstallDirPath := android.PathForModuleInstall(ctx, p.installBaseDir(ctx), p.SubDir()) filename := proptools.String(p.properties.Filename) filenameFromSrc := proptools.Bool(p.properties.Filename_from_src) @@ -379,10 +393,11 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { filename: filename, sourceFilePath: p.sourceFilePaths[0], outputFilePath: p.outputFilePaths[0], - installDirPath: p.installDirPath, + installDirPath: baseInstallDirPath, symlinks: p.properties.Symlinks, } installs = append(installs, ip) + p.installDirPaths = append(p.installDirPaths, baseInstallDirPath) } else if len(srcsProperty) > 0 { p.usedSrcsProperty = true if filename != "" { @@ -392,20 +407,39 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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") + if len(dstsProperty) > 0 { + ctx.PropertyErrorf("filename_from_src", "dsts is set. Cannot set filename_from_src") + } else { + ctx.PropertyErrorf("filename_from_src", "filename_from_src is implicitly set to true when using srcs") + } } p.sourceFilePaths = android.PathsForModuleSrc(ctx, srcsProperty) - for _, src := range p.sourceFilePaths { - filename := src.Base() + if len(dstsProperty) > 0 && len(p.sourceFilePaths) != len(dstsProperty) { + ctx.PropertyErrorf("dsts", "Must have one entry in dsts per source file") + } + for i, src := range p.sourceFilePaths { + var filename string + var installDirPath android.InstallPath + + if len(dstsProperty) > 0 { + var dstdir string + + dstdir, filename = filepath.Split(dstsProperty[i]) + installDirPath = baseInstallDirPath.Join(ctx, dstdir) + } else { + filename = src.Base() + installDirPath = baseInstallDirPath + } output := android.PathForModuleOut(ctx, filename).OutputPath ip := installProperties{ filename: filename, sourceFilePath: src, outputFilePath: output, - installDirPath: p.installDirPath, + installDirPath: installDirPath, } p.outputFilePaths = append(p.outputFilePaths, output) installs = append(installs, ip) + p.installDirPaths = append(p.installDirPaths, installDirPath) } } else if ctx.Config().AllowMissingDependencies() { // If no srcs was set and AllowMissingDependencies is enabled then @@ -421,9 +455,10 @@ func (p *PrebuiltEtc) GenerateAndroidBuildActions(ctx android.ModuleContext) { filename: filename, sourceFilePath: p.sourceFilePaths[0], outputFilePath: p.outputFilePaths[0], - installDirPath: p.installDirPath, + installDirPath: baseInstallDirPath, } installs = append(installs, ip) + p.installDirPaths = append(p.installDirPaths, baseInstallDirPath) } else { ctx.PropertyErrorf("src", "missing prebuilt source file") return @@ -493,7 +528,7 @@ func (p *PrebuiltEtc) AndroidMkEntries() []android.AndroidMkEntries { 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_MODULE_PATH", p.installDirPaths[0].String()) entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.outputFilePaths[0].Base()) if len(p.properties.Symlinks) > 0 { entries.AddStrings("LOCAL_MODULE_SYMLINKS", p.properties.Symlinks...) diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go index e739afed9..75c6d1243 100644 --- a/etc/prebuilt_etc_test.go +++ b/etc/prebuilt_etc_test.go @@ -119,6 +119,113 @@ func TestPrebuiltEtcMultipleSrcs(t *testing.T) { android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[2].Base()) } +func TestPrebuiltEtcDsts(t *testing.T) { + result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` + prebuilt_etc { + name: "foo", + srcs: ["foo.conf", "bar.conf"], + dsts: ["foodir/foo.conf", "bardir/extradir/different.name"], + } + `) + + p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) + android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base()) + android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base()) + + expectedPaths := [...]string{ + "out/soong/target/product/test_device/system/etc/foodir", + "out/soong/target/product/test_device/system/etc/bardir/extradir", + } + android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0]) + android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1]) +} + +func TestPrebuiltEtcDstsPlusRelativeInstallPath(t *testing.T) { + result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` + prebuilt_etc { + name: "foo", + srcs: ["foo.conf", "bar.conf"], + dsts: ["foodir/foo.conf", "bardir/extradir/different.name"], + relative_install_path: "somewhere", + } + `) + + p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) + android.AssertStringEquals(t, "output file path", "foo.conf", p.outputFilePaths[0].Base()) + android.AssertStringEquals(t, "output file path", "different.name", p.outputFilePaths[1].Base()) + + expectedPaths := [...]string{ + "out/soong/target/product/test_device/system/etc/somewhere/foodir", + "out/soong/target/product/test_device/system/etc/somewhere/bardir/extradir", + } + android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[0], p.installDirPaths[0]) + android.AssertPathRelativeToTopEquals(t, "install dir", expectedPaths[1], p.installDirPaths[1]) +} + +func TestPrebuiltEtcDstsSrcGlob(t *testing.T) { + result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` + prebuilt_etc { + name: "foo", + srcs: ["*.conf"], + dsts: ["a.conf", "b.conf", "c.conf"], + } + `) + + p := result.Module("foo", "android_arm64_armv8-a").(*PrebuiltEtc) + android.AssertStringEquals(t, "output file path", "a.conf", p.outputFilePaths[0].Base()) + android.AssertStringEquals(t, "output file path", "b.conf", p.outputFilePaths[1].Base()) + android.AssertStringEquals(t, "output file path", "c.conf", p.outputFilePaths[2].Base()) +} + +func TestPrebuiltEtcDstsSrcGlobDstsTooShort(t *testing.T) { + prepareForPrebuiltEtcTest. + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")). + RunTestWithBp(t, ` + prebuilt_etc { + name: "foo", + srcs: ["*.conf"], + dsts: ["a.conf", "b.conf"], + } + `) +} + +func TestPrebuiltEtcDstsSrcGlobDstsTooLong(t *testing.T) { + prepareForPrebuiltEtcTest. + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("Must have one entry in dsts per source file")). + RunTestWithBp(t, ` + prebuilt_etc { + name: "foo", + srcs: ["*.conf"], + dsts: ["a.conf", "b.conf", "c.conf", "d.conf"], + } + `) +} + +func TestPrebuiltEtcCannotDstsWithSrc(t *testing.T) { + prepareForPrebuiltEtcTest. + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Must use srcs")). + RunTestWithBp(t, ` + prebuilt_etc { + name: "foo.conf", + src: "foo.conf", + dsts: ["a.conf"], + } + `) +} + +func TestPrebuiltEtcCannotDstsWithFilenameFromSrc(t *testing.T) { + prepareForPrebuiltEtcTest. + ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("dsts is set. Cannot set filename_from_src")). + RunTestWithBp(t, ` + prebuilt_etc { + name: "foo.conf", + srcs: ["foo.conf"], + dsts: ["a.conf"], + filename_from_src: true, + } + `) +} + func TestPrebuiltEtcAndroidMk(t *testing.T) { result := prepareForPrebuiltEtcTest.RunTestWithBp(t, ` prebuilt_etc { @@ -165,7 +272,7 @@ func TestPrebuiltEtcRelativeInstallPathInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/etc/bar" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltEtcCannotSetRelativeInstallPathAndSubDir(t *testing.T) { @@ -231,7 +338,7 @@ func TestPrebuiltRootInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltRootInstallDirPathValidate(t *testing.T) { @@ -256,7 +363,7 @@ func TestPrebuiltAvbInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/root/avb" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltAvdInstallDirPathValidate(t *testing.T) { @@ -280,7 +387,7 @@ func TestPrebuiltUserShareInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/usr/share/bar" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) { @@ -295,7 +402,7 @@ func TestPrebuiltUserShareHostInstallDirPath(t *testing.T) { buildOS := result.Config.BuildOS.String() p := result.Module("foo.conf", buildOS+"_common").(*PrebuiltEtc) expected := filepath.Join("out/soong/host", result.Config.PrebuiltOS(), "usr", "share", "bar") - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) { @@ -309,7 +416,7 @@ func TestPrebuiltPrebuiltUserHyphenDataInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/usr/hyphen-data/bar" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) { @@ -323,7 +430,7 @@ func TestPrebuiltPrebuiltUserKeyLayoutInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/usr/keylayout/bar" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) { @@ -337,7 +444,7 @@ func TestPrebuiltPrebuiltUserKeyCharsInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/usr/keychars/bar" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) { @@ -351,7 +458,7 @@ func TestPrebuiltPrebuiltUserIdcInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/usr/idc/bar" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltFontInstallDirPath(t *testing.T) { @@ -364,7 +471,7 @@ func TestPrebuiltFontInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/fonts" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltOverlayInstallDirPath(t *testing.T) { @@ -377,7 +484,7 @@ func TestPrebuiltOverlayInstallDirPath(t *testing.T) { p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) expected := "out/soong/target/product/test_device/system/overlay" - android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", expected, p.installDirPaths[0]) } func TestPrebuiltFirmwareDirPath(t *testing.T) { @@ -409,7 +516,7 @@ func TestPrebuiltFirmwareDirPath(t *testing.T) { t.Run(tt.description, func(t *testing.T) { result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config) p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) - android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0]) }) } } @@ -443,7 +550,7 @@ func TestPrebuiltDSPDirPath(t *testing.T) { t.Run(tt.description, func(t *testing.T) { result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config) p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) - android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0]) }) } } @@ -477,7 +584,7 @@ func TestPrebuiltRFSADirPath(t *testing.T) { t.Run(tt.description, func(t *testing.T) { result := prepareForPrebuiltEtcTest.RunTestWithBp(t, tt.config) p := result.Module("foo.conf", "android_arm64_armv8-a").(*PrebuiltEtc) - android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPath) + android.AssertPathRelativeToTopEquals(t, "install dir", tt.expectedPath, p.installDirPaths[0]) }) } } |