Merge "Add source collision test, rust_bindgen doc."
diff --git a/android/paths.go b/android/paths.go
index 20ff55e..65f129c 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1555,3 +1555,15 @@
}
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 `<SrcPath>`) to
+// `<install_root>/<RelativeInstallPath>/<filename>`, or
+// `<install_root>/<filename>` 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 b9bcc3a..10cc4b6 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -116,9 +116,9 @@
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 045ae82..d0c4e6e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1145,7 +1145,7 @@
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 49e4642..a70c767 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -403,16 +403,16 @@
}
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()
+ dataDest := android.PathForModuleOut(ctx, "image"+suffix, fi.apexRelativePath(relPath), d.RelativeInstallPath).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 @@
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.RelativeInstallPath, 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 3f812c2..e91b40a 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -149,21 +149,25 @@
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 @@
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 0d5b6bd..fdf2879 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1401,9 +1401,9 @@
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 8a1c8ed..38a5c2d 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -539,7 +539,7 @@
data_libs: ["test_lib"],
gtest: false,
}
- `
+ `
config := TestConfig(buildDir, android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
@@ -564,7 +564,7 @@
}
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,53 @@
}
}
+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()
+
+ 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'", entries.EntryMap["LOCAL_TEST_DATA"][0])
+ }
+}
+
func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
ctx := testCcNoVndk(t, `
cc_library {
@@ -2919,6 +2966,52 @@
}
}
+func TestDataLibsPrebuiltSharedTestLibrary(t *testing.T) {
+ bp := `
+ cc_prebuilt_test_library_shared {
+ name: "test_lib",
+ relative_install_path: "foo/bar/baz",
+ srcs: ["srcpath/dontusethispath/baz.so"],
+ }
+
+ 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()
+
+ 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'", entries.EntryMap["LOCAL_TEST_DATA"][0])
+ }
+}
+
func TestVersionedStubs(t *testing.T) {
ctx := testCc(t, `
cc_library_shared {
diff --git a/cc/pgo.go b/cc/pgo.go
index 9298e7a..674e1bb 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -199,8 +199,8 @@
return false
}
- // If at least one property exists, validate that all properties exist
- if !profileKindPresent || !filePresent || !benchmarksPresent {
+ // profileKindPresent and filePresent are mandatory properties.
+ if !profileKindPresent || !filePresent {
var missing []string
if !profileKindPresent {
missing = append(missing, "profile kind (either \"instrumentation\" or \"sampling\" property)")
@@ -208,13 +208,15 @@
if !filePresent {
missing = append(missing, "profile_file property")
}
- if !benchmarksPresent {
- missing = append(missing, "non-empty benchmarks property")
- }
missingProps := strings.Join(missing, ", ")
ctx.ModuleErrorf("PGO specification is missing properties: " + missingProps)
}
+ // Benchmark property is mandatory for instrumentation PGO.
+ if isInstrumentation && !benchmarksPresent {
+ ctx.ModuleErrorf("Instrumentation PGO specification is missing benchmark property")
+ }
+
if isSampling && isInstrumentation {
ctx.PropertyErrorf("pgo", "Exactly one of \"instrumentation\" and \"sampling\" properties must be set")
}
@@ -288,15 +290,17 @@
// Add flags to profile this module based on its profile_kind
if props.ShouldProfileModule && props.isInstrumentation() {
- return props.addInstrumentationProfileGatherFlags(ctx, flags)
+ props.addInstrumentationProfileGatherFlags(ctx, flags)
+ // Instrumentation PGO use and gather flags cannot coexist.
+ return flags
} else if props.ShouldProfileModule && props.isSampling() {
- return props.addSamplingProfileGatherFlags(ctx, flags)
+ props.addSamplingProfileGatherFlags(ctx, flags)
} else if ctx.DeviceConfig().SamplingPGO() {
- return props.addSamplingProfileGatherFlags(ctx, flags)
+ props.addSamplingProfileGatherFlags(ctx, flags)
}
if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
- return props.addProfileUseFlags(ctx, flags)
+ props.addProfileUseFlags(ctx, flags)
}
return flags
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 0751f1c..653b43e 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -26,6 +26,7 @@
ctx.RegisterModuleType("cc_prebuilt_library", PrebuiltLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
+ ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", prebuiltBinaryFactory)
}
@@ -243,6 +244,16 @@
return module.Init()
}
+// cc_prebuilt_test_library_shared installs a precompiled shared library
+// to be used as a data dependency of a test-related module (such as cc_test, or
+// cc_test_library).
+func PrebuiltSharedTestLibraryFactory() android.Module {
+ module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported)
+ library.BuildOnlyShared()
+ library.baseInstaller = NewTestInstaller()
+ return module.Init()
+}
+
func NewPrebuiltSharedLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module, library := NewPrebuiltLibrary(hod)
library.BuildOnlyShared()
diff --git a/cc/test.go b/cc/test.go
index 37afb0c..9b6864a 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -165,7 +165,7 @@
return test.baseCompiler.Properties.Srcs
}
-func (test *testBinary) dataPaths() android.Paths {
+func (test *testBinary) dataPaths() []android.DataPath {
return test.data
}
@@ -310,7 +310,7 @@
*binaryDecorator
*baseCompiler
Properties TestBinaryProperties
- data android.Paths
+ data []android.DataPath
testConfig android.Path
}
@@ -339,7 +339,11 @@
}
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 @@
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()})
}
})
diff --git a/rust/builder.go b/rust/builder.go
index 4872709..45cd268 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -42,14 +42,14 @@
_ = pctx.SourcePathVariable("clippyCmd", "${config.RustBin}/clippy-driver")
clippyDriver = pctx.AndroidStaticRule("clippy",
blueprint.RuleParams{
- Command: "$clippyCmd " +
+ Command: "$envVars $clippyCmd " +
// Because clippy-driver uses rustc as backend, we need to have some output even during the linting.
// Use the metadata output as it has the smallest footprint.
"--emit metadata -o $out $in ${libFlags} " +
"$rustcFlags $clippyFlags",
CommandDeps: []string{"$clippyCmd"},
},
- "rustcFlags", "libFlags", "clippyFlags")
+ "rustcFlags", "libFlags", "clippyFlags", "envVars")
zip = pctx.AndroidStaticRule("zip",
blueprint.RuleParams{
@@ -199,25 +199,6 @@
output.coverageFile = gcnoFile
}
- if flags.Clippy {
- clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
- ctx.Build(pctx, android.BuildParams{
- Rule: clippyDriver,
- Description: "clippy " + main.Rel(),
- Output: clippyFile,
- ImplicitOutputs: nil,
- Inputs: inputs,
- Implicits: implicits,
- Args: map[string]string{
- "rustcFlags": strings.Join(rustcFlags, " "),
- "libFlags": strings.Join(libFlags, " "),
- "clippyFlags": strings.Join(flags.ClippyFlags, " "),
- },
- })
- // Declare the clippy build as an implicit dependency of the original crate.
- implicits = append(implicits, clippyFile)
- }
-
if len(deps.SrcDeps) > 0 {
genSubDir := "out/"
moduleGenDir := android.PathForModuleOut(ctx, genSubDir)
@@ -244,6 +225,26 @@
envVars = append(envVars, "OUT_DIR=$$PWD/"+moduleGenDir.String())
}
+ if flags.Clippy {
+ clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: clippyDriver,
+ Description: "clippy " + main.Rel(),
+ Output: clippyFile,
+ ImplicitOutputs: nil,
+ Inputs: inputs,
+ Implicits: implicits,
+ Args: map[string]string{
+ "rustcFlags": strings.Join(rustcFlags, " "),
+ "libFlags": strings.Join(libFlags, " "),
+ "clippyFlags": strings.Join(flags.ClippyFlags, " "),
+ "envVars": strings.Join(envVars, " "),
+ },
+ })
+ // Declare the clippy build as an implicit dependency of the original crate.
+ implicits = append(implicits, clippyFile)
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: rustc,
Description: "rustc " + main.Rel(),