Merge "Add boot_image module type"
diff --git a/android/apex.go b/android/apex.go
index 31c62e9..d3f8d2a 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -830,9 +830,8 @@
return
}
- // do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version or
- // min_sdk_version is not finalized (e.g. current or codenames)
- if minSdkVersion.IsCurrent() {
+ // do not enforce deps.min_sdk_version if APEX/APK doesn't set min_sdk_version
+ if minSdkVersion.IsNone() {
return
}
diff --git a/android/api_levels.go b/android/api_levels.go
index 08328e1..1b53f3f 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -81,6 +81,10 @@
return this.value == "current"
}
+func (this ApiLevel) IsNone() bool {
+ return this.number == -1
+}
+
// Returns -1 if the current API level is less than the argument, 0 if they
// are equal, and 1 if it is greater than the argument.
func (this ApiLevel) CompareTo(other ApiLevel) int {
diff --git a/android/filegroup.go b/android/filegroup.go
index fd4a2fe..3d1bbc5 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -23,7 +23,7 @@
func init() {
RegisterModuleType("filegroup", FileGroupFactory)
- RegisterBp2BuildMutator("filegroup", bp2buildMutator)
+ RegisterBp2BuildMutator("filegroup", FilegroupBp2Build)
}
// https://docs.bazel.build/versions/master/be/general.html#filegroup
@@ -51,7 +51,7 @@
func (bfg *bazelFilegroup) GenerateAndroidBuildActions(ctx ModuleContext) {}
// TODO: Create helper functions to avoid this boilerplate.
-func bp2buildMutator(ctx TopDownMutatorContext) {
+func FilegroupBp2Build(ctx TopDownMutatorContext) {
if m, ok := ctx.Module().(*fileGroup); ok {
name := "__bp2build__" + m.base().BaseModuleName()
ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{
diff --git a/android/module.go b/android/module.go
index a20dc56..dcc2b84 100644
--- a/android/module.go
+++ b/android/module.go
@@ -1885,19 +1885,11 @@
}
func (e *earlyModuleContext) Glob(globPattern string, excludes []string) Paths {
- ret, err := e.GlobWithDeps(globPattern, excludes)
- if err != nil {
- e.ModuleErrorf("glob: %s", err.Error())
- }
- return pathsForModuleSrcFromFullPath(e, ret, true)
+ return Glob(e, globPattern, excludes)
}
func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
- ret, err := e.GlobWithDeps(globPattern, excludes)
- if err != nil {
- e.ModuleErrorf("glob: %s", err.Error())
- }
- return pathsForModuleSrcFromFullPath(e, ret, false)
+ return GlobFiles(e, globPattern, excludes)
}
func (b *earlyModuleContext) IsSymlink(path Path) bool {
diff --git a/android/paths.go b/android/paths.go
index 592b9e1..b5a1401 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -51,6 +51,53 @@
func (NullPathContext) AddNinjaFileDeps(...string) {}
func (ctx NullPathContext) Config() Config { return ctx.config }
+// EarlyModulePathContext is a subset of EarlyModuleContext methods required by the
+// Path methods. These path methods can be called before any mutators have run.
+type EarlyModulePathContext interface {
+ PathContext
+ PathGlobContext
+
+ ModuleDir() string
+ ModuleErrorf(fmt string, args ...interface{})
+}
+
+var _ EarlyModulePathContext = ModuleContext(nil)
+
+// Glob globs files and directories matching globPattern relative to ModuleDir(),
+// paths in the excludes parameter will be omitted.
+func Glob(ctx EarlyModulePathContext, globPattern string, excludes []string) Paths {
+ ret, err := ctx.GlobWithDeps(globPattern, excludes)
+ if err != nil {
+ ctx.ModuleErrorf("glob: %s", err.Error())
+ }
+ return pathsForModuleSrcFromFullPath(ctx, ret, true)
+}
+
+// GlobFiles globs *only* files (not directories) matching globPattern relative to ModuleDir().
+// Paths in the excludes parameter will be omitted.
+func GlobFiles(ctx EarlyModulePathContext, globPattern string, excludes []string) Paths {
+ ret, err := ctx.GlobWithDeps(globPattern, excludes)
+ if err != nil {
+ ctx.ModuleErrorf("glob: %s", err.Error())
+ }
+ return pathsForModuleSrcFromFullPath(ctx, ret, false)
+}
+
+// ModuleWithDepsPathContext is a subset of *ModuleContext methods required by
+// the Path methods that rely on module dependencies having been resolved.
+type ModuleWithDepsPathContext interface {
+ EarlyModulePathContext
+ GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+}
+
+// ModuleMissingDepsPathContext is a subset of *ModuleContext methods required by
+// the Path methods that rely on module dependencies having been resolved and ability to report
+// missing dependency errors.
+type ModuleMissingDepsPathContext interface {
+ ModuleWithDepsPathContext
+ AddMissingDependencies(missingDeps []string)
+}
+
type ModuleInstallPathContext interface {
BaseModuleContext
@@ -143,18 +190,18 @@
}
type genPathProvider interface {
- genPathWithExt(ctx ModuleContext, subdir, ext string) ModuleGenPath
+ genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath
}
type objPathProvider interface {
- objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath
+ objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath
}
type resPathProvider interface {
- resPathWithName(ctx ModuleContext, name string) ModuleResPath
+ resPathWithName(ctx ModuleOutPathContext, name string) ModuleResPath
}
// GenPathWithExt derives a new file path in ctx's generated sources directory
// from the current path, but with the new extension.
-func GenPathWithExt(ctx ModuleContext, subdir string, p Path, ext string) ModuleGenPath {
+func GenPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleGenPath {
if path, ok := p.(genPathProvider); ok {
return path.genPathWithExt(ctx, subdir, ext)
}
@@ -164,7 +211,7 @@
// ObjPathWithExt derives a new file path in ctx's object directory from the
// current path, but with the new extension.
-func ObjPathWithExt(ctx ModuleContext, subdir string, p Path, ext string) ModuleObjPath {
+func ObjPathWithExt(ctx ModuleOutPathContext, subdir string, p Path, ext string) ModuleObjPath {
if path, ok := p.(objPathProvider); ok {
return path.objPathWithExt(ctx, subdir, ext)
}
@@ -175,7 +222,7 @@
// ResPathWithName derives a new path in ctx's output resource directory, using
// the current path to create the directory name, and the `name` argument for
// the filename.
-func ResPathWithName(ctx ModuleContext, p Path, name string) ModuleResPath {
+func ResPathWithName(ctx ModuleOutPathContext, p Path, name string) ModuleResPath {
if path, ok := p.(resPathProvider); ok {
return path.resPathWithName(ctx, name)
}
@@ -261,7 +308,7 @@
// `android:"path"` so that dependencies on SourceFileProducer modules will have already been handled by the
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
// OutputFileProducer dependencies will cause the module to be marked as having missing dependencies.
-func PathsForModuleSrc(ctx ModuleContext, paths []string) Paths {
+func PathsForModuleSrc(ctx ModuleMissingDepsPathContext, paths []string) Paths {
return PathsForModuleSrcExcludes(ctx, paths, nil)
}
@@ -272,7 +319,7 @@
// will have already been handled by the path_properties mutator. If ctx.Config().AllowMissingDependencies() is
// true then any missing SourceFileProducer or OutputFileProducer dependencies will cause the module to be marked as
// having missing dependencies.
-func PathsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) Paths {
+func PathsForModuleSrcExcludes(ctx ModuleMissingDepsPathContext, paths, excludes []string) Paths {
ret, missingDeps := PathsAndMissingDepsForModuleSrcExcludes(ctx, paths, excludes)
if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies(missingDeps)
@@ -311,6 +358,29 @@
return ret
}
+// Expands Paths to a SourceFileProducer or OutputFileProducer module dependency referenced via ":name" or ":name{.tag}" syntax.
+// If the dependency is not found, a missingErrorDependency is returned.
+// If the module dependency is not a SourceFileProducer or OutputFileProducer, appropriate errors will be returned.
+func getPathsFromModuleDep(ctx ModuleWithDepsPathContext, path, moduleName, tag string) (Paths, error) {
+ module := ctx.GetDirectDepWithTag(moduleName, sourceOrOutputDepTag(tag))
+ if module == nil {
+ return nil, missingDependencyError{[]string{moduleName}}
+ }
+ if outProducer, ok := module.(OutputFileProducer); ok {
+ outputFiles, err := outProducer.OutputFiles(tag)
+ if err != nil {
+ return nil, fmt.Errorf("path dependency %q: %s", path, err)
+ }
+ return outputFiles, nil
+ } else if tag != "" {
+ return nil, fmt.Errorf("path dependency %q is not an output file producing module", path)
+ } else if srcProducer, ok := module.(SourceFileProducer); ok {
+ return srcProducer.Srcs(), nil
+ } else {
+ return nil, fmt.Errorf("path dependency %q is not a source file producing module", path)
+ }
+}
+
// PathsAndMissingDepsForModuleSrcExcludes returns Paths rooted from the module's local source directory, excluding
// paths listed in the excludes arguments, and a list of missing dependencies. It expands globs, references to
// SourceFileProducer modules using the ":name" syntax, and references to OutputFileProducer modules using the
@@ -319,7 +389,7 @@
// path_properties mutator. If ctx.Config().AllowMissingDependencies() is true then any missing SourceFileProducer or
// OutputFileProducer dependencies will be returned, and they will NOT cause the module to be marked as having missing
// dependencies.
-func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleContext, paths, excludes []string) (Paths, []string) {
+func PathsAndMissingDepsForModuleSrcExcludes(ctx ModuleWithDepsPathContext, paths, excludes []string) (Paths, []string) {
prefix := pathForModuleSrc(ctx).String()
var expandedExcludes []string
@@ -331,23 +401,13 @@
for _, e := range excludes {
if m, t := SrcIsModuleWithTag(e); m != "" {
- module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
- if module == nil {
- missingExcludeDeps = append(missingExcludeDeps, m)
- continue
- }
- if outProducer, ok := module.(OutputFileProducer); ok {
- outputFiles, err := outProducer.OutputFiles(t)
- if err != nil {
- ctx.ModuleErrorf("path dependency %q: %s", e, err)
- }
- expandedExcludes = append(expandedExcludes, outputFiles.Strings()...)
- } else if t != "" {
- ctx.ModuleErrorf("path dependency %q is not an output file producing module", e)
- } else if srcProducer, ok := module.(SourceFileProducer); ok {
- expandedExcludes = append(expandedExcludes, srcProducer.Srcs().Strings()...)
+ modulePaths, err := getPathsFromModuleDep(ctx, e, m, t)
+ if m, ok := err.(missingDependencyError); ok {
+ missingExcludeDeps = append(missingExcludeDeps, m.missingDeps...)
+ } else if err != nil {
+ reportPathError(ctx, err)
} else {
- ctx.ModuleErrorf("path dependency %q is not a source file producing module", e)
+ expandedExcludes = append(expandedExcludes, modulePaths.Strings()...)
}
} else {
expandedExcludes = append(expandedExcludes, filepath.Join(prefix, e))
@@ -382,7 +442,10 @@
return "missing dependencies: " + strings.Join(e.missingDeps, ", ")
}
-func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) {
+// Expands one path string to Paths rooted from the module's local source
+// directory, excluding those listed in the expandedExcludes.
+// Expands globs, references to SourceFileProducer or OutputFileProducer modules using the ":name" and ":name{.tag}" syntax.
+func expandOneSrcPath(ctx ModuleWithDepsPathContext, sPath string, expandedExcludes []string) (Paths, error) {
excludePaths := func(paths Paths) Paths {
if len(expandedExcludes) == 0 {
return paths
@@ -395,29 +458,18 @@
}
return remainder
}
- if m, t := SrcIsModuleWithTag(s); m != "" {
- module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
- if module == nil {
- return nil, missingDependencyError{[]string{m}}
- }
- if outProducer, ok := module.(OutputFileProducer); ok {
- outputFiles, err := outProducer.OutputFiles(t)
- if err != nil {
- return nil, fmt.Errorf("path dependency %q: %s", s, err)
- }
- return excludePaths(outputFiles), nil
- } else if t != "" {
- return nil, fmt.Errorf("path dependency %q is not an output file producing module", s)
- } else if srcProducer, ok := module.(SourceFileProducer); ok {
- return excludePaths(srcProducer.Srcs()), nil
+ if m, t := SrcIsModuleWithTag(sPath); m != "" {
+ modulePaths, err := getPathsFromModuleDep(ctx, sPath, m, t)
+ if err != nil {
+ return nil, err
} else {
- return nil, fmt.Errorf("path dependency %q is not a source file producing module", s)
+ return excludePaths(modulePaths), nil
}
- } else if pathtools.IsGlob(s) {
- paths := ctx.GlobFiles(pathForModuleSrc(ctx, s).String(), expandedExcludes)
+ } else if pathtools.IsGlob(sPath) {
+ paths := GlobFiles(ctx, pathForModuleSrc(ctx, sPath).String(), expandedExcludes)
return PathsWithModuleSrcSubDir(ctx, paths, ""), nil
} else {
- p := pathForModuleSrc(ctx, s)
+ p := pathForModuleSrc(ctx, sPath)
if exists, _, err := ctx.Config().fs.Exists(p.String()); err != nil {
ReportPathErrorf(ctx, "%s: %s", p, err.Error())
} else if !exists && !ctx.Config().testAllowNonExistentPaths {
@@ -436,7 +488,7 @@
// each string. If incDirs is false, strip paths with a trailing '/' from the list.
// It intended for use in globs that only list files that exist, so it allows '$' in
// filenames.
-func pathsForModuleSrcFromFullPath(ctx EarlyModuleContext, paths []string, incDirs bool) Paths {
+func pathsForModuleSrcFromFullPath(ctx EarlyModulePathContext, paths []string, incDirs bool) Paths {
prefix := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir()) + "/"
if prefix == "./" {
prefix = ""
@@ -465,16 +517,16 @@
return ret
}
-// PathsWithOptionalDefaultForModuleSrc returns Paths rooted from the module's
-// local source directory. If input is nil, use the default if it exists. If input is empty, returns nil.
-func PathsWithOptionalDefaultForModuleSrc(ctx ModuleContext, input []string, def string) Paths {
+// PathsWithOptionalDefaultForModuleSrc returns Paths rooted from the module's local source
+// directory. If input is nil, use the default if it exists. If input is empty, returns nil.
+func PathsWithOptionalDefaultForModuleSrc(ctx ModuleMissingDepsPathContext, input []string, def string) Paths {
if input != nil {
return PathsForModuleSrc(ctx, input)
}
// Use Glob so that if the default doesn't exist, a dependency is added so that when it
// is created, we're run again.
path := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir(), def)
- return ctx.Glob(path, nil)
+ return Glob(ctx, path, nil)
}
// Strings returns the Paths in string form
@@ -846,7 +898,7 @@
ReportPathErrorf(ctx, "path may not contain a glob: %s", path.String())
}
- if modCtx, ok := ctx.(ModuleContext); ok && ctx.Config().AllowMissingDependencies() {
+ if modCtx, ok := ctx.(ModuleMissingDepsPathContext); ok && ctx.Config().AllowMissingDependencies() {
exists, err := existsWithDependencies(ctx, path)
if err != nil {
reportPathError(ctx, err)
@@ -913,7 +965,7 @@
// OverlayPath returns the overlay for `path' if it exists. This assumes that the
// SourcePath is the path to a resource overlay directory.
-func (p SourcePath) OverlayPath(ctx ModuleContext, path Path) OptionalPath {
+func (p SourcePath) OverlayPath(ctx ModuleMissingDepsPathContext, path Path) OptionalPath {
var relDir string
if srcPath, ok := path.(SourcePath); ok {
relDir = srcPath.path
@@ -1054,7 +1106,7 @@
// PathForModuleSrc returns a Path representing the paths... under the
// module's local source directory.
-func PathForModuleSrc(ctx ModuleContext, pathComponents ...string) Path {
+func PathForModuleSrc(ctx ModuleMissingDepsPathContext, pathComponents ...string) Path {
p, err := validatePath(pathComponents...)
if err != nil {
reportPathError(ctx, err)
@@ -1080,7 +1132,7 @@
return paths[0]
}
-func pathForModuleSrc(ctx ModuleContext, paths ...string) SourcePath {
+func pathForModuleSrc(ctx EarlyModulePathContext, paths ...string) SourcePath {
p, err := validatePath(paths...)
if err != nil {
reportPathError(ctx, err)
@@ -1099,7 +1151,7 @@
// PathsWithModuleSrcSubDir takes a list of Paths and returns a new list of Paths where Rel() on each path
// will return the path relative to subDir in the module's source directory. If any input paths are not located
// inside subDir then a path error will be reported.
-func PathsWithModuleSrcSubDir(ctx ModuleContext, paths Paths, subDir string) Paths {
+func PathsWithModuleSrcSubDir(ctx EarlyModulePathContext, paths Paths, subDir string) Paths {
paths = append(Paths(nil), paths...)
subDirFullPath := pathForModuleSrc(ctx, subDir)
for i, path := range paths {
@@ -1111,7 +1163,7 @@
// PathWithModuleSrcSubDir takes a Path and returns a Path where Rel() will return the path relative to subDir in the
// module's source directory. If the input path is not located inside subDir then a path error will be reported.
-func PathWithModuleSrcSubDir(ctx ModuleContext, path Path, subDir string) Path {
+func PathWithModuleSrcSubDir(ctx EarlyModulePathContext, path Path, subDir string) Path {
subDirFullPath := pathForModuleSrc(ctx, subDir)
rel := Rel(ctx, subDirFullPath.String(), path.String())
return subDirFullPath.Join(ctx, rel)
@@ -1119,22 +1171,22 @@
// OptionalPathForModuleSrc returns an OptionalPath. The OptionalPath contains a
// valid path if p is non-nil.
-func OptionalPathForModuleSrc(ctx ModuleContext, p *string) OptionalPath {
+func OptionalPathForModuleSrc(ctx ModuleMissingDepsPathContext, p *string) OptionalPath {
if p == nil {
return OptionalPath{}
}
return OptionalPathForPath(PathForModuleSrc(ctx, *p))
}
-func (p SourcePath) genPathWithExt(ctx ModuleContext, subdir, ext string) ModuleGenPath {
+func (p SourcePath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
-func (p SourcePath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p SourcePath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
-func (p SourcePath) resPathWithName(ctx ModuleContext, name string) ModuleResPath {
+func (p SourcePath) resPathWithName(ctx ModuleOutPathContext, name string) ModuleResPath {
// TODO: Use full directory if the new ctx is not the current ctx?
return PathForModuleRes(ctx, p.path, name)
}
@@ -1146,11 +1198,20 @@
var _ Path = ModuleOutPath{}
-func (p ModuleOutPath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p ModuleOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
-func pathForModule(ctx ModuleContext) OutputPath {
+// ModuleOutPathContext Subset of ModuleContext functions necessary for output path methods.
+type ModuleOutPathContext interface {
+ PathContext
+
+ ModuleName() string
+ ModuleDir() string
+ ModuleSubDir() string
+}
+
+func pathForModuleOut(ctx ModuleOutPathContext) OutputPath {
return PathForOutput(ctx, ".intermediates", ctx.ModuleDir(), ctx.ModuleName(), ctx.ModuleSubDir())
}
@@ -1161,13 +1222,13 @@
var _ Path = BazelOutPath{}
var _ objPathProvider = BazelOutPath{}
-func (p BazelOutPath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p BazelOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
// PathForVndkRefAbiDump returns an OptionalPath representing the path of the
// reference abi dump for the given module. This is not guaranteed to be valid.
-func PathForVndkRefAbiDump(ctx ModuleContext, version, fileName string,
+func PathForVndkRefAbiDump(ctx ModuleInstallPathContext, version, fileName string,
isNdk, isLlndkOrVndk, isGzip bool) OptionalPath {
arches := ctx.DeviceConfig().Arches()
@@ -1223,13 +1284,13 @@
// PathForModuleOut returns a Path representing the paths... under the module's
// output directory.
-func PathForModuleOut(ctx ModuleContext, paths ...string) ModuleOutPath {
+func PathForModuleOut(ctx ModuleOutPathContext, paths ...string) ModuleOutPath {
p, err := validatePath(paths...)
if err != nil {
reportPathError(ctx, err)
}
return ModuleOutPath{
- OutputPath: pathForModule(ctx).withRel(p),
+ OutputPath: pathForModuleOut(ctx).withRel(p),
}
}
@@ -1245,24 +1306,24 @@
// PathForModuleGen returns a Path representing the paths... under the module's
// `gen' directory.
-func PathForModuleGen(ctx ModuleContext, paths ...string) ModuleGenPath {
+func PathForModuleGen(ctx ModuleOutPathContext, paths ...string) ModuleGenPath {
p, err := validatePath(paths...)
if err != nil {
reportPathError(ctx, err)
}
return ModuleGenPath{
ModuleOutPath: ModuleOutPath{
- OutputPath: pathForModule(ctx).withRel("gen").withRel(p),
+ OutputPath: pathForModuleOut(ctx).withRel("gen").withRel(p),
},
}
}
-func (p ModuleGenPath) genPathWithExt(ctx ModuleContext, subdir, ext string) ModuleGenPath {
+func (p ModuleGenPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
// TODO: make a different path for local vs remote generated files?
return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
-func (p ModuleGenPath) objPathWithExt(ctx ModuleContext, subdir, ext string) ModuleObjPath {
+func (p ModuleGenPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
}
@@ -1276,7 +1337,7 @@
// PathForModuleObj returns a Path representing the paths... under the module's
// 'obj' directory.
-func PathForModuleObj(ctx ModuleContext, pathComponents ...string) ModuleObjPath {
+func PathForModuleObj(ctx ModuleOutPathContext, pathComponents ...string) ModuleObjPath {
p, err := validatePath(pathComponents...)
if err != nil {
reportPathError(ctx, err)
@@ -1294,7 +1355,7 @@
// PathForModuleRes returns a Path representing the paths... under the module's
// 'res' directory.
-func PathForModuleRes(ctx ModuleContext, pathComponents ...string) ModuleResPath {
+func PathForModuleRes(ctx ModuleOutPathContext, pathComponents ...string) ModuleResPath {
p, err := validatePath(pathComponents...)
if err != nil {
reportPathError(ctx, err)
diff --git a/android/testing.go b/android/testing.go
index 76172d1..5640c29 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -89,7 +89,7 @@
f := func(ctx RegisterMutatorsContext) {
ctx.TopDown(mutatorName, m)
}
- bp2buildMutators = append(bp2buildMutators, f)
+ ctx.bp2buildMutators = append(ctx.bp2buildMutators, f)
}
func (ctx *TestContext) Register() {
@@ -100,7 +100,7 @@
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
- RegisterMutatorsForBazelConversion(ctx.Context.Context, bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildMutators)
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 5da11ce..6dd49e5 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -26,6 +26,7 @@
android.hardware.graphics.bufferqueue@2.0(minSdkVersion:29)
android.hardware.graphics.common-ndk_platform(minSdkVersion:29)
android.hardware.graphics.common-unstable-ndk_platform(minSdkVersion:29)
+android.hardware.graphics.common-V2-ndk_platform(minSdkVersion:29)
android.hardware.graphics.common@1.0(minSdkVersion:29)
android.hardware.graphics.common@1.1(minSdkVersion:29)
android.hardware.graphics.common@1.2(minSdkVersion:29)
@@ -165,6 +166,7 @@
derive_sdk_prefer32(minSdkVersion:30)
derive_sdk_prefer32(minSdkVersion:current)
dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29)
+dnsresolver_aidl_interface-V8-ndk_platform(minSdkVersion:29)
DocumentsUI-res-lib(minSdkVersion:29)
exoplayer2-extractor(minSdkVersion:16)
exoplayer2-extractor-annotation-stubs(minSdkVersion:16)
@@ -478,11 +480,14 @@
netd-client(minSdkVersion:29)
netd_aidl_interface-java(minSdkVersion:29)
netd_aidl_interface-unstable-java(minSdkVersion:29)
+netd_aidl_interface-V6-java(minSdkVersion:29)
netd_event_listener_interface-java(minSdkVersion:29)
netd_event_listener_interface-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-unstable-ndk_platform(minSdkVersion:29)
+netd_event_listener_interface-V2-ndk_platform(minSdkVersion:29)
netlink-client(minSdkVersion:29)
networkstack-aidl-interfaces-unstable-java(minSdkVersion:29)
+networkstack-aidl-interfaces-V10-java(minSdkVersion:29)
networkstack-client(minSdkVersion:29)
NetworkStackApiStableDependencies(minSdkVersion:29)
NetworkStackApiStableLib(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index 384d6c7..ade8fa9 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -854,11 +854,17 @@
Contents: apexContents,
})
+ minSdkVersion := a.minSdkVersion(mctx)
+ // When min_sdk_version is not set, the apex is built against FutureApiLevel.
+ if minSdkVersion.IsNone() {
+ minSdkVersion = android.FutureApiLevel
+ }
+
// This is the main part of this mutator. Mark the collected dependencies that they need to
// be built for this apexBundle.
apexInfo := android.ApexInfo{
ApexVariationName: mctx.ModuleName(),
- MinSdkVersionStr: a.minSdkVersion(mctx).String(),
+ MinSdkVersionStr: minSdkVersion.String(),
RequiredSdks: a.RequiredSdks(),
Updatable: a.Updatable(),
InApexes: []string{mctx.ModuleName()},
@@ -2116,17 +2122,13 @@
func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel {
ver := proptools.String(a.properties.Min_sdk_version)
if ver == "" {
- return android.FutureApiLevel
+ return android.NoneApiLevel
}
apiLevel, err := android.ApiLevelFromUser(ctx, ver)
if err != nil {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
return android.NoneApiLevel
}
- if apiLevel.IsPreview() {
- // All codenames should build against "current".
- return android.FutureApiLevel
- }
return apiLevel
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 56487ce..cded770 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -2135,6 +2135,74 @@
expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30")
}
+func TestApexMinSdkVersion_WorksWithSdkCodename(t *testing.T) {
+ withSAsActiveCodeNames := func(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
+ config.TestProductVariables.Platform_version_active_codenames = []string{"S"}
+ }
+ testApexError(t, `libbar.*: should support min_sdk_version\(S\)`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ min_sdk_version: "S",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ cc_library {
+ name: "libfoo",
+ shared_libs: ["libbar"],
+ apex_available: ["myapex"],
+ min_sdk_version: "29",
+ }
+ cc_library {
+ name: "libbar",
+ apex_available: ["myapex"],
+ }
+ `, withSAsActiveCodeNames)
+}
+
+func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
+ withSAsActiveCodeNames := func(fs map[string][]byte, config android.Config) {
+ config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
+ config.TestProductVariables.Platform_version_active_codenames = []string{"S", "T"}
+ }
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ min_sdk_version: "S",
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ cc_library {
+ name: "libfoo",
+ shared_libs: ["libbar"],
+ apex_available: ["myapex"],
+ min_sdk_version: "S",
+ }
+ cc_library {
+ name: "libbar",
+ stubs: {
+ symbol_file: "libbar.map.txt",
+ versions: ["30", "S", "T"],
+ },
+ }
+ `, withSAsActiveCodeNames)
+
+ // ensure libfoo is linked with "S" version of libbar stub
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000")
+ libFlags := libfoo.Rule("ld").Args["libFlags"]
+ ensureContains(t, libFlags, "android_arm64_armv8-a_shared_S/libbar.so")
+}
+
func TestFilesInSubDir(t *testing.T) {
ctx, _ := testApex(t, `
apex {
@@ -4213,9 +4281,11 @@
}
}
+// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
+// propagation of paths to dex implementation jars from the former to the latter.
func TestPrebuiltExportDexImplementationJars(t *testing.T) {
transform := func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"})
+ // Empty transformation.
}
checkDexJarBuildPath := func(ctx *android.TestContext, name string) {
@@ -4298,7 +4368,6 @@
bp := `
prebuilt_apex {
name: "myapex",
- prefer: true,
arch: {
arm64: {
src: "myapex-arm64.apex",
@@ -4312,6 +4381,7 @@
java_import {
name: "libfoo",
+ prefer: true,
jars: ["libfoo.jar"],
}
@@ -5863,7 +5933,7 @@
srcs: ["a.java"],
sdk_version: "current",
apex_available: [
- "com.android.art.something",
+ "com.android.art.debug",
],
hostdex: true,
}
@@ -5891,15 +5961,15 @@
}
apex {
- name: "com.android.art.something",
- key: "com.android.art.something.key",
+ name: "com.android.art.debug",
+ key: "com.android.art.debug.key",
java_libs: ["some-art-lib"],
updatable: true,
min_sdk_version: "current",
}
apex_key {
- name: "com.android.art.something.key",
+ name: "com.android.art.debug.key",
}
filegroup {
@@ -5932,9 +6002,9 @@
"build/make/target/product/security": nil,
"apex_manifest.json": nil,
"AndroidManifest.xml": nil,
- "system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
- "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
- "system/sepolicy/apex/com.android.art.something-file_contexts": nil,
+ "system/sepolicy/apex/some-updatable-apex-file_contexts": nil,
+ "system/sepolicy/apex/some-non-updatable-apex-file_contexts": nil,
+ "system/sepolicy/apex/com.android.art.debug-file_contexts": nil,
"framework/aidl/a.aidl": nil,
}
cc.GatherRequiredFilesForTest(fs)
@@ -5998,15 +6068,15 @@
t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
transform = func(config *dexpreopt.GlobalConfig) {
- config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"com.android.art.something:some-art-lib"})
+ config.ArtApexJars = android.CreateTestConfiguredJarList([]string{"com.android.art.debug:some-art-lib"})
}
testNoUpdatableJarsInBootImage(t, "", transform)
})
t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
- err = `module "some-art-lib" from updatable apexes \["com.android.art.something"\] is not allowed in the framework boot image`
+ err = `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the framework boot image`
transform = func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateTestConfiguredJarList([]string{"com.android.art.something:some-art-lib"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"com.android.art.debug:some-art-lib"})
}
testNoUpdatableJarsInBootImage(t, err, transform)
})
diff --git a/apex/builder.go b/apex/builder.go
index 67314d8..ee0a410 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -598,7 +598,7 @@
// bundletool doesn't understand what "current" is. We need to transform it to
// codename
- if moduleMinSdkVersion.IsCurrent() {
+ if moduleMinSdkVersion.IsCurrent() || moduleMinSdkVersion.IsNone() {
minSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
}
// apex module doesn't have a concept of target_sdk_version, hence for the time
diff --git a/bazel/properties.go b/bazel/properties.go
index ac0047b..79956e1 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -31,4 +31,7 @@
type BazelTargetModuleProperties struct {
// The Bazel rule class for this target.
Rule_class string
+
+ // The target label for the bzl file containing the definition of the rule class.
+ Bzl_load_location string
}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 8284ae3..1af1d60 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -18,6 +18,7 @@
"android/soong/android"
"fmt"
"reflect"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -29,8 +30,62 @@
}
type BazelTarget struct {
- name string
- content string
+ name string
+ content string
+ ruleClass string
+ bzlLoadLocation string
+}
+
+// IsLoadedFromStarlark determines if the BazelTarget's rule class is loaded from a .bzl file,
+// as opposed to a native rule built into Bazel.
+func (t BazelTarget) IsLoadedFromStarlark() bool {
+ return t.bzlLoadLocation != ""
+}
+
+// BazelTargets is a typedef for a slice of BazelTarget objects.
+type BazelTargets []BazelTarget
+
+// String returns the string representation of BazelTargets, without load
+// statements (use LoadStatements for that), since the targets are usually not
+// adjacent to the load statements at the top of the BUILD file.
+func (targets BazelTargets) String() string {
+ var res string
+ for i, target := range targets {
+ res += target.content
+ if i != len(targets)-1 {
+ res += "\n\n"
+ }
+ }
+ return res
+}
+
+// LoadStatements return the string representation of the sorted and deduplicated
+// Starlark rule load statements needed by a group of BazelTargets.
+func (targets BazelTargets) LoadStatements() string {
+ bzlToLoadedSymbols := map[string][]string{}
+ for _, target := range targets {
+ if target.IsLoadedFromStarlark() {
+ bzlToLoadedSymbols[target.bzlLoadLocation] =
+ append(bzlToLoadedSymbols[target.bzlLoadLocation], target.ruleClass)
+ }
+ }
+
+ var loadStatements []string
+ for bzl, ruleClasses := range bzlToLoadedSymbols {
+ loadStatement := "load(\""
+ loadStatement += bzl
+ loadStatement += "\", "
+ ruleClasses = android.SortedUniqueStrings(ruleClasses)
+ for i, ruleClass := range ruleClasses {
+ loadStatement += "\"" + ruleClass + "\""
+ if i != len(ruleClasses)-1 {
+ loadStatement += ", "
+ }
+ }
+ loadStatement += ")"
+ loadStatements = append(loadStatements, loadStatement)
+ }
+ return strings.Join(android.SortedUniqueStrings(loadStatements), "\n")
}
type bpToBuildContext interface {
@@ -67,6 +122,17 @@
QueryView
)
+func (mode CodegenMode) String() string {
+ switch mode {
+ case Bp2Build:
+ return "Bp2Build"
+ case QueryView:
+ return "QueryView"
+ default:
+ return fmt.Sprintf("%d", mode)
+ }
+}
+
func (ctx CodegenContext) AddNinjaFileDeps(...string) {}
func (ctx CodegenContext) Config() android.Config { return ctx.config }
func (ctx CodegenContext) Context() android.Context { return ctx.context }
@@ -93,8 +159,8 @@
return attributes
}
-func GenerateSoongModuleTargets(ctx bpToBuildContext, codegenMode CodegenMode) map[string][]BazelTarget {
- buildFileToTargets := make(map[string][]BazelTarget)
+func GenerateSoongModuleTargets(ctx bpToBuildContext, codegenMode CodegenMode) map[string]BazelTargets {
+ buildFileToTargets := make(map[string]BazelTargets)
ctx.VisitAllModules(func(m blueprint.Module) {
dir := ctx.ModuleDir(m)
var t BazelTarget
@@ -116,22 +182,44 @@
return buildFileToTargets
}
+// Helper method to trim quotes around strings.
+func trimQuotes(s string) string {
+ if s == "" {
+ // strconv.Unquote would error out on empty strings, but this method
+ // allows them, so return the empty string directly.
+ return ""
+ }
+ ret, err := strconv.Unquote(s)
+ if err != nil {
+ // Panic the error immediately.
+ panic(fmt.Errorf("Trying to unquote '%s', but got error: %s", s, err))
+ }
+ return ret
+}
+
func generateBazelTarget(ctx bpToBuildContext, m blueprint.Module) BazelTarget {
// extract the bazel attributes from the module.
props := getBuildProperties(ctx, m)
// extract the rule class name from the attributes. Since the string value
// will be string-quoted, remove the quotes here.
- ruleClass := strings.Replace(props.Attrs["rule_class"], "\"", "", 2)
+ ruleClass := trimQuotes(props.Attrs["rule_class"])
// Delete it from being generated in the BUILD file.
delete(props.Attrs, "rule_class")
+ // extract the bzl_load_location, and also remove the quotes around it here.
+ bzlLoadLocation := trimQuotes(props.Attrs["bzl_load_location"])
+ // Delete it from being generated in the BUILD file.
+ delete(props.Attrs, "bzl_load_location")
+
// Return the Bazel target with rule class and attributes, ready to be
// code-generated.
attributes := propsToAttributes(props.Attrs)
targetName := targetNameForBp2Build(ctx, m)
return BazelTarget{
- name: targetName,
+ name: targetName,
+ ruleClass: ruleClass,
+ bzlLoadLocation: bzlLoadLocation,
content: fmt.Sprintf(
bazelTarget,
ruleClass,
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index be32530..66ed42d 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -268,16 +268,185 @@
}
}
-func TestModuleTypeBp2Build(t *testing.T) {
+func TestLoadStatements(t *testing.T) {
testCases := []struct {
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- bp string
- expectedBazelTarget string
+ bazelTargets BazelTargets
+ expectedLoadStatements string
}{
{
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
+ bazelTargets: BazelTargets{
+ BazelTarget{
+ name: "foo",
+ ruleClass: "cc_library",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ },
+ expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
+ },
+ {
+ bazelTargets: BazelTargets{
+ BazelTarget{
+ name: "foo",
+ ruleClass: "cc_library",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ BazelTarget{
+ name: "bar",
+ ruleClass: "cc_library",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ },
+ expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
+ },
+ {
+ bazelTargets: BazelTargets{
+ BazelTarget{
+ name: "foo",
+ ruleClass: "cc_library",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ BazelTarget{
+ name: "bar",
+ ruleClass: "cc_binary",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ },
+ expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`,
+ },
+ {
+ bazelTargets: BazelTargets{
+ BazelTarget{
+ name: "foo",
+ ruleClass: "cc_library",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ BazelTarget{
+ name: "bar",
+ ruleClass: "cc_binary",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ BazelTarget{
+ name: "baz",
+ ruleClass: "java_binary",
+ bzlLoadLocation: "//build/bazel/rules:java.bzl",
+ },
+ },
+ expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")
+load("//build/bazel/rules:java.bzl", "java_binary")`,
+ },
+ {
+ bazelTargets: BazelTargets{
+ BazelTarget{
+ name: "foo",
+ ruleClass: "cc_binary",
+ bzlLoadLocation: "//build/bazel/rules:cc.bzl",
+ },
+ BazelTarget{
+ name: "bar",
+ ruleClass: "java_binary",
+ bzlLoadLocation: "//build/bazel/rules:java.bzl",
+ },
+ BazelTarget{
+ name: "baz",
+ ruleClass: "genrule",
+ // Note: no bzlLoadLocation for native rules
+ },
+ },
+ expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary")
+load("//build/bazel/rules:java.bzl", "java_binary")`,
+ },
+ }
+
+ for _, testCase := range testCases {
+ actual := testCase.bazelTargets.LoadStatements()
+ expected := testCase.expectedLoadStatements
+ if actual != expected {
+ t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
+ }
+ }
+
+}
+
+func TestGenerateBazelTargetModules_OneToMany_LoadedFromStarlark(t *testing.T) {
+ testCases := []struct {
+ bp string
+ expectedBazelTarget string
+ expectedBazelTargetCount int
+ expectedLoadStatements string
+ }{
+ {
+ bp: `custom {
+ name: "bar",
+}`,
+ expectedBazelTarget: `my_library(
+ name = "bar",
+)
+
+my_proto_library(
+ name = "bar_my_proto_library_deps",
+)
+
+proto_library(
+ name = "bar_proto_library_deps",
+)`,
+ expectedBazelTargetCount: 3,
+ expectedLoadStatements: `load("//build/bazel/rules:proto.bzl", "my_proto_library", "proto_library")
+load("//build/bazel/rules:rules.bzl", "my_library")`,
+ },
+ }
+
+ dir := "."
+ for _, testCase := range testCases {
+ config := android.TestConfig(buildDir, nil, testCase.bp, nil)
+ ctx := android.NewTestContext(config)
+ ctx.RegisterModuleType("custom", customModuleFactory)
+ ctx.RegisterBp2BuildMutator("custom_starlark", customBp2BuildMutatorFromStarlark)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
+ android.FailIfErrored(t, errs)
+ _, errs = ctx.ResolveDependencies(config)
+ android.FailIfErrored(t, errs)
+
+ bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
+ if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
+ t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
+ }
+
+ actualBazelTargets := bazelTargets.String()
+ if actualBazelTargets != testCase.expectedBazelTarget {
+ t.Errorf(
+ "Expected generated Bazel target to be '%s', got '%s'",
+ testCase.expectedBazelTarget,
+ actualBazelTargets,
+ )
+ }
+
+ actualLoadStatements := bazelTargets.LoadStatements()
+ if actualLoadStatements != testCase.expectedLoadStatements {
+ t.Errorf(
+ "Expected generated load statements to be '%s', got '%s'",
+ testCase.expectedLoadStatements,
+ actualLoadStatements,
+ )
+ }
+ }
+}
+
+func TestModuleTypeBp2Build(t *testing.T) {
+ testCases := []struct {
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ bp string
+ expectedBazelTarget string
+ description string
+ }{
+ {
+ description: "filegroup with no srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
bp: `filegroup {
name: "foo",
srcs: [],
@@ -289,8 +458,10 @@
)`,
},
{
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
+ description: "filegroup with srcs",
+ moduleTypeUnderTest: "filegroup",
+ moduleTypeUnderTestFactory: android.FileGroupFactory,
+ moduleTypeUnderTestBp2BuildMutator: android.FilegroupBp2Build,
bp: `filegroup {
name: "foo",
srcs: ["a", "b"],
@@ -304,18 +475,20 @@
)`,
},
{
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ description: "genrule with command line variable replacements",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
bp: `genrule {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
- tool_files: [":foo.tool"],
- cmd: "$(location :foo.tool) arg $(in) $(out)",
+ tools: [":foo.tool"],
+ cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
}`,
expectedBazelTarget: `genrule(
name = "foo",
- cmd = "$(location :foo.tool) arg $(SRCS) $(OUTS)",
+ cmd = "$(location :foo.tool) --genDir=$(GENDIR) arg $(SRCS) $(OUTS)",
outs = [
"foo.out",
],
@@ -328,18 +501,46 @@
)`,
},
{
- moduleTypeUnderTest: "genrule",
- moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ description: "genrule using $(locations :label)",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
bp: `genrule {
name: "foo",
out: ["foo.out"],
srcs: ["foo.in"],
- tools: [":foo.tool"],
- cmd: "$(location :foo.tool) --out-dir=$(genDir) $(in)",
+ tools: [":foo.tools"],
+ cmd: "$(locations :foo.tools) -s $(out) $(in)",
}`,
expectedBazelTarget: `genrule(
name = "foo",
- cmd = "$(location :foo.tool) --out-dir=$(GENDIR) $(SRCS)",
+ cmd = "$(locations :foo.tools) -s $(OUTS) $(SRCS)",
+ outs = [
+ "foo.out",
+ ],
+ srcs = [
+ "foo.in",
+ ],
+ tools = [
+ ":foo.tools",
+ ],
+)`,
+ },
+ {
+ description: "genrule using $(location) label should substitute first tool label automatically",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ bp: `genrule {
+ name: "foo",
+ out: ["foo.out"],
+ srcs: ["foo.in"],
+ tool_files: [":foo.tool", ":other.tool"],
+ cmd: "$(location) -s $(out) $(in)",
+}`,
+ expectedBazelTarget: `genrule(
+ name = "foo",
+ cmd = "$(location :foo.tool) -s $(OUTS) $(SRCS)",
outs = [
"foo.out",
],
@@ -348,6 +549,56 @@
],
tools = [
":foo.tool",
+ ":other.tool",
+ ],
+)`,
+ },
+ {
+ description: "genrule using $(locations) label should substitute first tool label automatically",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ bp: `genrule {
+ name: "foo",
+ out: ["foo.out"],
+ srcs: ["foo.in"],
+ tools: [":foo.tool", ":other.tool"],
+ cmd: "$(locations) -s $(out) $(in)",
+}`,
+ expectedBazelTarget: `genrule(
+ name = "foo",
+ cmd = "$(locations :foo.tool) -s $(OUTS) $(SRCS)",
+ outs = [
+ "foo.out",
+ ],
+ srcs = [
+ "foo.in",
+ ],
+ tools = [
+ ":foo.tool",
+ ":other.tool",
+ ],
+)`,
+ },
+ {
+ description: "genrule without tools or tool_files can convert successfully",
+ moduleTypeUnderTest: "genrule",
+ moduleTypeUnderTestFactory: genrule.GenRuleFactory,
+ moduleTypeUnderTestBp2BuildMutator: genrule.GenruleBp2Build,
+ bp: `genrule {
+ name: "foo",
+ out: ["foo.out"],
+ srcs: ["foo.in"],
+ cmd: "cp $(in) $(out)",
+}`,
+ expectedBazelTarget: `genrule(
+ name = "foo",
+ cmd = "cp $(SRCS) $(OUTS)",
+ outs = [
+ "foo.out",
+ ],
+ srcs = [
+ "foo.in",
],
)`,
},
@@ -358,6 +609,7 @@
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+ ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
ctx.RegisterForBazelConversion()
_, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
@@ -367,13 +619,14 @@
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context, Bp2Build)[dir]
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
- t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
+ t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
}
actualBazelTarget := bazelTargets[0]
if actualBazelTarget.content != testCase.expectedBazelTarget {
t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
testCase.expectedBazelTarget,
actualBazelTarget.content,
)
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
index 8cdee65..f2a4058 100644
--- a/bp2build/bzl_conversion_test.go
+++ b/bp2build/bzl_conversion_test.go
@@ -172,7 +172,7 @@
content: "irrelevant",
},
}
- files := CreateBazelFiles(ruleShims, make(map[string][]BazelTarget), QueryView)
+ files := CreateBazelFiles(ruleShims, make(map[string]BazelTargets), QueryView)
var actualSoongModuleBzl BazelFile
for _, f := range files {
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 2025ef7..62cd8d4 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -17,7 +17,7 @@
func CreateBazelFiles(
ruleShims map[string]RuleShim,
- buildToTargets map[string][]BazelTarget,
+ buildToTargets map[string]BazelTargets,
mode CodegenMode) []BazelFile {
files := make([]BazelFile, 0, len(ruleShims)+len(buildToTargets)+numAdditionalFiles)
@@ -43,20 +43,20 @@
return files
}
-func createBuildFiles(buildToTargets map[string][]BazelTarget, mode CodegenMode) []BazelFile {
+func createBuildFiles(buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
files := make([]BazelFile, 0, len(buildToTargets))
for _, dir := range android.SortedStringKeys(buildToTargets) {
- content := soongModuleLoad
- if mode == Bp2Build {
- // No need to load soong_module for bp2build BUILD files.
- content = ""
- }
targets := buildToTargets[dir]
sort.Slice(targets, func(i, j int) bool { return targets[i].name < targets[j].name })
- for _, t := range targets {
- content += "\n\n"
- content += t.content
+ content := soongModuleLoad
+ if mode == Bp2Build {
+ content = targets.LoadStatements()
}
+ if content != "" {
+ // If there are load statements, add a couple of newlines.
+ content += "\n\n"
+ }
+ content += targets.String()
files = append(files, newFile(dir, "BUILD.bazel", content))
}
return files
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 7f75b14..ec5f27e 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -55,7 +55,7 @@
}
func TestCreateBazelFiles_QueryView_AddsTopLevelFiles(t *testing.T) {
- files := CreateBazelFiles(map[string]RuleShim{}, map[string][]BazelTarget{}, QueryView)
+ files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, QueryView)
expectedFilePaths := []filepath{
{
dir: "",
@@ -85,7 +85,7 @@
}
func TestCreateBazelFiles_Bp2Build_AddsTopLevelFiles(t *testing.T) {
- files := CreateBazelFiles(map[string]RuleShim{}, map[string][]BazelTarget{}, Bp2Build)
+ files := CreateBazelFiles(map[string]RuleShim{}, map[string]BazelTargets{}, Bp2Build)
expectedFilePaths := []filepath{
{
dir: "",
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 4c31d2d..5e6481b 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -137,3 +137,29 @@
})
}
}
+
+// A bp2build mutator that uses load statements and creates a 1:M mapping from
+// module to target.
+func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
+ if m, ok := ctx.Module().(*customModule); ok {
+ baseName := "__bp2build__" + m.Name()
+ ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
+ Name: proptools.StringPtr(baseName),
+ }, &bazel.BazelTargetModuleProperties{
+ Rule_class: "my_library",
+ Bzl_load_location: "//build/bazel/rules:rules.bzl",
+ })
+ ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
+ Name: proptools.StringPtr(baseName + "_proto_library_deps"),
+ }, &bazel.BazelTargetModuleProperties{
+ Rule_class: "proto_library",
+ Bzl_load_location: "//build/bazel/rules:proto.bzl",
+ })
+ ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{
+ Name: proptools.StringPtr(baseName + "_my_proto_library_deps"),
+ }, &bazel.BazelTargetModuleProperties{
+ Rule_class: "my_proto_library",
+ Bzl_load_location: "//build/bazel/rules:proto.bzl",
+ })
+ }
+}
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 7dd50f6..e0f8caa 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -244,7 +244,7 @@
jobs = runtime.NumCPU() / 4
ramGb := int(config.TotalRAM() / 1024 / 1024 / 1024)
- if ramJobs := ramGb / 20; ramGb > 0 && jobs > ramJobs {
+ if ramJobs := ramGb / 25; ramGb > 0 && jobs > ramJobs {
jobs = ramJobs
}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 5ef4a90..654617c 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -146,7 +146,7 @@
builder.Command().Text("rm").Flag("-rf").Output(propFile)
for _, p := range props {
builder.Command().
- Text("echo").Flag("-e").
+ Text("echo").
Flag(`"` + p.name + "=" + p.value + `"`).
Text(">>").Output(propFile)
}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 1f47dec..ddfb459 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -47,7 +47,7 @@
ctx.BottomUp("genrule_tool_deps", toolDepsMutator).Parallel()
})
- android.RegisterBp2BuildMutator("genrule", bp2buildMutator)
+ android.RegisterBp2BuildMutator("genrule", GenruleBp2Build)
}
var (
@@ -794,15 +794,22 @@
return module
}
-func bp2buildMutator(ctx android.TopDownMutatorContext) {
+func GenruleBp2Build(ctx android.TopDownMutatorContext) {
if m, ok := ctx.Module().(*Module); ok {
name := "__bp2build__" + m.Name()
+ // Bazel only has the "tools" attribute.
+ tools := append(m.properties.Tools, m.properties.Tool_files...)
+
// Replace in and out variables with $< and $@
var cmd string
if m.properties.Cmd != nil {
cmd = strings.Replace(*m.properties.Cmd, "$(in)", "$(SRCS)", -1)
cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
cmd = strings.Replace(cmd, "$(genDir)", "$(GENDIR)", -1)
+ if len(tools) > 0 {
+ cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools[0]), -1)
+ cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools[0]), -1)
+ }
}
// The Out prop is not in an immediately accessible field
@@ -816,9 +823,6 @@
}
}
- // Bazel only has the "tools" attribute.
- tools := append(m.properties.Tools, m.properties.Tool_files...)
-
// Create the BazelTargetModule.
ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{
Name: proptools.StringPtr(name),
diff --git a/licenses/Android.bp b/licenses/Android.bp
index e87bdcf..f4a76d7 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -125,6 +125,22 @@
}
license_kind {
+ name: "SPDX-license-identifier-APSL-1.1",
+ conditions: [
+ "reciprocal",
+ ],
+ url: "https://spdx.org/licenses/APSL-1.1.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-APSL-2.0",
+ conditions: [
+ "reciprocal",
+ ],
+ url: "https://spdx.org/licenses/APSL-2.0.html",
+}
+
+license_kind {
name: "SPDX-license-identifier-Apache",
conditions: ["notice"],
}
@@ -558,6 +574,23 @@
}
license_kind {
+ name: "SPDX-license-identifier-CDDL",
+ conditions: ["reciprocal"],
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CDDL-1.0",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/CDLL-1.0.html",
+}
+
+license_kind {
+ name: "SPDX-license-identifier-CDDL-1.1",
+ conditions: ["reciprocal"],
+ url: "https://spdx.org/licenses/CDLL-1.1.html",
+}
+
+license_kind {
name: "SPDX-license-identifier-CPAL-1.0",
conditions: [
"by_exception_only",
diff --git a/rust/androidmk.go b/rust/androidmk.go
index e9da6fa..0307727 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -82,9 +82,6 @@
}
ret.Class = "EXECUTABLES"
- ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
- entries.SetOptionalPath("LOCAL_PREBUILT_COVERAGE_ARCHIVE", binary.coverageOutputZipFile)
- })
}
func (test *testDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
@@ -117,10 +114,6 @@
if library.distFile.Valid() {
ret.DistFiles = android.MakeDefaultDistFiles(library.distFile.Path())
}
-
- ret.ExtraEntries = append(ret.ExtraEntries, func(entries *android.AndroidMkEntries) {
- entries.SetOptionalPath("LOCAL_PREBUILT_COVERAGE_ARCHIVE", library.coverageOutputZipFile)
- })
}
func (procMacro *procMacroDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
diff --git a/rust/binary.go b/rust/binary.go
index ca07d07..2963a37 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -121,7 +121,7 @@
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
- outputs := TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
+ TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
if binary.stripper.NeedsStrip(ctx) {
strippedOutputFile := android.PathForModuleOut(ctx, "stripped", fileName)
@@ -129,24 +129,9 @@
binary.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
}
- binary.coverageFile = outputs.coverageFile
-
- var coverageFiles android.Paths
- if outputs.coverageFile != nil {
- coverageFiles = append(coverageFiles, binary.coverageFile)
- }
- if len(deps.coverageFiles) > 0 {
- coverageFiles = append(coverageFiles, deps.coverageFiles...)
- }
- binary.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, binary.getStem(ctx))
-
return outputFile
}
-func (binary *binaryDecorator) coverageOutputZipPath() android.OptionalPath {
- return binary.coverageOutputZipFile
-}
-
func (binary *binaryDecorator) autoDep(ctx BaseModuleContext) autoDep {
// Binaries default to dylib dependencies for device, rlib for host.
if binary.preferRlib() {
diff --git a/rust/binary_test.go b/rust/binary_test.go
index b44a5bc..86f50d3 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -130,6 +130,9 @@
if !strings.Contains(flags, "-C relocation-model=static") {
t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags)
}
+ if !strings.Contains(flags, "-C panic=abort") {
+ t.Errorf("static binary missing '-C panic=abort' in rustcFlags, found: %#v", flags)
+ }
if !strings.Contains(linkFlags, "-static") {
t.Errorf("static binary missing '-static' in linkFlags, found: %#v", flags)
}
diff --git a/rust/builder.go b/rust/builder.go
index 77d339a..56fe031 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -19,10 +19,8 @@
"strings"
"github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
"android/soong/android"
- "android/soong/cc"
"android/soong/rust/config"
)
@@ -76,8 +74,7 @@
)
type buildOutput struct {
- outputFile android.Path
- coverageFile android.Path
+ outputFile android.Path
}
func init() {
@@ -195,27 +192,6 @@
implicits = append(implicits, deps.CrtBegin.Path(), deps.CrtEnd.Path())
}
- if flags.Coverage {
- var gcnoFile android.WritablePath
- // Provide consistency with cc gcda output, see cc/builder.go init()
- profileEmitArg := strings.TrimPrefix(cc.PwdPrefix(), "PWD=") + "/"
-
- if outputFile.Ext() != "" {
- // rustc seems to split the output filename at the first '.' when determining the gcno filename
- // so we need to do the same here.
- gcnoFile = android.PathForModuleOut(ctx, strings.Split(outputFile.Base(), ".")[0]+".gcno")
- rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
- ctx, pathtools.ReplaceExtension(outputFile.Base(), "gcda")).String())
- } else {
- gcnoFile = android.PathForModuleOut(ctx, outputFile.Base()+".gcno")
- rustcFlags = append(rustcFlags, "-Z profile-emit="+profileEmitArg+android.PathForModuleOut(
- ctx, outputFile.Base()+".gcda").String())
- }
-
- implicitOutputs = append(implicitOutputs, gcnoFile)
- output.coverageFile = gcnoFile
- }
-
if len(deps.SrcDeps) > 0 {
genSubDir := "out/"
moduleGenDir := android.PathForModuleOut(ctx, genSubDir)
@@ -292,21 +268,3 @@
return output
}
-
-func TransformCoverageFilesToZip(ctx ModuleContext,
- covFiles android.Paths, baseName string) android.OptionalPath {
- if len(covFiles) > 0 {
-
- outputFile := android.PathForModuleOut(ctx, baseName+".zip")
-
- ctx.Build(pctx, android.BuildParams{
- Rule: zip,
- Description: "zip " + outputFile.Base(),
- Inputs: covFiles,
- Output: outputFile,
- })
-
- return android.OptionalPathForPath(outputFile)
- }
- return android.OptionalPath{}
-}
diff --git a/rust/compiler.go b/rust/compiler.go
index 2d9575c..c921824 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -136,8 +136,7 @@
}
type baseCompiler struct {
- Properties BaseCompilerProperties
- coverageFile android.Path //rustc generates a single gcno file
+ Properties BaseCompilerProperties
// Install related
dir string
@@ -148,8 +147,7 @@
location installLocation
sanitize *sanitize
- coverageOutputZipFile android.OptionalPath
- distFile android.OptionalPath
+ distFile android.OptionalPath
// Stripped output file. If Valid(), this file will be installed instead of outputFile.
strippedOutputFile android.OptionalPath
}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 21df024..fc11d29 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -19,6 +19,7 @@
"prebuilts/rust",
"system/bt",
"system/extras/profcollectd",
+ "system/extras/simpleperf",
"system/hardware/interfaces/keystore2",
"system/security",
"system/tools/aidl",
diff --git a/rust/config/global.go b/rust/config/global.go
index 08ec877..fb62278 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -49,7 +49,9 @@
"-C relocation-model=pic",
}
- deviceGlobalRustFlags = []string{}
+ deviceGlobalRustFlags = []string{
+ "-C panic=abort",
+ }
deviceGlobalLinkFlags = []string{
// Prepend the lld flags from cc_config so we stay in sync with cc
diff --git a/rust/coverage.go b/rust/coverage.go
index 26375f5..dac526a 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -20,7 +20,9 @@
"android/soong/cc"
)
-var CovLibraryName = "libprofile-extras"
+var CovLibraryName = "libprofile-clang-extras"
+
+const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
type coverage struct {
Properties cc.CoverageProperties
@@ -53,9 +55,9 @@
flags.Coverage = true
coverage := ctx.GetDirectDepWithTag(CovLibraryName, cc.CoverageDepTag).(cc.LinkableInterface)
flags.RustFlags = append(flags.RustFlags,
- "-Z profile", "-g", "-C opt-level=0", "-C link-dead-code")
+ "-Z instrument-coverage", "-g", "-C link-dead-code")
flags.LinkFlags = append(flags.LinkFlags,
- "--coverage", "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,getenv")
+ profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
}
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index e7f873e..4b6c9d4 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -56,7 +56,7 @@
fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
- rustcCoverageFlags := []string{"-Z profile", " -g ", "-C opt-level=0", "-C link-dead-code"}
+ rustcCoverageFlags := []string{"-Z instrument-coverage", " -g ", "-C link-dead-code"}
for _, flag := range rustcCoverageFlags {
missingErrorStr := "missing rustc flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
containsErrorStr := "contains rustc flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
@@ -75,7 +75,7 @@
}
}
- linkCoverageFlags := []string{"--coverage", " -g "}
+ linkCoverageFlags := []string{"-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw", " -g "}
for _, flag := range linkCoverageFlags {
missingErrorStr := "missing rust linker flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
containsErrorStr := "contains rust linker flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
@@ -96,83 +96,6 @@
}
-// Test coverage files are included correctly
-func TestCoverageZip(t *testing.T) {
- ctx := testRustCov(t, `
- rust_library {
- name: "libfoo",
- srcs: ["foo.rs"],
- rlibs: ["librlib"],
- crate_name: "foo",
- }
- rust_ffi_static {
- name: "libbaz",
- srcs: ["foo.rs"],
- rlibs: ["librlib"],
- crate_name: "baz",
- }
- rust_library_rlib {
- name: "librlib",
- srcs: ["foo.rs"],
- crate_name: "rlib",
- }
- rust_binary {
- name: "fizz",
- rlibs: ["librlib"],
- static_libs: ["libbaz"],
- srcs: ["foo.rs"],
- }
- cc_binary {
- name: "buzz",
- static_libs: ["libbaz"],
- srcs: ["foo.c"],
- }
- cc_library {
- name: "libbar",
- static_libs: ["libbaz"],
- compile_multilib: "64",
- srcs: ["foo.c"],
- }`)
-
- fizzZipInputs := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("zip").Inputs.Strings()
- libfooZipInputs := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_dylib_cov").Rule("zip").Inputs.Strings()
- buzzZipInputs := ctx.ModuleForTests("buzz", "android_arm64_armv8-a_cov").Rule("zip").Inputs.Strings()
- libbarZipInputs := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared_cov").Rule("zip").Inputs.Strings()
-
- // Make sure the expected number of input files are included.
- if len(fizzZipInputs) != 3 {
- t.Fatalf("expected only 3 coverage inputs for rust 'fizz' binary, got %#v: %#v", len(fizzZipInputs), fizzZipInputs)
- }
- if len(libfooZipInputs) != 2 {
- t.Fatalf("expected only 2 coverage inputs for rust 'libfoo' library, got %#v: %#v", len(libfooZipInputs), libfooZipInputs)
- }
- if len(buzzZipInputs) != 2 {
- t.Fatalf("expected only 2 coverage inputs for cc 'buzz' binary, got %#v: %#v", len(buzzZipInputs), buzzZipInputs)
- }
- if len(libbarZipInputs) != 2 {
- t.Fatalf("expected only 2 coverage inputs for cc 'libbar' library, got %#v: %#v", len(libbarZipInputs), libbarZipInputs)
- }
-
- // Make sure the expected inputs are provided to the zip rule.
- if !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_rlib_dylib-std_cov/librlib.gcno") ||
- !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") ||
- !android.SuffixInList(fizzZipInputs, "android_arm64_armv8-a_cov/fizz.gcno") {
- t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", fizzZipInputs)
- }
- if !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_rlib_dylib-std_cov/librlib.gcno") ||
- !android.SuffixInList(libfooZipInputs, "android_arm64_armv8-a_dylib_cov/libfoo.gcno") {
- t.Fatalf("missing expected coverage files for rust 'fizz' binary: %#v", libfooZipInputs)
- }
- if !android.SuffixInList(buzzZipInputs, "android_arm64_armv8-a_cov/obj/foo.gcno") ||
- !android.SuffixInList(buzzZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") {
- t.Fatalf("missing expected coverage files for cc 'buzz' binary: %#v", buzzZipInputs)
- }
- if !android.SuffixInList(libbarZipInputs, "android_arm64_armv8-a_static_cov/obj/foo.gcno") ||
- !android.SuffixInList(libbarZipInputs, "android_arm64_armv8-a_static_cov/libbaz.gcno") {
- t.Fatalf("missing expected coverage files for cc 'libbar' library: %#v", libbarZipInputs)
- }
-}
-
func TestCoverageDeps(t *testing.T) {
ctx := testRustCov(t, `
rust_binary {
@@ -181,7 +104,7 @@
}`)
fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustc")
- if !strings.Contains(fizz.Args["linkFlags"], "libprofile-extras.a") {
- t.Fatalf("missing expected coverage 'libprofile-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
+ if !strings.Contains(fizz.Args["linkFlags"], "libprofile-clang-extras.a") {
+ t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
}
}
diff --git a/rust/library.go b/rust/library.go
index 4ac52b4..6433285 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -452,26 +452,22 @@
fileName = library.getStem(ctx) + ctx.toolchain().RlibSuffix()
outputFile = android.PathForModuleOut(ctx, fileName)
- outputs := TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
- library.coverageFile = outputs.coverageFile
+ TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
} else if library.dylib() {
fileName = library.getStem(ctx) + ctx.toolchain().DylibSuffix()
outputFile = android.PathForModuleOut(ctx, fileName)
- outputs := TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
- library.coverageFile = outputs.coverageFile
+ TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
} else if library.static() {
fileName = library.getStem(ctx) + ctx.toolchain().StaticLibSuffix()
outputFile = android.PathForModuleOut(ctx, fileName)
- outputs := TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
- library.coverageFile = outputs.coverageFile
+ TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
} else if library.shared() {
fileName = library.sharedLibFilename(ctx)
outputFile = android.PathForModuleOut(ctx, fileName)
- outputs := TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
- library.coverageFile = outputs.coverageFile
+ TransformSrctoShared(ctx, srcPath, deps, flags, outputFile, deps.linkDirs)
}
if !library.rlib() && library.stripper.NeedsStrip(ctx) {
@@ -480,15 +476,6 @@
library.strippedOutputFile = android.OptionalPathForPath(strippedOutputFile)
}
- var coverageFiles android.Paths
- if library.coverageFile != nil {
- coverageFiles = append(coverageFiles, library.coverageFile)
- }
- if len(deps.coverageFiles) > 0 {
- coverageFiles = append(coverageFiles, deps.coverageFiles...)
- }
- library.coverageOutputZipFile = TransformCoverageFilesToZip(ctx, coverageFiles, library.getStem(ctx))
-
if library.rlib() || library.dylib() {
library.flagExporter.exportLinkDirs(deps.linkDirs...)
library.flagExporter.exportDepFlags(deps.depFlags...)
diff --git a/rust/rust.go b/rust/rust.go
index cda01d8..2ef9daf 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -291,8 +291,6 @@
depGeneratedHeaders android.Paths
depSystemIncludePaths android.Paths
- coverageFiles android.Paths
-
CrtBegin android.OptionalPath
CrtEnd android.OptionalPath
@@ -515,15 +513,7 @@
func (mod *Module) CoverageFiles() android.Paths {
if mod.compiler != nil {
- if !mod.compiler.nativeCoverage() {
- return android.Paths{}
- }
- if library, ok := mod.compiler.(*libraryDecorator); ok {
- if library.coverageFile != nil {
- return android.Paths{library.coverageFile}
- }
- return android.Paths{}
- }
+ return android.Paths{}
}
panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName()))
}
@@ -840,7 +830,6 @@
ctx.ModuleErrorf("mod %q not an rlib library", depName+rustDep.Properties.SubName)
return
}
- depPaths.coverageFiles = append(depPaths.coverageFiles, rustDep.CoverageFiles()...)
directRlibDeps = append(directRlibDeps, rustDep)
mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, depName+rustDep.Properties.SubName)
case procMacroDepTag:
@@ -916,7 +905,6 @@
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
- depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...)
directStaticLibDeps = append(directStaticLibDeps, ccDep)
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
case cc.IsSharedDepTag(depTag):
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 48c8d74..fc7f47e 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -134,7 +134,7 @@
if tctx.config == nil {
t.Fatalf("tctx.config not been generated yet. Please call generateConfig first.")
}
- tctx.config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
+ tctx.config.TestProductVariables.ClangCoverage = proptools.BoolPtr(true)
tctx.config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
tctx.config.TestProductVariables.NativeCoveragePaths = []string{"*"}
}
diff --git a/rust/test.go b/rust/test.go
index 408e03a..35e04ff 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -120,6 +120,9 @@
if test.testHarness() {
flags.RustFlags = append(flags.RustFlags, "--test")
}
+ if ctx.Device() {
+ flags.RustFlags = append(flags.RustFlags, "-Z panic_abort_tests")
+ }
return flags
}
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index d9c33f6..1fabd92 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -106,7 +106,7 @@
cmd := Command(ctx, config, "startRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd))
if output, err := cmd.CombinedOutput(); err != nil {
- ctx.Fatalf("rbe bootstrap failed with: %v\n%s\n", err, output)
+ ctx.Fatalf("Unable to start RBE reproxy\nFAILED: RBE bootstrap failed with: %v\n%s\n", err, output)
}
}