diff --git a/android/paths.go b/android/paths.go index 20ff55e85..65f129ce8 100644 --- a/android/paths.go +++ b/android/paths.go @@ -1555,3 +1555,15 @@ func absolutePath(path string) string { } return filepath.Join(absSrcDir, path) } + +// A DataPath represents the path of a file to be used as data, for example +// a test library to be installed alongside a test. +// The data file should be installed (copied from ``) to +// `//`, or +// `/` if RelativeInstallPath is empty. +type DataPath struct { + // The path of the data file that should be copied into the data directory + SrcPath Path + // The install path of the data file, relative to the install root. + RelativeInstallPath string +} diff --git a/apex/androidmk.go b/apex/androidmk.go index b9bcc3acf..10cc4b6c2 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -116,9 +116,9 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexBundleName, apexName, mo if len(fi.symlinks) > 0 { fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " ")) } - newDataPaths := []android.Path{} + newDataPaths := []android.DataPath{} for _, path := range fi.dataPaths { - dataOutPath := modulePath + ":" + path.Rel() + dataOutPath := modulePath + ":" + path.SrcPath.Rel() if ok := seenDataOutPaths[dataOutPath]; !ok { newDataPaths = append(newDataPaths, path) seenDataOutPaths[dataOutPath] = true diff --git a/apex/apex.go b/apex/apex.go index b29017d1f..aa0f9061f 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -1145,7 +1145,7 @@ type apexFile struct { module android.Module // list of symlinks that will be created in installDir that point to this apexFile symlinks []string - dataPaths android.Paths + dataPaths []android.DataPath transitiveDep bool moduleDir string diff --git a/apex/builder.go b/apex/builder.go index 49e4642bf..81f813172 100644 --- a/apex/builder.go +++ b/apex/builder.go @@ -403,16 +403,16 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { } for _, d := range fi.dataPaths { // TODO(eakammer): This is now the third repetition of ~this logic for test paths, refactoring should be possible - relPath := d.Rel() - dataPath := d.String() + relPath := d.SrcPath.Rel() + dataPath := d.SrcPath.String() if !strings.HasSuffix(dataPath, relPath) { panic(fmt.Errorf("path %q does not end with %q", dataPath, relPath)) } dataDest := android.PathForModuleOut(ctx, "image"+suffix, fi.apexRelativePath(relPath)).String() - copyCommands = append(copyCommands, "cp -f "+d.String()+" "+dataDest) - implicitInputs = append(implicitInputs, d) + copyCommands = append(copyCommands, "cp -f "+d.SrcPath.String()+" "+dataDest) + implicitInputs = append(implicitInputs, d.SrcPath) } } @@ -473,7 +473,7 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) { if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") { executablePaths = append(executablePaths, pathInApex) for _, d := range f.dataPaths { - readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.Rel())) + readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.SrcPath.Rel())) } for _, s := range f.symlinks { executablePaths = append(executablePaths, filepath.Join(f.installDir, s)) diff --git a/cc/androidmk.go b/cc/androidmk.go index 3f812c2c0..e91b40ad8 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -149,21 +149,25 @@ func (c *Module) AndroidMkEntries() []android.AndroidMkEntries { return []android.AndroidMkEntries{entries} } -func AndroidMkDataPaths(data android.Paths) []string { +func AndroidMkDataPaths(data []android.DataPath) []string { var testFiles []string for _, d := range data { - rel := d.Rel() - path := d.String() + rel := d.SrcPath.Rel() + path := d.SrcPath.String() if !strings.HasSuffix(path, rel) { panic(fmt.Errorf("path %q does not end with %q", path, rel)) } path = strings.TrimSuffix(path, rel) - testFiles = append(testFiles, path+":"+rel) + testFileString := path + ":" + rel + if len(d.RelativeInstallPath) > 0 { + testFileString += ":" + d.RelativeInstallPath + } + testFiles = append(testFiles, testFileString) } return testFiles } -func androidMkWriteTestData(data android.Paths, ctx AndroidMkContext, entries *android.AndroidMkEntries) { +func androidMkWriteTestData(data []android.DataPath, ctx AndroidMkContext, entries *android.AndroidMkEntries) { testFiles := AndroidMkDataPaths(data) if len(testFiles) > 0 { entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { @@ -357,8 +361,11 @@ func (benchmark *benchmarkDecorator) AndroidMkEntries(ctx AndroidMkContext, entr entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true) } }) - - androidMkWriteTestData(benchmark.data, ctx, entries) + dataPaths := []android.DataPath{} + for _, srcPath := range benchmark.data { + dataPaths = append(dataPaths, android.DataPath{SrcPath: srcPath}) + } + androidMkWriteTestData(dataPaths, ctx, entries) } func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { diff --git a/cc/cc.go b/cc/cc.go index 0d5b6bdf5..fdf28799c 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -1401,9 +1401,9 @@ func (c *Module) IsTestPerSrcAllTestsVariation() bool { return ok && test.isAllTestsVariation() } -func (c *Module) DataPaths() android.Paths { +func (c *Module) DataPaths() []android.DataPath { if p, ok := c.installer.(interface { - dataPaths() android.Paths + dataPaths() []android.DataPath }); ok { return p.dataPaths() } diff --git a/cc/cc_test.go b/cc/cc_test.go index 8a1c8ed4c..041c4a388 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -539,7 +539,7 @@ func TestDataLibs(t *testing.T) { data_libs: ["test_lib"], gtest: false, } - ` + ` config := TestConfig(buildDir, android.Android, nil, bp, nil) config.TestProductVariables.DeviceVndkVersion = StringPtr("current") @@ -564,7 +564,7 @@ func TestDataLibs(t *testing.T) { } outputPath := outputFiles[0].String() - testBinaryPath := testBinary.dataPaths()[0].String() + testBinaryPath := testBinary.dataPaths()[0].SrcPath.String() if !strings.HasSuffix(outputPath, "/main_test") { t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath) @@ -576,6 +576,54 @@ func TestDataLibs(t *testing.T) { } } +func TestDataLibsRelativeInstallPath(t *testing.T) { + bp := ` + cc_test_library { + name: "test_lib", + srcs: ["test_lib.cpp"], + relative_install_path: "foo/bar/baz", + gtest: false, + } + + cc_test { + name: "main_test", + data_libs: ["test_lib"], + gtest: false, + } + ` + + config := TestConfig(buildDir, android.Android, nil, bp, nil) + config.TestProductVariables.DeviceVndkVersion = StringPtr("current") + config.TestProductVariables.Platform_vndk_version = StringPtr("VER") + config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true) + + ctx := testCcWithConfig(t, config) + module := ctx.ModuleForTests("main_test", "android_arm_armv7-a-neon").Module() + testBinary := module.(*Module).linker.(*testBinary) + outputFiles, err := module.(android.OutputFileProducer).OutputFiles("") + if err != nil { + t.Fatalf("Expected cc_test to produce output files, error: %s", err) + } + if len(outputFiles) != 1 { + t.Errorf("expected exactly one output file. output files: [%s]", outputFiles) + } + if len(testBinary.dataPaths()) != 1 { + t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths()) + } + + outputPath := outputFiles[0].String() + testBinaryPath := testBinary.dataPaths()[0] + + if !strings.HasSuffix(outputPath, "/main_test") { + t.Errorf("expected test output file to be 'main_test', but was '%s'", outputPath) + } + entries := android.AndroidMkEntriesForTest(t, config, "", module)[0] + if !strings.HasSuffix(entries.EntryMap["LOCAL_TEST_DATA"][0], ":test_lib.so:foo/bar/baz") { + t.Errorf("expected LOCAL_TEST_DATA to end with `:test_lib.so:foo/bar/baz`,"+ + " but was '%s'", testBinaryPath) + } +} + func TestVndkWhenVndkVersionIsNotSet(t *testing.T) { ctx := testCcNoVndk(t, ` cc_library { diff --git a/cc/test.go b/cc/test.go index 37afb0ca4..9b6864a4e 100644 --- a/cc/test.go +++ b/cc/test.go @@ -165,7 +165,7 @@ func (test *testBinary) srcs() []string { return test.baseCompiler.Properties.Srcs } -func (test *testBinary) dataPaths() android.Paths { +func (test *testBinary) dataPaths() []android.DataPath { return test.data } @@ -310,7 +310,7 @@ type testBinary struct { *binaryDecorator *baseCompiler Properties TestBinaryProperties - data android.Paths + data []android.DataPath testConfig android.Path } @@ -339,7 +339,11 @@ func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { } func (test *testBinary) install(ctx ModuleContext, file android.Path) { - test.data = android.PathsForModuleSrc(ctx, test.Properties.Data) + dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data) + + for _, dataSrcPath := range dataSrcPaths { + test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath}) + } ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) { depName := ctx.OtherModuleName(dep) @@ -348,10 +352,14 @@ func (test *testBinary) install(ctx ModuleContext, file android.Path) { if !ok { ctx.ModuleErrorf("data_lib %q is not a linkable cc module", depName) } + ccModule, ok := dep.(*Module) + if !ok { + ctx.ModuleErrorf("data_lib %q is not a cc module", depName) + } if ccDep.OutputFile().Valid() { - test.data = append(test.data, ccDep.OutputFile().Path()) - } else { - ctx.ModuleErrorf("data_lib %q has no output file", depName) + test.data = append(test.data, + android.DataPath{SrcPath: ccDep.OutputFile().Path(), + RelativeInstallPath: ccModule.installer.relativeInstallPath()}) } })