Merge "rust: Refactor stripped output file path"
diff --git a/android/Android.bp b/android/Android.bp
index 6450a06..cfa2be3 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -19,6 +19,9 @@
"soong-ui-metrics_proto",
"golang-protobuf-proto",
"golang-protobuf-encoding-prototext",
+
+ // Only used for tests.
+ "androidmk-parser",
],
srcs: [
"androidmk.go",
diff --git a/android/androidmk.go b/android/androidmk.go
index b6b04a6..9025a74 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -25,7 +25,6 @@
"bytes"
"fmt"
"io"
- "io/ioutil"
"os"
"path/filepath"
"reflect"
@@ -35,6 +34,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
+ "github.com/google/blueprint/pathtools"
)
func init() {
@@ -690,7 +690,7 @@
})
}
-func translateAndroidMk(ctx SingletonContext, mkFile string, mods []blueprint.Module) error {
+func translateAndroidMk(ctx SingletonContext, absMkFile string, mods []blueprint.Module) error {
buf := &bytes.Buffer{}
fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
@@ -699,7 +699,7 @@
for _, mod := range mods {
err := translateAndroidMkModule(ctx, buf, mod)
if err != nil {
- os.Remove(mkFile)
+ os.Remove(absMkFile)
return err
}
@@ -719,27 +719,7 @@
fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
}
- // Don't write to the file if it hasn't changed
- if _, err := os.Stat(absolutePath(mkFile)); !os.IsNotExist(err) {
- if data, err := ioutil.ReadFile(absolutePath(mkFile)); err == nil {
- matches := buf.Len() == len(data)
-
- if matches {
- for i, value := range buf.Bytes() {
- if value != data[i] {
- matches = false
- break
- }
- }
- }
-
- if matches {
- return nil
- }
- }
- }
-
- return ioutil.WriteFile(absolutePath(mkFile), buf.Bytes(), 0666)
+ return pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
}
func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {
diff --git a/android/config.go b/android/config.go
index bd13c45..6f05565 100644
--- a/android/config.go
+++ b/android/config.go
@@ -334,10 +334,8 @@
ShippingApiLevel: stringPtr("30"),
},
- outDir: buildDir,
- // soongOutDir is inconsistent with production (it should be buildDir + "/soong")
- // but a lot of tests assume this :(
- soongOutDir: buildDir,
+ outDir: buildDir,
+ soongOutDir: filepath.Join(buildDir, "soong"),
captureBuild: true,
env: envCopy,
@@ -592,12 +590,11 @@
return path
}
-func (c *config) HostJavaToolPath(ctx PathContext, path string) Path {
- return PathForOutput(ctx, "host", c.PrebuiltOS(), "framework", path)
-}
-
-func (c *config) HostJavaBinToolPath(ctx PathContext, tool string) Path {
- path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false, tool)
+func (c *config) HostJavaToolPath(ctx PathContext, tool string) Path {
+ path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "framework", false, tool)
+ if ctx.Config().KatiEnabled() {
+ path = path.ToMakePath()
+ }
return path
}
diff --git a/android/makevars.go b/android/makevars.go
index 20db65a..8825d1a 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -142,15 +142,19 @@
var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
+func getSingletonMakevarsProviders(config Config) *[]makeVarsProvider {
+ return config.Once(singletonMakeVarsProvidersKey, func() interface{} {
+ return &[]makeVarsProvider{}
+ }).(*[]makeVarsProvider)
+}
+
// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
// the list of MakeVarsProviders to run.
func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
// Singletons are registered on the Context and may be different between different Contexts,
// for example when running multiple tests. Store the SingletonMakeVarsProviders in the
// Config so they are attached to the Context.
- singletonMakeVarsProviders := config.Once(singletonMakeVarsProvidersKey, func() interface{} {
- return &[]makeVarsProvider{}
- }).(*[]makeVarsProvider)
+ singletonMakeVarsProviders := getSingletonMakevarsProviders(config)
*singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
@@ -175,7 +179,9 @@
return &makeVarsSingleton{}
}
-type makeVarsSingleton struct{}
+type makeVarsSingleton struct {
+ installsForTesting []byte
+}
type makeVarsProvider struct {
pctx PackageContext
@@ -238,7 +244,7 @@
var katiSymlinks []katiInstall
providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
- providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...)
+ providers = append(providers, *getSingletonMakevarsProviders(ctx.Config())...)
for _, provider := range providers {
mctx := &makeVarsContext{
@@ -313,6 +319,8 @@
if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
ctx.Errorf(err.Error())
}
+
+ s.installsForTesting = installsBytes
}
func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
@@ -465,15 +473,19 @@
for _, symlink := range symlinks {
fmt.Fprintf(buf, "%s:", symlink.to.String())
+ if symlink.from != nil {
+ // The symlink doesn't need updating when the target is modified, but we sometimes
+ // have a dependency on a symlink to a binary instead of to the binary directly, and
+ // the mtime of the symlink must be updated when the binary is modified, so use a
+ // normal dependency here instead of an order-only dependency.
+ fmt.Fprintf(buf, " %s", symlink.from.String())
+ }
for _, dep := range symlink.implicitDeps {
fmt.Fprintf(buf, " %s", dep.String())
}
- if symlink.from != nil || len(symlink.orderOnlyDeps) > 0 {
+ if len(symlink.orderOnlyDeps) > 0 {
fmt.Fprintf(buf, " |")
}
- if symlink.from != nil {
- fmt.Fprintf(buf, " %s", symlink.from.String())
- }
for _, dep := range symlink.orderOnlyDeps {
fmt.Fprintf(buf, " %s", dep.String())
}
diff --git a/android/module.go b/android/module.go
index 3447f2b..c778078 100644
--- a/android/module.go
+++ b/android/module.go
@@ -2953,6 +2953,10 @@
to: fullInstallPath,
})
} else {
+ // The symlink doesn't need updating when the target is modified, but we sometimes
+ // have a dependency on a symlink to a binary instead of to the binary directly, and
+ // the mtime of the symlink must be updated when the binary is modified, so use a
+ // normal dependency here instead of an order-only dependency.
m.Build(pctx, BuildParams{
Rule: Symlink,
Description: "install symlink " + fullInstallPath.Base(),
diff --git a/android/module_test.go b/android/module_test.go
index 9e2b0ca..8607a8d 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -15,7 +15,12 @@
package android
import (
+ "bytes"
+ "path/filepath"
+ "runtime"
"testing"
+
+ mkparser "android/soong/androidmk/parser"
)
func TestSrcIsModule(t *testing.T) {
@@ -199,17 +204,28 @@
}
}
+func (m *depsModule) InstallBypassMake() bool {
+ return true
+}
+
func (m *depsModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+ outputFile := PathForModuleOut(ctx, ctx.ModuleName())
+ ctx.Build(pctx, BuildParams{
+ Rule: Touch,
+ Output: outputFile,
+ })
+ installFile := ctx.InstallFile(PathForModuleInstall(ctx), ctx.ModuleName(), outputFile)
+ ctx.InstallSymlink(PathForModuleInstall(ctx, "symlinks"), ctx.ModuleName(), installFile)
}
func (m *depsModule) DepsMutator(ctx BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), nil, m.props.Deps...)
+ ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
}
func depsModuleFactory() Module {
m := &depsModule{}
m.AddProperties(&m.props)
- InitAndroidModule(m)
+ InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon)
return m
}
@@ -320,3 +336,286 @@
ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(expectedErrs)).
RunTestWithBp(t, bp)
}
+
+func TestInstall(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+ bp := `
+ deps {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ deps {
+ name: "bar",
+ deps: ["baz", "qux"],
+ }
+
+ deps {
+ name: "baz",
+ deps: ["qux"],
+ }
+
+ deps {
+ name: "qux",
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForModuleTests,
+ PrepareForTestWithArchMutator,
+ ).RunTestWithBp(t, bp)
+
+ module := func(name string, host bool) TestingModule {
+ variant := "android_common"
+ if host {
+ variant = result.Config.BuildOSCommonTarget.String()
+ }
+ return result.ModuleForTests(name, variant)
+ }
+
+ outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
+
+ installRule := func(name string) TestingBuildParams {
+ return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system", name))
+ }
+
+ symlinkRule := func(name string) TestingBuildParams {
+ return module(name, false).Output(filepath.Join("out/soong/target/product/test_device/system/symlinks", name))
+ }
+
+ hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
+
+ hostInstallRule := func(name string) TestingBuildParams {
+ return module(name, true).Output(filepath.Join("out/soong/host/linux-x86", name))
+ }
+
+ hostSymlinkRule := func(name string) TestingBuildParams {
+ return module(name, true).Output(filepath.Join("out/soong/host/linux-x86/symlinks", name))
+ }
+
+ assertInputs := func(params TestingBuildParams, inputs ...Path) {
+ t.Helper()
+ AssertArrayString(t, "expected inputs", Paths(inputs).Strings(),
+ append(PathsIfNonNil(params.Input), params.Inputs...).Strings())
+ }
+
+ assertImplicits := func(params TestingBuildParams, implicits ...Path) {
+ t.Helper()
+ AssertArrayString(t, "expected implicit dependencies", Paths(implicits).Strings(),
+ append(PathsIfNonNil(params.Implicit), params.Implicits...).Strings())
+ }
+
+ assertOrderOnlys := func(params TestingBuildParams, orderonlys ...Path) {
+ t.Helper()
+ AssertArrayString(t, "expected orderonly dependencies", Paths(orderonlys).Strings(),
+ params.OrderOnly.Strings())
+ }
+
+ // Check host install rule dependencies
+ assertInputs(hostInstallRule("foo"), hostOutputRule("foo").Output)
+ assertImplicits(hostInstallRule("foo"),
+ hostInstallRule("bar").Output,
+ hostSymlinkRule("bar").Output,
+ hostInstallRule("baz").Output,
+ hostSymlinkRule("baz").Output,
+ hostInstallRule("qux").Output,
+ hostSymlinkRule("qux").Output,
+ )
+ assertOrderOnlys(hostInstallRule("foo"))
+
+ // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
+ // order-only dependency, so that the tool gets updated when the symlink is depended on.
+ assertInputs(hostSymlinkRule("foo"), hostInstallRule("foo").Output)
+ assertImplicits(hostSymlinkRule("foo"))
+ assertOrderOnlys(hostSymlinkRule("foo"))
+
+ // Check device install rule dependencies
+ assertInputs(installRule("foo"), outputRule("foo").Output)
+ assertImplicits(installRule("foo"))
+ assertOrderOnlys(installRule("foo"),
+ installRule("bar").Output,
+ symlinkRule("bar").Output,
+ installRule("baz").Output,
+ symlinkRule("baz").Output,
+ installRule("qux").Output,
+ symlinkRule("qux").Output,
+ )
+
+ // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
+ // but the current implementation uses a normal dependency.
+ assertInputs(symlinkRule("foo"), installRule("foo").Output)
+ assertImplicits(symlinkRule("foo"))
+ assertOrderOnlys(symlinkRule("foo"))
+}
+
+func TestInstallBypassMake(t *testing.T) {
+ if runtime.GOOS != "linux" {
+ t.Skip("requires linux")
+ }
+ bp := `
+ deps {
+ name: "foo",
+ deps: ["bar"],
+ }
+
+ deps {
+ name: "bar",
+ deps: ["baz", "qux"],
+ }
+
+ deps {
+ name: "baz",
+ deps: ["qux"],
+ }
+
+ deps {
+ name: "qux",
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForModuleTests,
+ PrepareForTestWithArchMutator,
+ FixtureModifyConfig(SetKatiEnabledForTests),
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterSingletonType("makevars", makeVarsSingletonFunc)
+ }),
+ ).RunTestWithBp(t, bp)
+
+ installs := result.SingletonForTests("makevars").Singleton().(*makeVarsSingleton).installsForTesting
+ buf := bytes.NewBuffer(append([]byte(nil), installs...))
+ parser := mkparser.NewParser("makevars", buf)
+
+ nodes, errs := parser.Parse()
+ if len(errs) > 0 {
+ t.Fatalf("error parsing install rules: %s", errs[0])
+ }
+
+ rules := parseMkRules(t, result.Config, nodes)
+
+ module := func(name string, host bool) TestingModule {
+ variant := "android_common"
+ if host {
+ variant = result.Config.BuildOSCommonTarget.String()
+ }
+ return result.ModuleForTests(name, variant)
+ }
+
+ outputRule := func(name string) TestingBuildParams { return module(name, false).Output(name) }
+
+ ruleForOutput := func(output string) installMakeRule {
+ for _, rule := range rules {
+ if rule.target == output {
+ return rule
+ }
+ }
+ t.Fatalf("no make install rule for %s", output)
+ return installMakeRule{}
+ }
+
+ installRule := func(name string) installMakeRule {
+ return ruleForOutput(filepath.Join("out/target/product/test_device/system", name))
+ }
+
+ symlinkRule := func(name string) installMakeRule {
+ return ruleForOutput(filepath.Join("out/target/product/test_device/system/symlinks", name))
+ }
+
+ hostOutputRule := func(name string) TestingBuildParams { return module(name, true).Output(name) }
+
+ hostInstallRule := func(name string) installMakeRule {
+ return ruleForOutput(filepath.Join("out/host/linux-x86", name))
+ }
+
+ hostSymlinkRule := func(name string) installMakeRule {
+ return ruleForOutput(filepath.Join("out/host/linux-x86/symlinks", name))
+ }
+
+ assertDeps := func(rule installMakeRule, deps ...string) {
+ t.Helper()
+ AssertArrayString(t, "expected inputs", deps, rule.deps)
+ }
+
+ assertOrderOnlys := func(rule installMakeRule, orderonlys ...string) {
+ t.Helper()
+ AssertArrayString(t, "expected orderonly dependencies", orderonlys, rule.orderOnlyDeps)
+ }
+
+ // Check host install rule dependencies
+ assertDeps(hostInstallRule("foo"),
+ hostOutputRule("foo").Output.String(),
+ hostInstallRule("bar").target,
+ hostSymlinkRule("bar").target,
+ hostInstallRule("baz").target,
+ hostSymlinkRule("baz").target,
+ hostInstallRule("qux").target,
+ hostSymlinkRule("qux").target,
+ )
+ assertOrderOnlys(hostInstallRule("foo"))
+
+ // Check host symlink rule dependencies. Host symlinks must use a normal dependency, not an
+ // order-only dependency, so that the tool gets updated when the symlink is depended on.
+ assertDeps(hostSymlinkRule("foo"), hostInstallRule("foo").target)
+ assertOrderOnlys(hostSymlinkRule("foo"))
+
+ // Check device install rule dependencies
+ assertDeps(installRule("foo"), outputRule("foo").Output.String())
+ assertOrderOnlys(installRule("foo"),
+ installRule("bar").target,
+ symlinkRule("bar").target,
+ installRule("baz").target,
+ symlinkRule("baz").target,
+ installRule("qux").target,
+ symlinkRule("qux").target,
+ )
+
+ // Check device symlink rule dependencies. Device symlinks could use an order-only dependency,
+ // but the current implementation uses a normal dependency.
+ assertDeps(symlinkRule("foo"), installRule("foo").target)
+ assertOrderOnlys(symlinkRule("foo"))
+}
+
+type installMakeRule struct {
+ target string
+ deps []string
+ orderOnlyDeps []string
+}
+
+func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []installMakeRule {
+ var rules []installMakeRule
+ for _, node := range nodes {
+ if mkParserRule, ok := node.(*mkparser.Rule); ok {
+ var rule installMakeRule
+
+ if targets := mkParserRule.Target.Words(); len(targets) == 0 {
+ t.Fatalf("no targets for rule %s", mkParserRule.Dump())
+ } else if len(targets) > 1 {
+ t.Fatalf("unsupported multiple targets for rule %s", mkParserRule.Dump())
+ } else if !targets[0].Const() {
+ t.Fatalf("unsupported non-const target for rule %s", mkParserRule.Dump())
+ } else {
+ rule.target = normalizeStringRelativeToTop(config, targets[0].Value(nil))
+ }
+
+ prereqList := &rule.deps
+ for _, prereq := range mkParserRule.Prerequisites.Words() {
+ if !prereq.Const() {
+ t.Fatalf("unsupported non-const prerequisite for rule %s", mkParserRule.Dump())
+ }
+
+ if prereq.Value(nil) == "|" {
+ prereqList = &rule.orderOnlyDeps
+ continue
+ }
+
+ *prereqList = append(*prereqList, normalizeStringRelativeToTop(config, prereq.Value(nil)))
+ }
+
+ rules = append(rules, rule)
+ }
+ }
+
+ return rules
+}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index abd0c29..c19debb 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -177,16 +177,6 @@
})
}
-// HostJavaBinToolVariable returns a Variable whose value is the path to a host java tool
-// in the bin directory for host java targets. It may only be called during a Go
-// package's initialization - either from the init() function or as part of a
-// package-scoped variable's initialization.
-func (p PackageContext) HostJavaBinToolVariable(name, path string) blueprint.Variable {
- return p.VariableFunc(name, func(ctx PackageVarContext) string {
- return ctx.Config().HostJavaBinToolPath(ctx, path).String()
- })
-}
-
// HostJNIToolVariable returns a Variable whose value is the path to a host tool
// in the lib directory for host targets. It may only be called during a Go
// package's initialization - either from the init() function or as part of a
diff --git a/android/paths.go b/android/paths.go
index 82c8a24..e68106c 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1661,6 +1661,12 @@
return makePathForInstall(ctx, os, arch, partition, ctx.Debug(), pathComponents...)
}
+// PathForHostDexInstall returns an InstallPath representing the install path for the
+// module appended with paths...
+func PathForHostDexInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
+ return makePathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", ctx.Debug(), pathComponents...)
+}
+
// PathForModuleInPartitionInstall is similar to PathForModuleInstall but partition is provided by the caller
func PathForModuleInPartitionInstall(ctx ModuleInstallPathContext, partition string, pathComponents ...string) InstallPath {
os, arch := osAndArch(ctx)
@@ -2058,7 +2064,12 @@
// Writes a file to the output directory. Attempting to write directly to the output directory
// will fail due to the sandbox of the soong_build process.
func WriteFileToOutputDir(path WritablePath, data []byte, perm os.FileMode) error {
- return ioutil.WriteFile(absolutePath(path.String()), data, perm)
+ absPath := absolutePath(path.String())
+ err := os.MkdirAll(filepath.Dir(absPath), 0777)
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(absPath, data, perm)
}
func RemoveAllOutputDir(path WritablePath) error {
diff --git a/android/paths_test.go b/android/paths_test.go
index 3f4625d..3cad852 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -993,7 +993,7 @@
{
name: "in out dir",
buildDir: "out",
- src: "out/a/b/c",
+ src: "out/soong/a/b/c",
err: "is in output",
},
}
@@ -1525,7 +1525,7 @@
fmt.Println(p.Rel(), p2.Rel())
// Output:
- // out/system/framework/boot.art out/system/framework/boot.oat
+ // out/soong/system/framework/boot.art out/soong/system/framework/boot.oat
// boot.art boot.oat
}
@@ -1539,7 +1539,7 @@
fmt.Println(p.Rel(), p2.Rel())
// Output:
- // out/system/framework/boot.art out/system/framework/oat/arm/boot.vdex
+ // out/soong/system/framework/boot.art out/soong/system/framework/oat/arm/boot.vdex
// boot.art oat/arm/boot.vdex
}
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index feee90f..3766bb0 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -64,10 +64,10 @@
fmt.Printf("outputs: %q\n", rule.Outputs())
// Output:
- // commands: "ld a.o b.o -o out/linked && echo success"
+ // commands: "ld a.o b.o -o out/soong/linked && echo success"
// tools: ["ld"]
// inputs: ["a.o" "b.o"]
- // outputs: ["out/linked"]
+ // outputs: ["out/soong/linked"]
}
func ExampleRuleBuilder_SymlinkOutputs() {
@@ -79,7 +79,7 @@
Tool(PathForSource(ctx, "ln")).
FlagWithInput("-s ", PathForTesting("a.o")).
SymlinkOutput(PathForOutput(ctx, "a"))
- rule.Command().Text("cp out/a out/b").
+ rule.Command().Text("cp out/soong/a out/soong/b").
ImplicitSymlinkOutput(PathForOutput(ctx, "b"))
fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
@@ -89,11 +89,11 @@
fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs())
// Output:
- // commands: "ln -s a.o out/a && cp out/a out/b"
+ // commands: "ln -s a.o out/soong/a && cp out/soong/a out/soong/b"
// tools: ["ln"]
// inputs: ["a.o"]
- // outputs: ["out/a" "out/b"]
- // symlink_outputs: ["out/a" "out/b"]
+ // outputs: ["out/soong/a" "out/soong/b"]
+ // symlink_outputs: ["out/soong/a" "out/soong/b"]
}
func ExampleRuleBuilder_Temporary() {
@@ -117,10 +117,10 @@
fmt.Printf("outputs: %q\n", rule.Outputs())
// Output:
- // commands: "cp a out/b && cp out/b out/c"
+ // commands: "cp a out/soong/b && cp out/soong/b out/soong/c"
// tools: ["cp"]
// inputs: ["a"]
- // outputs: ["out/c"]
+ // outputs: ["out/soong/c"]
}
func ExampleRuleBuilder_DeleteTemporaryFiles() {
@@ -145,10 +145,10 @@
fmt.Printf("outputs: %q\n", rule.Outputs())
// Output:
- // commands: "cp a out/b && cp out/b out/c && rm -f out/b"
+ // commands: "cp a out/soong/b && cp out/soong/b out/soong/c && rm -f out/soong/b"
// tools: ["cp"]
// inputs: ["a"]
- // outputs: ["out/c"]
+ // outputs: ["out/soong/c"]
}
func ExampleRuleBuilder_Installs() {
@@ -168,7 +168,7 @@
fmt.Printf("rule.Installs().String() = %q\n", rule.Installs().String())
// Output:
- // rule.Installs().String() = "out/linked:/bin/linked out/linked:/sbin/linked"
+ // rule.Installs().String() = "out/soong/linked:/bin/linked out/soong/linked:/sbin/linked"
}
func ExampleRuleBuilderCommand() {
@@ -271,7 +271,7 @@
FlagWithRspFileInputList("@", PathForOutput(ctx, "foo.rsp"), PathsForTesting("a.java", "b.java")).
String())
// Output:
- // javac @out/foo.rsp
+ // javac @out/soong/foo.rsp
}
func ExampleRuleBuilderCommand_String() {
@@ -371,15 +371,15 @@
addCommands(rule)
wantCommands := []string{
- "out_local/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/module/depfile " +
- "FlagWithInput=input FlagWithOutput=out_local/module/output FlagWithRspFileInputList=out_local/rsp " +
- "Input out_local/module/Output out_local/module/SymlinkOutput Text Tool after command2 old cmd",
- "command2 out_local/module/depfile2 input2 out_local/module/output2 tool2",
- "command3 input3 out_local/module/output2 out_local/module/output3 input3 out_local/module/output2",
+ "out_local/soong/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/soong/module/depfile " +
+ "FlagWithInput=input FlagWithOutput=out_local/soong/module/output FlagWithRspFileInputList=out_local/soong/rsp " +
+ "Input out_local/soong/module/Output out_local/soong/module/SymlinkOutput Text Tool after command2 old cmd",
+ "command2 out_local/soong/module/depfile2 input2 out_local/soong/module/output2 tool2",
+ "command3 input3 out_local/soong/module/output2 out_local/soong/module/output3 input3 out_local/soong/module/output2",
}
- wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
- "out_local/module/DepFile out_local/module/depfile out_local/module/ImplicitDepFile out_local/module/depfile2"
+ wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer " +
+ "out_local/soong/module/DepFile out_local/soong/module/depfile out_local/soong/module/ImplicitDepFile out_local/soong/module/depfile2"
AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
@@ -403,13 +403,13 @@
wantCommands := []string{
"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
- "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
+ "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
"__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
- wantDepMergerCommand := "out_local/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
+ wantDepMergerCommand := "out_local/soong/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_SANDBOX_DIR__/out/DepFile __SBOX_SANDBOX_DIR__/out/depfile __SBOX_SANDBOX_DIR__/out/ImplicitDepFile __SBOX_SANDBOX_DIR__/out/depfile2"
AssertDeepEquals(t, "rule.Commands()", wantCommands, rule.Commands())
@@ -433,7 +433,7 @@
wantCommands := []string{
"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
- "FlagWithRspFileInputList=out_local/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
+ "FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
"__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 4f37fc3..80237fb 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -449,18 +449,23 @@
fmt.Fprintf(w, dist)
}
- distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
- distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisBackedByModuleFile.String())
- distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
+ if a.apisUsedByModuleFile.String() != "" {
+ goal := "apps_only"
+ distFile := a.apisUsedByModuleFile.String()
+ fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
+ " $(call dist-for-goals,%s,%s:ndk_apis_usedby_apex/$(notdir %s))\n"+
+ "endif\n",
+ goal, distFile, distFile)
+ }
+
+ if a.apisBackedByModuleFile.String() != "" {
+ goal := "apps_only"
+ distFile := a.apisBackedByModuleFile.String()
+ fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
+ " $(call dist-for-goals,%s,%s:ndk_apis_backedby_apex/$(notdir %s))\n"+
+ "endif\n",
+ goal, distFile, distFile)
+ }
}
}}
}
-
-func distCoverageFiles(w io.Writer, dir string, distfile string) {
- if distfile != "" {
- goal := "apps_only"
- fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
- " $(call dist-for-goals,%s,%s:%s/$(notdir %s))\n"+
- "endif\n", goal, distfile, dir, distfile)
- }
-}
diff --git a/apex/apex.go b/apex/apex.go
index 20660d3..33188cb 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -424,9 +424,8 @@
isCompressed bool
// Path of API coverage generate file
- nativeApisUsedByModuleFile android.ModuleOutPath
- nativeApisBackedByModuleFile android.ModuleOutPath
- javaApisUsedByModuleFile android.ModuleOutPath
+ apisUsedByModuleFile android.ModuleOutPath
+ apisBackedByModuleFile android.ModuleOutPath
// Collect the module directory for IDE info in java/jdeps.go.
modulePaths []string
diff --git a/apex/builder.go b/apex/builder.go
index 2e21ddf..e22d694 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -67,7 +67,6 @@
pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
pctx.HostBinToolVariable("make_erofs", "make_erofs")
pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
- pctx.HostBinToolVariable("dexdeps", "dexdeps")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
}
@@ -708,12 +707,12 @@
"readelf": "${config.ClangBin}/llvm-readelf",
},
})
- a.nativeApisUsedByModuleFile = apisUsedbyOutputFile
+ a.apisUsedByModuleFile = apisUsedbyOutputFile
- var nativeLibNames []string
+ var libNames []string
for _, f := range a.filesInfo {
if f.class == nativeSharedLib {
- nativeLibNames = append(nativeLibNames, f.stem())
+ libNames = append(libNames, f.stem())
}
}
apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
@@ -721,25 +720,9 @@
rule.Command().
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
Output(apisBackedbyOutputFile).
- Flags(nativeLibNames)
+ Flags(libNames)
rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
- a.nativeApisBackedByModuleFile = apisBackedbyOutputFile
-
- var javaLibOrApkPath []android.Path
- for _, f := range a.filesInfo {
- if f.class == javaSharedLib || f.class == app {
- javaLibOrApkPath = append(javaLibOrApkPath, f.builtFile)
- }
- }
- javaApiUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.xml")
- javaUsedByRule := android.NewRuleBuilder(pctx, ctx)
- javaUsedByRule.Command().
- Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")).
- BuiltTool("dexdeps").
- Output(javaApiUsedbyOutputFile).
- Inputs(javaLibOrApkPath)
- javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
- a.javaApisUsedByModuleFile = javaApiUsedbyOutputFile
+ a.apisBackedByModuleFile = apisBackedbyOutputFile
bundleConfig := a.buildBundleConfig(ctx)
diff --git a/apex/testing.go b/apex/testing.go
index 337c862..69bd73e 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -24,7 +24,6 @@
android.MockFS{
// Needed by apex.
"system/core/rootdir/etc/public.libraries.android.txt": nil,
- "build/soong/scripts/gen_java_usedby_apex.sh": nil,
"build/soong/scripts/gen_ndk_backedby_apex.sh": nil,
// Needed by prebuilt_apex.
"build/soong/scripts/unpack-prebuilt-apex.sh": nil,
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 4c9f579..58489c2 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -3585,6 +3585,58 @@
}
}
+func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
+ for _, tc := range []struct {
+ name string
+ sdkVersion string
+ variant string
+ expected string
+ }{
+ {
+ name: "default is current",
+ sdkVersion: "",
+ variant: "android_arm64_armv8-a_static",
+ expected: "platform_apis",
+ },
+ {
+ name: "use sdk_version",
+ sdkVersion: `sdk_version: "29"`,
+ variant: "android_arm64_armv8-a_static",
+ expected: "platform_apis",
+ },
+ {
+ name: "use sdk_version(sdk variant)",
+ sdkVersion: `sdk_version: "29"`,
+ variant: "android_arm64_armv8-a_sdk_static",
+ expected: "29",
+ },
+ {
+ name: "use min_sdk_version",
+ sdkVersion: `min_sdk_version: "29"`,
+ variant: "android_arm64_armv8-a_static",
+ expected: "29",
+ },
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library {
+ name: "libfoo",
+ stl: "none",
+ srcs: ["a/Foo.aidl"],
+ `+tc.sdkVersion+`
+ }
+ `)
+ libfoo := ctx.ModuleForTests("libfoo", tc.variant)
+ manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+ aidlCommand := manifest.Commands[0].GetCommand()
+ expectedAidlFlag := "--min_sdk_version=" + tc.expected
+ if !strings.Contains(aidlCommand, expectedAidlFlag) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+ }
+ })
+ }
+}
+
func TestMinSdkVersionInClangTriple(t *testing.T) {
ctx := testCc(t, `
cc_library_shared {
diff --git a/cc/compiler.go b/cc/compiler.go
index 00df669..ffe8b2e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -552,6 +552,12 @@
flags.aidlFlags = append(flags.aidlFlags, "-t")
}
+ aidlMinSdkVersion := ctx.minSdkVersion()
+ if aidlMinSdkVersion == "" {
+ aidlMinSdkVersion = "platform_apis"
+ }
+ flags.aidlFlags = append(flags.aidlFlags, "--min_sdk_version="+aidlMinSdkVersion)
+
flags.Local.CommonFlags = append(flags.Local.CommonFlags,
"-I"+android.PathForModuleGen(ctx, "aidl").String())
}
diff --git a/compliance/build_license_metadata/build_license_metadata.go b/compliance/build_license_metadata/build_license_metadata.go
index ba3cc3e..8b1fe58 100644
--- a/compliance/build_license_metadata/build_license_metadata.go
+++ b/compliance/build_license_metadata/build_license_metadata.go
@@ -119,7 +119,7 @@
for _, installMap := range installMaps {
components := strings.Split(installMap, ":")
if len(components) != 2 {
- panic(fmt.Errorf("install map entry %q contains %d colons, expected 1", len(components)-1))
+ panic(fmt.Errorf("install map entry %q contains %d colons, expected 1", installMap, len(components)-1))
}
ret = append(ret, &license_metadata_proto.InstallMap{
FromPath: proto.String(components[0]),
@@ -140,7 +140,7 @@
dep := components[0]
components = components[1:]
ad := &license_metadata_proto.AnnotatedDependency{
- File: proto.String(dep),
+ File: proto.String(dep),
Annotations: make([]string, 0, len(components)),
}
for _, ann := range components {
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index d81ac2c..4a3d390 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -115,16 +115,16 @@
// Test that class loader context structure is correct.
t.Run("string", func(t *testing.T) {
wantStr := " --host-context-for-sdk 29 " +
- "PCL[out/" + AndroidHidlManager + ".jar]#" +
- "PCL[out/" + AndroidHidlBase + ".jar]" +
+ "PCL[out/soong/" + AndroidHidlManager + ".jar]#" +
+ "PCL[out/soong/" + AndroidHidlBase + ".jar]" +
" --target-context-for-sdk 29 " +
"PCL[/system/framework/" + AndroidHidlManager + ".jar]#" +
"PCL[/system/framework/" + AndroidHidlBase + ".jar]" +
" --host-context-for-sdk any " +
- "PCL[out/a.jar]#PCL[out/b.jar]#PCL[out/c.jar]#PCL[out/d.jar]" +
- "{PCL[out/a2.jar]#PCL[out/b2.jar]#PCL[out/c2.jar]" +
- "{PCL[out/a1.jar]#PCL[out/b1.jar]}}#" +
- "PCL[out/f.jar]#PCL[out/a3.jar]#PCL[out/b3.jar]" +
+ "PCL[out/soong/a.jar]#PCL[out/soong/b.jar]#PCL[out/soong/c.jar]#PCL[out/soong/d.jar]" +
+ "{PCL[out/soong/a2.jar]#PCL[out/soong/b2.jar]#PCL[out/soong/c2.jar]" +
+ "{PCL[out/soong/a1.jar]#PCL[out/soong/b1.jar]}}#" +
+ "PCL[out/soong/f.jar]#PCL[out/soong/a3.jar]#PCL[out/soong/b3.jar]" +
" --target-context-for-sdk any " +
"PCL[/system/a.jar]#PCL[/system/b.jar]#PCL[/system/c.jar]#PCL[/system/d.jar]" +
"{PCL[/system/a2.jar]#PCL[/system/b2.jar]#PCL[/system/c2.jar]" +
@@ -138,11 +138,11 @@
// Test that all expected build paths are gathered.
t.Run("paths", func(t *testing.T) {
wantPaths := []string{
- "out/android.hidl.manager-V1.0-java.jar", "out/android.hidl.base-V1.0-java.jar",
- "out/a.jar", "out/b.jar", "out/c.jar", "out/d.jar",
- "out/a2.jar", "out/b2.jar", "out/c2.jar",
- "out/a1.jar", "out/b1.jar",
- "out/f.jar", "out/a3.jar", "out/b3.jar",
+ "out/soong/android.hidl.manager-V1.0-java.jar", "out/soong/android.hidl.base-V1.0-java.jar",
+ "out/soong/a.jar", "out/soong/b.jar", "out/soong/c.jar", "out/soong/d.jar",
+ "out/soong/a2.jar", "out/soong/b2.jar", "out/soong/c2.jar",
+ "out/soong/a1.jar", "out/soong/b1.jar",
+ "out/soong/f.jar", "out/soong/a3.jar", "out/soong/b3.jar",
}
if !reflect.DeepEqual(wantPaths, havePaths.Strings()) {
t.Errorf("\nwant paths: %s\nhave paths: %s", wantPaths, havePaths)
@@ -270,13 +270,13 @@
// Test that class loader context structure is correct.
t.Run("string", func(t *testing.T) {
- wantStr := " --host-context-for-sdk 30 PCL[out/c.jar]" +
+ wantStr := " --host-context-for-sdk 30 PCL[out/soong/c.jar]" +
" --target-context-for-sdk 30 PCL[/system/c.jar]" +
- " --host-context-for-sdk 29 PCL[out/b.jar]" +
+ " --host-context-for-sdk 29 PCL[out/soong/b.jar]" +
" --target-context-for-sdk 29 PCL[/system/b.jar]" +
- " --host-context-for-sdk 28 PCL[out/a.jar]" +
+ " --host-context-for-sdk 28 PCL[out/soong/a.jar]" +
" --target-context-for-sdk 28 PCL[/system/a.jar]" +
- " --host-context-for-sdk any PCL[out/d.jar]" +
+ " --host-context-for-sdk any PCL[out/soong/d.jar]" +
" --target-context-for-sdk any PCL[/system/d.jar]"
if wantStr != haveStr {
t.Errorf("\nwant class loader context: %s\nhave class loader context: %s", wantStr, haveStr)
diff --git a/java/androidmk.go b/java/androidmk.go
index eca5caa..35b4c8e 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -285,11 +285,6 @@
}}
} else {
outputFile := binary.wrapperFile
- // Have Make installation trigger Soong installation by using Soong's install path as
- // the output file.
- if binary.Host() {
- outputFile = binary.binaryFile
- }
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "EXECUTABLES",
diff --git a/java/app.go b/java/app.go
index 6554d66..7c195fc 100755
--- a/java/app.go
+++ b/java/app.go
@@ -721,10 +721,12 @@
// Install the app package.
if (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() {
- ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile)
+ var extraInstalledPaths android.Paths
for _, extra := range a.extraOutputFiles {
- ctx.InstallFile(a.installDir, extra.Base(), extra)
+ installed := ctx.InstallFile(a.installDir, extra.Base(), extra)
+ extraInstalledPaths = append(extraInstalledPaths, installed)
}
+ ctx.InstallFile(a.installDir, a.outputFile.Base(), a.outputFile, extraInstalledPaths...)
}
a.buildAppDependencyInfo(ctx)
diff --git a/java/app_import.go b/java/app_import.go
index 3e5f972..4d1969e 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -108,6 +108,8 @@
return true
}
+func (a *AndroidAppImport) InstallBypassMake() bool { return true }
+
// Updates properties with variant-specific values.
func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
config := ctx.Config()
diff --git a/java/base.go b/java/base.go
index ca34f2e..859baaf 100644
--- a/java/base.go
+++ b/java/base.go
@@ -784,6 +784,9 @@
flags = append(flags, "--transaction_names")
}
+ aidlMinSdkVersion := j.MinSdkVersion(ctx).ApiLevel.String()
+ flags = append(flags, "--min_sdk_version="+aidlMinSdkVersion)
+
return strings.Join(flags, " "), deps
}
diff --git a/java/config/config.go b/java/config/config.go
index 92d49a6..30c6f91 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -124,8 +124,8 @@
pctx.HostBinToolVariable("Zip2ZipCmd", "zip2zip")
pctx.HostBinToolVariable("ZipSyncCmd", "zipsync")
pctx.HostBinToolVariable("ApiCheckCmd", "apicheck")
- pctx.HostJavaBinToolVariable("D8Cmd", "d8")
- pctx.HostJavaBinToolVariable("R8Cmd", "r8-compat-proguard")
+ pctx.HostBinToolVariable("D8Cmd", "d8")
+ pctx.HostBinToolVariable("R8Cmd", "r8-compat-proguard")
pctx.HostBinToolVariable("HiddenAPICmd", "hiddenapi")
pctx.HostBinToolVariable("ExtractApksCmd", "extract_apks")
pctx.VariableFunc("TurbineJar", func(ctx android.PackageVarContext) string {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index e9dc982..8ab5a45 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -335,17 +335,19 @@
dexpreoptRule.Build("dexpreopt", "dexpreopt")
- if global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) {
- // APEX variants of java libraries are hidden from Make, so their dexpreopt outputs need special
- // handling. Currently, for APEX variants of java libraries, only those in the system server
- // classpath are handled here. Preopting of boot classpath jars in the ART APEX are handled in
- // java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
- for _, install := range dexpreoptRule.Installs() {
- // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
- installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
- installBase := filepath.Base(install.To)
- arch := filepath.Base(installDir)
- installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
+ for _, install := range dexpreoptRule.Installs() {
+ // Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
+ installDir := strings.TrimPrefix(filepath.Dir(install.To), "/")
+ installBase := filepath.Base(install.To)
+ arch := filepath.Base(installDir)
+ installPath := android.PathForModuleInPartitionInstall(ctx, "", installDir)
+
+ if global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) {
+ // APEX variants of java libraries are hidden from Make, so their dexpreopt
+ // outputs need special handling. Currently, for APEX variants of java
+ // libraries, only those in the system server classpath are handled here.
+ // Preopting of boot classpath jars in the ART APEX are handled in
+ // java/dexpreopt_bootjars.go, and other APEX jars are not preopted.
// The installs will be handled by Make as sub-modules of the java library.
d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
name: arch + "-" + installBase,
@@ -354,10 +356,12 @@
installDirOnDevice: installPath,
installFileOnDevice: installBase,
})
+ } else {
+ ctx.InstallFile(installPath, installBase, install.From)
}
- } else {
- // The installs will be handled by Make as LOCAL_SOONG_BUILT_INSTALLED of the java library
- // module.
+ }
+
+ if !global.ApexSystemServerJars.ContainsJar(moduleName(ctx)) {
d.builtInstalled = dexpreoptRule.Installs().String()
}
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 869a598..c84a15c 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -769,8 +769,8 @@
d.Javadoc.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip")
- jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar")
- doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar")
+ jsilver := ctx.Config().HostJavaToolPath(ctx, "jsilver.jar")
+ doclava := ctx.Config().HostJavaToolPath(ctx, "doclava.jar")
outDir := android.PathForModuleOut(ctx, "out")
srcJarDir := android.PathForModuleOut(ctx, "srcjars")
diff --git a/java/java.go b/java/java.go
index 854097b..3bb9a92 100644
--- a/java/java.go
+++ b/java/java.go
@@ -265,6 +265,8 @@
return j.kytheFiles
}
+func (j *Module) InstallBypassMake() bool { return true }
+
type dependencyTag struct {
blueprint.BaseDependencyTag
name string
@@ -567,8 +569,22 @@
if j.InstallMixin != nil {
extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
}
- j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
- j.Stem()+".jar", j.outputFile, extraInstallDeps...)
+ hostDexNeeded := Bool(j.deviceProperties.Hostdex) && !ctx.Host()
+ if hostDexNeeded {
+ ctx.InstallFile(android.PathForHostDexInstall(ctx, "framework"),
+ j.Stem()+"-hostdex.jar", j.outputFile)
+ }
+ var installDir android.InstallPath
+ if ctx.InstallInTestcases() {
+ var archDir string
+ if !ctx.Host() {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ }
+ j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
}
@@ -842,6 +858,20 @@
dexJarFile android.Path
}
+func (j *Test) InstallInTestcases() bool {
+ // Host java tests install into $(HOST_OUT_JAVA_LIBRARIES), and then are copied into
+ // testcases by base_rules.mk.
+ return !j.Host()
+}
+
+func (j *TestHelperLibrary) InstallInTestcases() bool {
+ return true
+}
+
+func (j *JavaTestImport) InstallInTestcases() bool {
+ return true
+}
+
func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
if len(j.testHostProperties.Data_native_bins) > 0 {
for _, target := range ctx.MultiTargets() {
@@ -1376,8 +1406,17 @@
})
if Bool(j.properties.Installable) {
- ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
- jarName, outputFile)
+ var installDir android.InstallPath
+ if ctx.InstallInTestcases() {
+ var archDir string
+ if !ctx.Host() {
+ archDir = ctx.DeviceConfig().DeviceArch()
+ }
+ installDir = android.PathForModuleInstall(ctx, ctx.ModuleName(), archDir)
+ } else {
+ installDir = android.PathForModuleInstall(ctx, "framework")
+ }
+ ctx.InstallFile(installDir, jarName, outputFile)
}
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.properties.Aidl.Export_include_dirs)
diff --git a/java/java_test.go b/java/java_test.go
index bc9b409..c039f72 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1357,6 +1357,36 @@
}
}
+func TestAidlFlagsWithMinSdkVersion(t *testing.T) {
+ fixture := android.GroupFixturePreparers(
+ prepareForJavaTest, FixtureWithPrebuiltApis(map[string][]string{"14": {"foo"}}))
+
+ for _, tc := range []struct {
+ name string
+ sdkVersion string
+ expected string
+ }{
+ {"default is current", "", "current"},
+ {"use sdk_version", `sdk_version: "14"`, "14"},
+ {"system_current", `sdk_version: "system_current"`, "current"},
+ } {
+ t.Run(tc.name, func(t *testing.T) {
+ ctx := fixture.RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["aidl/foo/IFoo.aidl"],
+ `+tc.sdkVersion+`
+ }
+ `)
+ aidlCommand := ctx.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+ expectedAidlFlag := "--min_sdk_version=" + tc.expected
+ if !strings.Contains(aidlCommand, expectedAidlFlag) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+ }
+ })
+ }
+}
+
func TestDataNativeBinaries(t *testing.T) {
ctx, _ := testJava(t, `
java_test_host {
diff --git a/mk2rbc/cmd/mk2rbc.go b/mk2rbc/cmd/mk2rbc.go
index 25507d2..0f030d3 100644
--- a/mk2rbc/cmd/mk2rbc.go
+++ b/mk2rbc/cmd/mk2rbc.go
@@ -46,7 +46,7 @@
dryRun = flag.Bool("dry_run", false, "dry run")
recurse = flag.Bool("convert_dependents", false, "convert all dependent files")
mode = flag.String("mode", "", `"backup" to back up existing files, "write" to overwrite them`)
- warn = flag.Bool("warnings", false, "warn about partially failed conversions")
+ noWarn = flag.Bool("no_warnings", false, "don't warn about partially failed conversions")
verbose = flag.Bool("v", false, "print summary")
errstat = flag.Bool("error_stat", false, "print error statistics")
traceVar = flag.String("trace", "", "comma-separated list of variables to trace")
@@ -75,7 +75,7 @@
flagAlias("root", "d")
flagAlias("dry_run", "n")
flagAlias("convert_dependents", "r")
- flagAlias("warnings", "w")
+ flagAlias("no_warnings", "w")
flagAlias("error_stat", "e")
}
@@ -336,7 +336,7 @@
OutputSuffix: *suffix,
TracedVariables: tracedVariables,
TraceCalls: *traceCalls,
- WarnPartialSuccess: *warn,
+ WarnPartialSuccess: !*noWarn,
SourceFS: os.DirFS(*rootDir),
MakefileFinder: makefileFinder,
}
@@ -419,7 +419,7 @@
func printStats() {
var sortedFiles []string
- if !*warn && !*verbose {
+ if *noWarn && !*verbose {
return
}
for p := range converted {
@@ -437,7 +437,7 @@
nOk++
}
}
- if *warn {
+ if !*noWarn {
if nPartial > 0 {
fmt.Fprintf(os.Stderr, "Conversion was partially successful for:\n")
for _, f := range sortedFiles {
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 2aac40e..55835c1 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -72,6 +72,7 @@
soongConfigVarSetOld = "add_soong_config_var_value"
soongConfigAppend = "soong_config_append"
soongConfigAssign = "soong_config_set"
+ soongConfigGet = "soong_config_get"
wildcardExistsPhony = "$wildcard_exists"
)
@@ -95,6 +96,7 @@
soongConfigVarSetOld: {baseName + ".soong_config_set", starlarkTypeVoid, hiddenArgGlobal},
soongConfigAssign: {baseName + ".soong_config_set", starlarkTypeVoid, hiddenArgGlobal},
soongConfigAppend: {baseName + ".soong_config_append", starlarkTypeVoid, hiddenArgGlobal},
+ soongConfigGet: {baseName + ".soong_config_get", starlarkTypeString, hiddenArgGlobal},
"add-to-product-copy-files-if-exists": {baseName + ".copy_if_exists", starlarkTypeList, hiddenArgNone},
"addprefix": {baseName + ".addprefix", starlarkTypeList, hiddenArgNone},
"addsuffix": {baseName + ".addsuffix", starlarkTypeList, hiddenArgNone},
@@ -538,7 +540,7 @@
return
}
name := a.Name.Strings[0]
- // Soong confuguration
+ // Soong configuration
if strings.HasPrefix(name, soongNsPrefix) {
ctx.handleSoongNsAssignment(strings.TrimPrefix(name, soongNsPrefix), a)
return
@@ -639,7 +641,7 @@
// Upon seeing
// SOONG_CONFIG_x_y = v
// find a namespace called `x` and act as if we encountered
- // $(call add_config_var_value(x,y,v)
+ // $(call soong_config_set,x,y,v)
// or check that `x_y` is a namespace, and then add the RHS of this assignment as variables in
// it.
// Emit an error in the ambiguous situation (namespaces `foo_bar` with a variable `baz`
@@ -680,7 +682,7 @@
ctx.errorf(asgn, "no %s variable in %s namespace, please use add_soong_config_var_value instead", varName, namespaceName)
return
}
- fname := soongConfigVarSetOld
+ fname := soongConfigAssign
if asgn.Type == "+=" {
fname = soongConfigAppend
}
@@ -1322,7 +1324,7 @@
}
if strings.HasPrefix(refDump, soongNsPrefix) {
// TODO (asmundak): if we find many, maybe handle them.
- return ctx.newBadExpr(node, "SOONG_CONFIG_ variables cannot be referenced: %s", refDump)
+ return ctx.newBadExpr(node, "SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: %s", refDump)
}
if v := ctx.addVariable(refDump); v != nil {
return &variableRefExpr{v, ctx.lastAssignment(v.name()) != nil}
@@ -1388,11 +1390,14 @@
if len(words) != 3 {
return ctx.newBadExpr(node, "%s function should have 3 arguments", fname)
}
- if !words[0].Const() || !words[1].Const() {
- return ctx.newBadExpr(node, "%s function's from and to arguments should be constant", fname)
+ from := ctx.parseMakeString(node, words[0])
+ if xBad, ok := from.(*badExpr); ok {
+ return xBad
}
- from := words[0].Strings[0]
- to := words[1].Strings[0]
+ to := ctx.parseMakeString(node, words[1])
+ if xBad, ok := to.(*badExpr); ok {
+ return xBad
+ }
words[2].TrimLeftSpaces()
words[2].TrimRightSpaces()
obj := ctx.parseMakeString(node, words[2])
@@ -1402,13 +1407,13 @@
return &callExpr{
object: obj,
name: "replace",
- args: []starlarkExpr{&stringLiteralExpr{from}, &stringLiteralExpr{to}},
+ args: []starlarkExpr{from, to},
returnType: typ,
}
}
return &callExpr{
name: fname,
- args: []starlarkExpr{&stringLiteralExpr{from}, &stringLiteralExpr{to}, obj},
+ args: []starlarkExpr{from, to, obj},
returnType: obj.typ(),
}
}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 083d0bc..80a482f 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -226,6 +226,9 @@
PRODUCT_NAME = gizmo
else
endif
+local_var :=
+ifdef local_var
+endif
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
@@ -235,6 +238,9 @@
cfg["PRODUCT_NAME"] = "gizmo"
else:
pass
+ _local_var = ""
+ if _local_var:
+ pass
`,
},
{
@@ -691,7 +697,7 @@
PRODUCT_COPY_FILES := $(addprefix pfx-,a b c)
PRODUCT_COPY_FILES := $(addsuffix .sff, a b c)
PRODUCT_NAME := $(word 1, $(subst ., ,$(TARGET_BOARD_PLATFORM)))
-$(info $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS)))
+$(info $(patsubst %.pub,$(PRODUCT_NAME)%,$(PRODUCT_ADB_KEYS)))
$(info $(dir foo/bar))
$(info $(firstword $(PRODUCT_COPY_FILES)))
$(info $(lastword $(PRODUCT_COPY_FILES)))
@@ -714,7 +720,7 @@
cfg["PRODUCT_COPY_FILES"] = rblf.addprefix("pfx-", "a b c")
cfg["PRODUCT_COPY_FILES"] = rblf.addsuffix(".sff", "a b c")
cfg["PRODUCT_NAME"] = ((g.get("TARGET_BOARD_PLATFORM", "")).replace(".", " ")).split()[0]
- rblf.mkinfo("product.mk", rblf.mkpatsubst("%.pub", "%", g.get("PRODUCT_ADB_KEYS", "")))
+ rblf.mkinfo("product.mk", rblf.mkpatsubst("%.pub", "%s%%" % cfg["PRODUCT_NAME"], g.get("PRODUCT_ADB_KEYS", "")))
rblf.mkinfo("product.mk", rblf.dir("foo/bar"))
rblf.mkinfo("product.mk", cfg["PRODUCT_COPY_FILES"][0])
rblf.mkinfo("product.mk", cfg["PRODUCT_COPY_FILES"][-1])
@@ -821,10 +827,30 @@
rblf.soong_config_namespace(g, "cvd")
rblf.soong_config_set(g, "cvd", "launch_configs", "cvd_config_auto.json")
rblf.soong_config_append(g, "cvd", "grub_config", "grub.cfg")
- # MK2RBC TRANSLATION ERROR: SOONG_CONFIG_ variables cannot be referenced: SOONG_CONFIG_cvd_grub_config
+ # MK2RBC TRANSLATION ERROR: SOONG_CONFIG_ variables cannot be referenced, use soong_config_get instead: SOONG_CONFIG_cvd_grub_config
# x := $(SOONG_CONFIG_cvd_grub_config)
rblf.warning("product.mk", "partially successful conversion")
`,
+ }, {
+ desc: "soong namespace accesses",
+ mkname: "product.mk",
+ in: `
+SOONG_CONFIG_NAMESPACES += cvd
+SOONG_CONFIG_cvd += launch_configs
+SOONG_CONFIG_cvd_launch_configs = cvd_config_auto.json
+SOONG_CONFIG_cvd += grub_config
+SOONG_CONFIG_cvd_grub_config += grub.cfg
+x := $(call soong_config_get,cvd,grub_config)
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ rblf.soong_config_namespace(g, "cvd")
+ rblf.soong_config_set(g, "cvd", "launch_configs", "cvd_config_auto.json")
+ rblf.soong_config_append(g, "cvd", "grub_config", "grub.cfg")
+ _x = rblf.soong_config_get(g, "cvd", "grub_config")
+`,
},
{
desc: "string split",
diff --git a/mk2rbc/variable.go b/mk2rbc/variable.go
index 4bb9ed5..ded07fe 100644
--- a/mk2rbc/variable.go
+++ b/mk2rbc/variable.go
@@ -177,8 +177,8 @@
baseVariable
}
-func (lv localVariable) emitDefined(_ *generationContext) {
- panic("implement me")
+func (lv localVariable) emitDefined(gctx *generationContext) {
+ gctx.writef(lv.String())
}
func (lv localVariable) String() string {
diff --git a/rust/bindgen.go b/rust/bindgen.go
index 845f258..32d02e4 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -15,6 +15,7 @@
package rust
import (
+ "fmt"
"strings"
"github.com/google/blueprint"
@@ -147,6 +148,31 @@
cflags = append(cflags, strings.ReplaceAll(ccToolchain.Cflags(), "${config.", "${cc_config."))
cflags = append(cflags, strings.ReplaceAll(ccToolchain.ToolchainCflags(), "${config.", "${cc_config."))
+ if ctx.RustModule().UseVndk() {
+ cflags = append(cflags, "-D__ANDROID_VNDK__")
+ if ctx.RustModule().InVendor() {
+ cflags = append(cflags, "-D__ANDROID_VENDOR__")
+ } else if ctx.RustModule().InProduct() {
+ cflags = append(cflags, "-D__ANDROID_PRODUCT__")
+ }
+ }
+
+ if ctx.RustModule().InRecovery() {
+ cflags = append(cflags, "-D__ANDROID_RECOVERY__")
+ }
+
+ if mctx, ok := ctx.(*moduleContext); ok && mctx.apexVariationName() != "" {
+ cflags = append(cflags, "-D__ANDROID_APEX__")
+ if ctx.Device() {
+ cflags = append(cflags, fmt.Sprintf("-D__ANDROID_APEX_MIN_SDK_VERSION__=%d",
+ ctx.RustModule().apexSdkVersion.FinalOrFutureInt()))
+ }
+ }
+
+ if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ cflags = append(cflags, "-D__ANDROID_NATIVE_BRIDGE__")
+ }
+
// Dependency clang flags and include paths
cflags = append(cflags, deps.depClangFlags...)
for _, include := range deps.depIncludePaths {
diff --git a/rust/rust.go b/rust/rust.go
index 7c8e80b..b3e543e 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -162,6 +162,9 @@
docTimestampFile android.OptionalPath
hideApexVariantFromMake bool
+
+ // For apex variants, this is set as apex.min_sdk_version
+ apexSdkVersion android.ApiLevel
}
func (mod *Module) Header() bool {
@@ -675,6 +678,10 @@
return mod.OutputFile().Valid() && !mod.Properties.PreventInstall
}
+func (ctx moduleContext) apexVariationName() string {
+ return ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).ApexVariationName
+}
+
var _ cc.LinkableInterface = (*Module)(nil)
func (mod *Module) Init() android.Module {
@@ -1023,6 +1030,20 @@
directSrcProvidersDeps := []*Module{}
directSrcDeps := [](android.SourceFileProducer){}
+ // For the dependency from platform to apex, use the latest stubs
+ mod.apexSdkVersion = android.FutureApiLevel
+ apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ mod.apexSdkVersion = apexInfo.MinSdkVersion
+ }
+
+ if android.InList("hwaddress", ctx.Config().SanitizeDevice()) {
+ // In hwasan build, we override apexSdkVersion to the FutureApiLevel(10000)
+ // so that even Q(29/Android10) apexes could use the dynamic unwinder by linking the newer stubs(e.g libc(R+)).
+ // (b/144430859)
+ mod.apexSdkVersion = android.FutureApiLevel
+ }
+
ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep)
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 88787cd..1830a18 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -3,4 +3,4 @@
per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file construct_context.py = ngeoffray@google.com,calin@google.com,skvadrik@google.com
per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
-per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com
\ No newline at end of file
+per-file gen_ndk*.sh = sophiez@google.com, allenhair@google.com
diff --git a/scripts/gen_java_usedby_apex.sh b/scripts/gen_java_usedby_apex.sh
deleted file mode 100755
index 73e3dfb..0000000
--- a/scripts/gen_java_usedby_apex.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash -e
-
-# Copyright 2020 Google Inc. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-printHelp() {
- echo "**************************** Usage Instructions ****************************"
- echo "This script is used to generate the Mainline modules used-by Java symbols."
- echo ""
- echo "To run this script use: ./gen_java_usedby_apex.sh \$BINARY_DEXDEPS_PATH \$OUTPUT_FILE_PATH \$JAR_AND_APK_LIST"
- echo "For example: If all jar and apk files are '/myJar.jar /myApk.apk' and output write to /myModule.txt then the command would be:"
- echo "./gen_java_usedby_apex.sh \$BINARY_DEXDEPS_PATH /myModule.txt /myJar.jar /myApk.apk"
-}
-
-genUsedByList() {
- dexdeps="$1"
- shift
- out="$1"
- shift
- rm -f "$out"
- touch "$out"
- for x in "$@"; do
- "$dexdeps" "$x" >> "$out"
- done
-}
-
-if [[ "$1" == "help" ]]
-then
- printHelp
-elif [[ "$#" -lt 2 ]]
-then
- echo "Wrong argument length. Expecting at least 2 argument representing dexdeps path, output path, followed by a list of jar or apk files in the Mainline module."
-else
- genUsedByList "$@"
-fi
\ No newline at end of file
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index bf97b88..d5033ef 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -275,6 +275,9 @@
s.generateAndroidBuildActions(ctx)
installDir := android.PathForModuleInstall(ctx, "bin", proptools.String(s.properties.Sub_dir))
s.installedFile = ctx.InstallExecutable(installDir, s.outputFilePath.Base(), s.outputFilePath)
+ for _, symlink := range s.Symlinks() {
+ ctx.InstallSymlink(installDir, symlink, s.installedFile)
+ }
}
func (s *ShBinary) AndroidMkEntries() []android.AndroidMkEntries {
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 83007be..86c8568 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -76,6 +76,9 @@
// out/build_date.txt is considered a "source file"
buildDatetimeFilePath := filepath.Join(outDir, "build_date.txt")
+ // bpglob is built explicitly using Microfactory
+ bpglob := filepath.Join(config.SoongOutDir(), "bpglob")
+
danglingRules := make(map[string]bool)
scanner := bufio.NewScanner(stdout)
@@ -88,7 +91,8 @@
if strings.HasPrefix(line, modulePathsDir) ||
line == variablesFilePath ||
line == dexpreoptConfigFilePath ||
- line == buildDatetimeFilePath {
+ line == buildDatetimeFilePath ||
+ line == bpglob {
// Leaf node is in one of Soong's bootstrap directories, which do not have
// full build rules in the primary build.ninja file.
continue