Merge "Emit error if expression cannot be evaluated to boolean during androidmk conversion"
diff --git a/android/androidmk.go b/android/androidmk.go
index dbf3aa8..a8153cc 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -236,8 +236,8 @@
}
}
- if amod.noticeFile.Valid() {
- a.SetString("LOCAL_NOTICE_FILE", amod.noticeFile.String())
+ if len(amod.noticeFiles) > 0 {
+ a.SetString("LOCAL_NOTICE_FILE", strings.Join(amod.noticeFiles.Strings(), " "))
}
if host {
diff --git a/android/config.go b/android/config.go
index 32e32ae..b2bda2a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -570,8 +570,8 @@
return String(c.productVariables.BuildId)
}
-func (c *config) BuildNumberFromFile() string {
- return String(c.productVariables.BuildNumberFromFile)
+func (c *config) BuildNumberFile(ctx PathContext) Path {
+ return PathForOutput(ctx, String(c.productVariables.BuildNumberFile))
}
// DeviceName returns the name of the current device target
diff --git a/android/module.go b/android/module.go
index 665a30f..1026bdf 100644
--- a/android/module.go
+++ b/android/module.go
@@ -172,6 +172,7 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
RequiredModuleNames() []string
HostRequiredModuleNames() []string
@@ -214,11 +215,12 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
SkipInstall()
ExportedToMake() bool
InitRc() Paths
VintfFragments() Paths
- NoticeFile() OptionalPath
+ NoticeFiles() Paths
AddProperties(props ...interface{})
GetProperties() []interface{}
@@ -242,6 +244,8 @@
RequiredModuleNames() []string
HostRequiredModuleNames() []string
TargetRequiredModuleNames() []string
+
+ filesToInstall() InstallPaths
}
// Qualified id for a module
@@ -643,9 +647,9 @@
primaryVisibilityProperty visibilityProperty
noAddressSanitizer bool
- installFiles Paths
+ installFiles InstallPaths
checkbuildFiles Paths
- noticeFile OptionalPath
+ noticeFiles Paths
// Used by buildTargetSingleton to create checkbuild and per-directory build targets
// Only set on the final variant of each module
@@ -849,22 +853,20 @@
return m.commonProperties.NamespaceExportedToMake
}
-func (m *ModuleBase) computeInstallDeps(
- ctx blueprint.ModuleContext) Paths {
+func (m *ModuleBase) computeInstallDeps(ctx blueprint.ModuleContext) InstallPaths {
- result := Paths{}
+ var result InstallPaths
// TODO(ccross): we need to use WalkDeps and have some way to know which dependencies require installation
- ctx.VisitDepsDepthFirstIf(isFileInstaller,
- func(m blueprint.Module) {
- fileInstaller := m.(fileInstaller)
- files := fileInstaller.filesToInstall()
- result = append(result, files...)
- })
+ ctx.VisitDepsDepthFirst(func(m blueprint.Module) {
+ if a, ok := m.(Module); ok {
+ result = append(result, a.filesToInstall()...)
+ }
+ })
return result
}
-func (m *ModuleBase) filesToInstall() Paths {
+func (m *ModuleBase) filesToInstall() InstallPaths {
return m.installFiles
}
@@ -900,12 +902,16 @@
return false
}
+func (m *ModuleBase) InstallForceOS() *OsType {
+ return nil
+}
+
func (m *ModuleBase) Owner() string {
return String(m.commonProperties.Owner)
}
-func (m *ModuleBase) NoticeFile() OptionalPath {
- return m.noticeFile
+func (m *ModuleBase) NoticeFiles() Paths {
+ return m.noticeFiles
}
func (m *ModuleBase) setImageVariation(variant string) {
@@ -948,8 +954,8 @@
}
func (m *ModuleBase) generateModuleTarget(ctx ModuleContext) {
- allInstalledFiles := Paths{}
- allCheckbuildFiles := Paths{}
+ var allInstalledFiles InstallPaths
+ var allCheckbuildFiles Paths
ctx.VisitAllModuleVariants(func(module Module) {
a := module.base()
allInstalledFiles = append(allInstalledFiles, a.installFiles...)
@@ -968,7 +974,7 @@
ctx.Build(pctx, BuildParams{
Rule: blueprint.Phony,
Output: name,
- Implicits: allInstalledFiles,
+ Implicits: allInstalledFiles.Paths(),
Default: !ctx.Config().EmbeddedInMake(),
})
deps = append(deps, name)
@@ -1151,12 +1157,25 @@
}
})
- notice := proptools.StringDefault(m.commonProperties.Notice, "NOTICE")
+ m.noticeFiles = make([]Path, 0)
+ optPath := OptionalPath{}
+ notice := proptools.StringDefault(m.commonProperties.Notice, "")
if module := SrcIsModule(notice); module != "" {
- m.noticeFile = ctx.ExpandOptionalSource(¬ice, "notice")
- } else {
+ optPath = ctx.ExpandOptionalSource(¬ice, "notice")
+ } else if notice != "" {
noticePath := filepath.Join(ctx.ModuleDir(), notice)
- m.noticeFile = ExistentPathForSource(ctx, noticePath)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ }
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ } else {
+ for _, notice = range []string{"LICENSE", "LICENCE", "NOTICE"} {
+ noticePath := filepath.Join(ctx.ModuleDir(), notice)
+ optPath = ExistentPathForSource(ctx, noticePath)
+ if optPath.Valid() {
+ m.noticeFiles = append(m.noticeFiles, optPath.Path())
+ }
+ }
}
m.module.GenerateAndroidBuildActions(ctx)
@@ -1296,8 +1315,8 @@
type moduleContext struct {
bp blueprint.ModuleContext
baseModuleContext
- installDeps Paths
- installFiles Paths
+ installDeps InstallPaths
+ installFiles InstallPaths
checkbuildFiles Paths
module Module
@@ -1703,6 +1722,10 @@
return m.module.InstallBypassMake()
}
+func (m *moduleContext) InstallForceOS() *OsType {
+ return m.module.InstallForceOS()
+}
+
func (m *moduleContext) skipInstall(fullInstallPath InstallPath) bool {
if m.module.base().commonProperties.SkipInstall {
return true
@@ -1746,7 +1769,7 @@
if !m.skipInstall(fullInstallPath) {
- deps = append(deps, m.installDeps...)
+ deps = append(deps, m.installDeps.Paths()...)
var implicitDeps, orderOnlyDeps Paths
@@ -1827,20 +1850,6 @@
m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
}
-type fileInstaller interface {
- filesToInstall() Paths
-}
-
-func isFileInstaller(m blueprint.Module) bool {
- _, ok := m.(fileInstaller)
- return ok
-}
-
-func isAndroidModule(m blueprint.Module) bool {
- _, ok := m.(Module)
- return ok
-}
-
func findStringInSlice(str string, slice []string) int {
for i, s := range slice {
if s == str {
diff --git a/android/paths.go b/android/paths.go
index 66725c6..8b373da 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -53,6 +53,7 @@
InstallInRecovery() bool
InstallInRoot() bool
InstallBypassMake() bool
+ InstallForceOS() *OsType
}
var _ ModuleInstallPathContext = ModuleContext(nil)
@@ -1205,22 +1206,40 @@
// PathForModuleInstall returns a Path representing the install path for the
// module appended with paths...
func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
+ os := ctx.Os()
+ if forceOS := ctx.InstallForceOS(); forceOS != nil {
+ os = *forceOS
+ }
+ partition := modulePartition(ctx, os)
+
+ ret := pathForInstall(ctx, os, partition, ctx.Debug(), pathComponents...)
+
+ if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
+ ret = ret.ToMakePath()
+ }
+
+ return ret
+}
+
+func pathForInstall(ctx PathContext, os OsType, partition string, debug bool,
+ pathComponents ...string) InstallPath {
+
var outPaths []string
- if ctx.Device() {
- partition := modulePartition(ctx)
+
+ if os.Class == Device {
outPaths = []string{"target", "product", ctx.Config().DeviceName(), partition}
} else {
- switch ctx.Os() {
+ switch os {
case Linux:
- outPaths = []string{"host", "linux-x86"}
+ outPaths = []string{"host", "linux-x86", partition}
case LinuxBionic:
// TODO: should this be a separate top level, or shared with linux-x86?
- outPaths = []string{"host", "linux_bionic-x86"}
+ outPaths = []string{"host", "linux_bionic-x86", partition}
default:
- outPaths = []string{"host", ctx.Os().String() + "-x86"}
+ outPaths = []string{"host", os.String() + "-x86", partition}
}
}
- if ctx.Debug() {
+ if debug {
outPaths = append([]string{"debug"}, outPaths...)
}
outPaths = append(outPaths, pathComponents...)
@@ -1231,9 +1250,6 @@
}
ret := InstallPath{basePath{path, ctx.Config(), ""}, ""}
- if ctx.InstallBypassMake() && ctx.Config().EmbeddedInMake() {
- ret = ret.ToMakePath()
- }
return ret
}
@@ -1253,47 +1269,76 @@
return "/" + rel
}
-func modulePartition(ctx ModuleInstallPathContext) string {
+func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
var partition string
- if ctx.InstallInData() {
- partition = "data"
- } else if ctx.InstallInTestcases() {
+ if ctx.InstallInTestcases() {
+ // "testcases" install directory can be used for host or device modules.
partition = "testcases"
- } else if ctx.InstallInRamdisk() {
- if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
- partition = "recovery/root/first_stage_ramdisk"
+ } else if os.Class == Device {
+ if ctx.InstallInData() {
+ partition = "data"
+ } else if ctx.InstallInRamdisk() {
+ if ctx.DeviceConfig().BoardUsesRecoveryAsBoot() {
+ partition = "recovery/root/first_stage_ramdisk"
+ } else {
+ partition = "ramdisk"
+ }
+ if !ctx.InstallInRoot() {
+ partition += "/system"
+ }
+ } else if ctx.InstallInRecovery() {
+ if ctx.InstallInRoot() {
+ partition = "recovery/root"
+ } else {
+ // the layout of recovery partion is the same as that of system partition
+ partition = "recovery/root/system"
+ }
+ } else if ctx.SocSpecific() {
+ partition = ctx.DeviceConfig().VendorPath()
+ } else if ctx.DeviceSpecific() {
+ partition = ctx.DeviceConfig().OdmPath()
+ } else if ctx.ProductSpecific() {
+ partition = ctx.DeviceConfig().ProductPath()
+ } else if ctx.SystemExtSpecific() {
+ partition = ctx.DeviceConfig().SystemExtPath()
+ } else if ctx.InstallInRoot() {
+ partition = "root"
} else {
- partition = "ramdisk"
+ partition = "system"
}
- if !ctx.InstallInRoot() {
- partition += "/system"
+ if ctx.InstallInSanitizerDir() {
+ partition = "data/asan/" + partition
}
- } else if ctx.InstallInRecovery() {
- if ctx.InstallInRoot() {
- partition = "recovery/root"
- } else {
- // the layout of recovery partion is the same as that of system partition
- partition = "recovery/root/system"
- }
- } else if ctx.SocSpecific() {
- partition = ctx.DeviceConfig().VendorPath()
- } else if ctx.DeviceSpecific() {
- partition = ctx.DeviceConfig().OdmPath()
- } else if ctx.ProductSpecific() {
- partition = ctx.DeviceConfig().ProductPath()
- } else if ctx.SystemExtSpecific() {
- partition = ctx.DeviceConfig().SystemExtPath()
- } else if ctx.InstallInRoot() {
- partition = "root"
- } else {
- partition = "system"
- }
- if ctx.InstallInSanitizerDir() {
- partition = "data/asan/" + partition
}
return partition
}
+type InstallPaths []InstallPath
+
+// Paths returns the InstallPaths as a Paths
+func (p InstallPaths) Paths() Paths {
+ if p == nil {
+ return nil
+ }
+ ret := make(Paths, len(p))
+ for i, path := range p {
+ ret[i] = path
+ }
+ return ret
+}
+
+// Strings returns the string forms of the install paths.
+func (p InstallPaths) Strings() []string {
+ if p == nil {
+ return nil
+ }
+ ret := make([]string, len(p))
+ for i, path := range p {
+ ret[i] = path.String()
+ }
+ return ret
+}
+
// validateSafePath validates a path that we trust (may contain ninja variables).
// Ensures that each path component does not attempt to leave its component.
func validateSafePath(pathComponents ...string) (string, error) {
diff --git a/android/paths_test.go b/android/paths_test.go
index 7a32026..f1908ac 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -205,6 +205,7 @@
inRamdisk bool
inRecovery bool
inRoot bool
+ forceOS *OsType
}
func (m moduleInstallPathContextImpl) Config() Config {
@@ -241,6 +242,10 @@
return false
}
+func (m moduleInstallPathContextImpl) InstallForceOS() *OsType {
+ return m.forceOS
+}
+
func pathTestConfig(buildDir string) Config {
return TestConfig(buildDir, nil, "", nil)
}
@@ -598,6 +603,40 @@
},
in: []string{"nativetest", "my_test"},
out: "target/product/test_device/data/asan/data/nativetest/my_test",
+ }, {
+ name: "device testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inTestcases: true,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "target/product/test_device/testcases/my_test/my_test_bin",
+ }, {
+ name: "host testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: hostTarget.Os,
+ target: hostTarget,
+ },
+ inTestcases: true,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
+ }, {
+ name: "forced host testcases",
+ ctx: &moduleInstallPathContextImpl{
+ baseModuleContext: baseModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
+ inTestcases: true,
+ forceOS: &Linux,
+ },
+ in: []string{"my_test", "my_test_bin"},
+ out: "host/linux-x86/testcases/my_test/my_test_bin",
},
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index b4f144a..9005f07 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -162,9 +162,10 @@
r.Command().Text("rm").Flag("-f").Outputs(temporariesList)
}
-// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take input paths, such
-// as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or RuleBuilderCommand.FlagWithInput. Inputs to a command
-// that are also outputs of another command in the same RuleBuilder are filtered out.
+// Inputs returns the list of paths that were passed to the RuleBuilderCommand methods that take
+// input paths, such as RuleBuilderCommand.Input, RuleBuilderComand.Implicit, or
+// RuleBuilderCommand.FlagWithInput. Inputs to a command that are also outputs of another command
+// in the same RuleBuilder are filtered out. The list is sorted and duplicates removed.
func (r *RuleBuilder) Inputs() Paths {
outputs := r.outputSet()
depFiles := r.depFileSet()
@@ -193,6 +194,28 @@
return inputList
}
+// OrderOnlys returns the list of paths that were passed to the RuleBuilderCommand.OrderOnly or
+// RuleBuilderCommand.OrderOnlys. The list is sorted and duplicates removed.
+func (r *RuleBuilder) OrderOnlys() Paths {
+ orderOnlys := make(map[string]Path)
+ for _, c := range r.commands {
+ for _, orderOnly := range c.orderOnlys {
+ orderOnlys[orderOnly.String()] = orderOnly
+ }
+ }
+
+ var orderOnlyList Paths
+ for _, orderOnly := range orderOnlys {
+ orderOnlyList = append(orderOnlyList, orderOnly)
+ }
+
+ sort.Slice(orderOnlyList, func(i, j int) bool {
+ return orderOnlyList[i].String() < orderOnlyList[j].String()
+ })
+
+ return orderOnlyList
+}
+
func (r *RuleBuilder) outputSet() map[string]WritablePath {
outputs := make(map[string]WritablePath)
for _, c := range r.commands {
@@ -203,8 +226,9 @@
return outputs
}
-// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take output paths, such
-// as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or RuleBuilderCommand.FlagWithInput.
+// Outputs returns the list of paths that were passed to the RuleBuilderCommand methods that take
+// output paths, such as RuleBuilderCommand.Output, RuleBuilderCommand.ImplicitOutput, or
+// RuleBuilderCommand.FlagWithInput. The list is sorted and duplicates removed.
func (r *RuleBuilder) Outputs() WritablePaths {
outputs := r.outputSet()
@@ -262,7 +286,8 @@
return tools
}
-// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method.
+// Tools returns the list of paths that were passed to the RuleBuilderCommand.Tool method. The
+// list is sorted and duplicates removed.
func (r *RuleBuilder) Tools() Paths {
toolsSet := r.toolsSet()
@@ -337,6 +362,7 @@
ctx.Build(pctx, BuildParams{
Rule: ErrorRule,
Outputs: r.Outputs(),
+ OrderOnly: r.OrderOnlys(),
Description: desc,
Args: map[string]string{
"error": "missing dependencies: " + strings.Join(r.missingDeps, ", "),
@@ -453,6 +479,7 @@
type RuleBuilderCommand struct {
buf strings.Builder
inputs Paths
+ orderOnlys Paths
outputs WritablePaths
depFiles WritablePaths
tools Paths
@@ -475,6 +502,10 @@
return path.String()
}
+func (c *RuleBuilderCommand) addOrderOnly(path Path) {
+ c.orderOnlys = append(c.orderOnlys, path)
+}
+
func (c *RuleBuilderCommand) outputStr(path Path) string {
if c.sbox {
// Errors will be handled in RuleBuilder.Build where we have a context to report them
@@ -604,6 +635,22 @@
return c
}
+// OrderOnly adds the specified input path to the dependencies returned by RuleBuilder.OrderOnlys
+// without modifying the command line.
+func (c *RuleBuilderCommand) OrderOnly(path Path) *RuleBuilderCommand {
+ c.addOrderOnly(path)
+ return c
+}
+
+// OrderOnlys adds the specified input paths to the dependencies returned by RuleBuilder.OrderOnlys
+// without modifying the command line.
+func (c *RuleBuilderCommand) OrderOnlys(paths Paths) *RuleBuilderCommand {
+ for _, path := range paths {
+ c.addOrderOnly(path)
+ }
+ return c
+}
+
// Output adds the specified output path to the command line. The path will also be added to the outputs returned by
// RuleBuilder.Outputs.
func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index acf8127..c41b067 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -265,14 +265,16 @@
func TestRuleBuilder(t *testing.T) {
fs := map[string][]byte{
- "dep_fixer": nil,
- "input": nil,
- "Implicit": nil,
- "Input": nil,
- "Tool": nil,
- "input2": nil,
- "tool2": nil,
- "input3": nil,
+ "dep_fixer": nil,
+ "input": nil,
+ "Implicit": nil,
+ "Input": nil,
+ "OrderOnly": nil,
+ "OrderOnlys": nil,
+ "Tool": nil,
+ "input2": nil,
+ "tool2": nil,
+ "input3": nil,
}
ctx := PathContextForTesting(TestConfig("out", nil, "", fs))
@@ -290,6 +292,7 @@
ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
Input(PathForSource(ctx, "Input")).
Output(PathForOutput(ctx, "Output")).
+ OrderOnly(PathForSource(ctx, "OrderOnly")).
Text("Text").
Tool(PathForSource(ctx, "Tool"))
@@ -298,6 +301,7 @@
DepFile(PathForOutput(ctx, "depfile2")).
Input(PathForSource(ctx, "input2")).
Output(PathForOutput(ctx, "output2")).
+ OrderOnlys(PathsForSource(ctx, []string{"OrderOnlys"})).
Tool(PathForSource(ctx, "tool2"))
// Test updates to the first command after the second command has been started
@@ -317,6 +321,7 @@
wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
+ wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
t.Run("normal", func(t *testing.T) {
rule := NewRuleBuilder()
@@ -346,6 +351,9 @@
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
@@ -380,6 +388,9 @@
if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
}
+ if g, w := rule.OrderOnlys(), wantOrderOnlys; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.OrderOnlys() = %#v\n got %#v", w, g)
+ }
if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
diff --git a/android/variable.go b/android/variable.go
index 9cbe624..25c94bc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -140,9 +140,8 @@
// Suffix to add to generated Makefiles
Make_suffix *string `json:",omitempty"`
- BuildId *string `json:",omitempty"`
- BuildNumberFromFile *string `json:",omitempty"`
- DateFromFile *string `json:",omitempty"`
+ BuildId *string `json:",omitempty"`
+ BuildNumberFile *string `json:",omitempty"`
Platform_version_name *string `json:",omitempty"`
Platform_sdk_version *int `json:",omitempty"`
@@ -345,7 +344,7 @@
func (v *productVariables) SetDefaultConfig() {
*v = productVariables{
- BuildNumberFromFile: stringPtr("123456789"),
+ BuildNumberFile: stringPtr("build_number.txt"),
Platform_version_name: stringPtr("Q"),
Platform_sdk_version: intPtr(28),
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 0abec0d..5c15e8e 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -120,8 +120,8 @@
fmt.Fprintln(w, "LOCAL_MODULE_SYMLINKS :=", strings.Join(fi.symlinks, " "))
}
- if fi.module != nil && fi.module.NoticeFile().Valid() {
- fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", fi.module.NoticeFile().Path().String())
+ if fi.module != nil && len(fi.module.NoticeFiles()) > 0 {
+ fmt.Fprintln(w, "LOCAL_NOTICE_FILE :=", strings.Join(fi.module.NoticeFiles().Strings(), " "))
}
} else {
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", pathWhenActivated)
@@ -308,7 +308,7 @@
}
if a.installedFilesFile != nil {
- goal := "droidcore"
+ goal := "checkbuild"
distFile := name + "-installed-files.txt"
fmt.Fprintln(w, ".PHONY:", goal)
fmt.Fprintf(w, "$(call dist-for-goals,%s,%s:%s)\n",
diff --git a/apex/apex.go b/apex/apex.go
index 6d4b17b..c791162 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -52,6 +52,7 @@
var (
sharedLibTag = dependencyTag{name: "sharedLib", payload: true}
+ jniLibTag = dependencyTag{name: "jniLib", payload: true}
executableTag = dependencyTag{name: "executable", payload: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
prebuiltTag = dependencyTag{name: "prebuilt", payload: true}
@@ -1155,10 +1156,13 @@
})
}
-type apexNativeDependencies struct {
+type ApexNativeDependencies struct {
// List of native libraries
Native_shared_libs []string
+ // List of JNI libraries
+ Jni_libs []string
+
// List of native executables
Binaries []string
@@ -1168,19 +1172,19 @@
type apexMultilibProperties struct {
// Native dependencies whose compile_multilib is "first"
- First apexNativeDependencies
+ First ApexNativeDependencies
// Native dependencies whose compile_multilib is "both"
- Both apexNativeDependencies
+ Both ApexNativeDependencies
// Native dependencies whose compile_multilib is "prefer32"
- Prefer32 apexNativeDependencies
+ Prefer32 ApexNativeDependencies
// Native dependencies whose compile_multilib is "32"
- Lib32 apexNativeDependencies
+ Lib32 ApexNativeDependencies
// Native dependencies whose compile_multilib is "64"
- Lib64 apexNativeDependencies
+ Lib64 ApexNativeDependencies
}
type apexBundleProperties struct {
@@ -1202,11 +1206,7 @@
// Default: /system/sepolicy/apex/<module_name>_file_contexts.
File_contexts *string `android:"path"`
- // List of native shared libs that are embedded inside this APEX bundle
- Native_shared_libs []string
-
- // List of executables that are embedded inside this APEX bundle
- Binaries []string
+ ApexNativeDependencies
// List of java libraries that are embedded inside this APEX bundle
Java_libs []string
@@ -1214,9 +1214,6 @@
// List of prebuilt files that are embedded inside this APEX bundle
Prebuilts []string
- // List of tests that are embedded inside this APEX bundle
- Tests []string
-
// Name of the apex_key module that provides the private key to sign APEX
Key *string
@@ -1413,6 +1410,8 @@
jacocoReportClassesFile android.Path // only for javalibs and apps
certificate java.Certificate // only for apps
+
+ isJniLib bool
}
func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
@@ -1531,7 +1530,7 @@
}
func addDependenciesForNativeModules(ctx android.BottomUpMutatorContext,
- native_shared_libs []string, binaries []string, tests []string,
+ nativeModules ApexNativeDependencies,
target android.Target, imageVariation string) {
// Use *FarVariation* to be able to depend on modules having
// conflicting variations with this module. This is required since
@@ -1541,16 +1540,22 @@
{Mutator: "image", Variation: imageVariation},
{Mutator: "link", Variation: "shared"},
{Mutator: "version", Variation: ""}, // "" is the non-stub variant
- }...), sharedLibTag, native_shared_libs...)
+ }...), sharedLibTag, nativeModules.Native_shared_libs...)
+
+ ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
+ {Mutator: "image", Variation: imageVariation},
+ {Mutator: "link", Variation: "shared"},
+ {Mutator: "version", Variation: ""}, // "" is the non-stub variant
+ }...), jniLibTag, nativeModules.Jni_libs...)
ctx.AddFarVariationDependencies(append(target.Variations(),
blueprint.Variation{Mutator: "image", Variation: imageVariation}),
- executableTag, binaries...)
+ executableTag, nativeModules.Binaries...)
ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "image", Variation: imageVariation},
{Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
- }...), testTag, tests...)
+ }...), testTag, nativeModules.Tests...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -1583,41 +1588,39 @@
}
}
for i, target := range targets {
- // When multilib.* is omitted for native_shared_libs, it implies
- // multilib.both.
- ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: a.getImageVariation(config)},
- {Mutator: "link", Variation: "shared"},
- }...), sharedLibTag, a.properties.Native_shared_libs...)
-
- // When multilib.* is omitted for tests, it implies
- // multilib.both.
- ctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
- {Mutator: "image", Variation: a.getImageVariation(config)},
- {Mutator: "test_per_src", Variation: ""}, // "" is the all-tests variant
- }...), testTag, a.properties.Tests...)
+ // When multilib.* is omitted for native_shared_libs/jni_libs/tests, it implies
+ // multilib.both
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: a.properties.Native_shared_libs,
+ Tests: a.properties.Tests,
+ Jni_libs: a.properties.Jni_libs,
+ Binaries: nil,
+ },
+ target, a.getImageVariation(config))
// Add native modules targetting both ABIs
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Both.Native_shared_libs,
- a.properties.Multilib.Both.Binaries,
- a.properties.Multilib.Both.Tests,
+ a.properties.Multilib.Both,
target,
a.getImageVariation(config))
isPrimaryAbi := i == 0
if isPrimaryAbi {
// When multilib.* is omitted for binaries, it implies
- // multilib.first.
- ctx.AddFarVariationDependencies(append(target.Variations(),
- blueprint.Variation{Mutator: "image", Variation: a.getImageVariation(config)}),
- executableTag, a.properties.Binaries...)
+ // multilib.first
+ addDependenciesForNativeModules(ctx,
+ ApexNativeDependencies{
+ Native_shared_libs: nil,
+ Tests: nil,
+ Jni_libs: nil,
+ Binaries: a.properties.Binaries,
+ },
+ target, a.getImageVariation(config))
// Add native modules targetting the first ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.First.Native_shared_libs,
- a.properties.Multilib.First.Binaries,
- a.properties.Multilib.First.Tests,
+ a.properties.Multilib.First,
target,
a.getImageVariation(config))
}
@@ -1626,32 +1629,24 @@
case "lib32":
// Add native modules targetting 32-bit ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib32.Native_shared_libs,
- a.properties.Multilib.Lib32.Binaries,
- a.properties.Multilib.Lib32.Tests,
+ a.properties.Multilib.Lib32,
target,
a.getImageVariation(config))
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries,
- a.properties.Multilib.Prefer32.Tests,
+ a.properties.Multilib.Prefer32,
target,
a.getImageVariation(config))
case "lib64":
// Add native modules targetting 64-bit ABI
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Lib64.Native_shared_libs,
- a.properties.Multilib.Lib64.Binaries,
- a.properties.Multilib.Lib64.Tests,
+ a.properties.Multilib.Lib64,
target,
a.getImageVariation(config))
if !has32BitTarget {
addDependenciesForNativeModules(ctx,
- a.properties.Multilib.Prefer32.Native_shared_libs,
- a.properties.Multilib.Prefer32.Binaries,
- a.properties.Multilib.Prefer32.Tests,
+ a.properties.Multilib.Prefer32,
target,
a.getImageVariation(config))
}
@@ -1660,8 +1655,8 @@
for _, sanitizer := range ctx.Config().SanitizeDevice() {
if sanitizer == "hwaddress" {
addDependenciesForNativeModules(ctx,
- []string{"libclang_rt.hwasan-aarch64-android"},
- nil, nil, target, a.getImageVariation(config))
+ ApexNativeDependencies{[]string{"libclang_rt.hwasan-aarch64-android"}, nil, nil, nil},
+ target, a.getImageVariation(config))
break
}
}
@@ -2082,16 +2077,23 @@
depName := ctx.OtherModuleName(child)
if _, isDirectDep := parent.(*apexBundle); isDirectDep {
switch depTag {
- case sharedLibTag:
+ case sharedLibTag, jniLibTag:
+ isJniLib := depTag == jniLibTag
if c, ok := child.(*cc.Module); ok {
// bootstrap bionic libs are treated as provided by system
if c.HasStubsVariants() && !cc.InstallToBootstrap(c.BaseModuleName(), ctx.Config()) {
provideNativeLibs = append(provideNativeLibs, c.OutputFile().Path().Base())
}
- filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, c, handleSpecialLibs))
+ fi := apexFileForNativeLibrary(ctx, c, handleSpecialLibs)
+ fi.isJniLib = isJniLib
+ filesInfo = append(filesInfo, fi)
return true // track transitive dependencies
} else {
- ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
+ propertyName := "native_shared_libs"
+ if isJniLib {
+ propertyName = "jni_libs"
+ }
+ ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
}
case executableTag:
if cc, ok := child.(*cc.Module); ok {
@@ -2327,6 +2329,11 @@
a.linkToSystemLib = false
}
+ // We also don't want the optimization for host APEXes, because it doesn't make sense.
+ if ctx.Host() {
+ a.linkToSystemLib = false
+ }
+
// prepare apex_manifest.json
a.buildManifest(ctx, provideNativeLibs, requireNativeLibs)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 10fc8d6..8c5ca8b 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -226,6 +226,14 @@
os.RemoveAll(buildDir)
}
+// ensure that 'result' equals 'expected'
+func ensureEquals(t *testing.T, result string, expected string) {
+ t.Helper()
+ if result != expected {
+ t.Errorf("%q != %q", expected, result)
+ }
+}
+
// ensure that 'result' contains 'expected'
func ensureContains(t *testing.T, result string, expected string) {
t.Helper()
@@ -1532,13 +1540,17 @@
var surplus []string
filesMatched := make(map[string]bool)
for _, file := range getFiles(t, ctx, moduleName, variant) {
+ mactchFound := false
for _, expected := range files {
if matched, _ := path.Match(expected, file.path); matched {
filesMatched[expected] = true
- return
+ mactchFound = true
+ break
}
}
- surplus = append(surplus, file.path)
+ if !mactchFound {
+ surplus = append(surplus, file.path)
+ }
}
if len(surplus) > 0 {
@@ -1605,8 +1617,10 @@
ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
"lib/libvndk.so",
"lib/libvndksp.so",
+ "lib/libc++.so",
"lib64/libvndk.so",
"lib64/libvndksp.so",
+ "lib64/libc++.so",
"etc/llndk.libraries.VER.txt",
"etc/vndkcore.libraries.VER.txt",
"etc/vndksp.libraries.VER.txt",
@@ -1666,6 +1680,8 @@
"lib/libvndk.so",
"lib/libvndk.arm.so",
"lib64/libvndk.so",
+ "lib/libc++.so",
+ "lib64/libc++.so",
"etc/*",
})
}
@@ -1877,6 +1893,8 @@
ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
"lib/libvndk.so",
"lib64/libvndk.so",
+ "lib/libc++.so",
+ "lib64/libc++.so",
"etc/*",
})
}
@@ -3611,6 +3629,70 @@
ensureRealfileExists(t, files, "lib64/myotherlib.so") // this is a real file
}
+func TestApexWithJniLibs(t *testing.T) {
+ ctx, _ := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ jni_libs: ["mylib"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ srcs: ["mylib.cpp"],
+ shared_libs: ["mylib2"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+
+ cc_library {
+ name: "mylib2",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ }
+ `)
+
+ rule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
+ // Notice mylib2.so (transitive dep) is not added as a jni_lib
+ ensureEquals(t, rule.Args["opt"], "-a jniLibs mylib.so")
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
+ "lib64/mylib.so",
+ "lib64/mylib2.so",
+ })
+}
+
+func TestApexWithJniLibs_Errors(t *testing.T) {
+ testApexError(t, `jni_libs: "xxx" is not a cc_library`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ jni_libs: ["xxx"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ prebuilt_etc {
+ name: "xxx",
+ src: "xxx",
+ }
+ `, withFiles(map[string][]byte{
+ "xxx": nil,
+ }))
+}
+
func TestMain(m *testing.M) {
run := func() int {
setUp()
diff --git a/apex/builder.go b/apex/builder.go
index adb3219..8c81fb4 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -180,6 +180,17 @@
optCommands = append(optCommands, "-v name "+*a.properties.Apex_name)
}
+ // collect jniLibs. Notice that a.filesInfo is already sorted
+ var jniLibs []string
+ for _, fi := range a.filesInfo {
+ if fi.isJniLib {
+ jniLibs = append(jniLibs, fi.builtFile.Base())
+ }
+ }
+ if len(jniLibs) > 0 {
+ optCommands = append(optCommands, "-a jniLibs "+strings.Join(jniLibs, " "))
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: apexManifestRule,
Input: manifestSrc,
@@ -215,15 +226,15 @@
noticeFiles := []android.Path{}
for _, f := range a.filesInfo {
if f.module != nil {
- notice := f.module.NoticeFile()
- if notice.Valid() {
- noticeFiles = append(noticeFiles, notice.Path())
+ notices := f.module.NoticeFiles()
+ if len(notices) > 0 {
+ noticeFiles = append(noticeFiles, notices...)
}
}
}
// append the notice file specified in the apex module itself
- if a.NoticeFile().Valid() {
- noticeFiles = append(noticeFiles, a.NoticeFile().Path())
+ if len(a.NoticeFiles()) > 0 {
+ noticeFiles = append(noticeFiles, a.NoticeFiles()...)
}
if len(noticeFiles) == 0 {
diff --git a/build_kzip.bash b/build_kzip.bash
index 008030f..0018ea9 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -19,16 +19,20 @@
# The extraction might fail for some source files, so run with -k and then check that
# sufficiently many files were generated.
declare -r out="${OUT_DIR:-out}"
+
# Build extraction files for C++ and Java. Build `merge_zips` which we use later.
build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xref_cxx xref_java
-#Build extraction file for Go files in build/soong directory.
+
+# Build extraction file for Go the files in build/{blueprint,soong} directories.
declare -r abspath_out=$(realpath "${out}")
declare -r go_extractor=$(realpath prebuilts/build-tools/linux-x86/bin/go_extractor)
declare -r go_root=$(realpath prebuilts/go/linux-x86)
+declare -r vnames_path=$(realpath build/soong/vnames.go.json)
+declare -r source_root=$PWD
for dir in blueprint soong; do
(cd "build/$dir";
- "$go_extractor" --goroot="$go_root" --rules=vnames.go.json --canonicalize_package_corpus \
- --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
+ KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" --rules="${vnames_path}" \
+ --canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
)
done
diff --git a/cc/linker.go b/cc/linker.go
index af4cbf3..a7b621a 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -501,19 +501,21 @@
var injectVersionSymbol = pctx.AndroidStaticRule("injectVersionSymbol",
blueprint.RuleParams{
Command: "$symbolInjectCmd -i $in -o $out -s soong_build_number " +
- "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $buildNumberFromFile",
+ "-from 'SOONG BUILD NUMBER PLACEHOLDER' -v $$(cat $buildNumberFile)",
CommandDeps: []string{"$symbolInjectCmd"},
},
- "buildNumberFromFile")
+ "buildNumberFile")
func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path, out android.WritablePath) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: injectVersionSymbol,
Description: "inject version symbol",
Input: in,
Output: out,
+ OrderOnly: android.Paths{buildNumberFile},
Args: map[string]string{
- "buildNumberFromFile": proptools.NinjaEscape(ctx.Config().BuildNumberFromFile()),
+ "buildNumberFile": buildNumberFile.String(),
},
})
}
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 8f48f86..73388ce 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -117,6 +117,17 @@
return outPath
}
+func combineNotices(ctx android.SingletonContext, paths android.Paths, out string) android.OutputPath {
+ outPath := android.PathForOutput(ctx, out)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cat,
+ Inputs: paths,
+ Output: outPath,
+ Description: "combine notices for " + out,
+ })
+ return outPath
+}
+
func writeStringToFile(ctx android.SingletonContext, content, out string) android.OutputPath {
outPath := android.PathForOutput(ctx, out)
ctx.Build(pctx, android.BuildParams{
diff --git a/cc/test.go b/cc/test.go
index 05e6fe5..1085d3a 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -49,7 +49,7 @@
// list of files or filegroup modules that provide data that should be installed alongside
// the test
- Data []string `android:"path"`
+ Data []string `android:"path,arch_variant"`
// list of compatibility suites (for example "cts", "vts") that the module should be
// installed into.
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index aed7918..20762a8 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -661,14 +661,14 @@
headers = append(headers, exportedHeaders(ctx, l)...)
}
- if m.NoticeFile().Valid() {
+ if len(m.NoticeFiles()) > 0 {
noticeName := ctx.ModuleName(m) + ".txt"
noticeOut := filepath.Join(noticeDir, noticeName)
// skip already copied notice file
if !installedNotices[noticeOut] {
installedNotices[noticeOut] = true
- snapshotOutputs = append(snapshotOutputs, copyFile(
- ctx, m.NoticeFile().Path(), noticeOut))
+ snapshotOutputs = append(snapshotOutputs, combineNotices(
+ ctx, m.NoticeFiles(), noticeOut))
}
}
})
diff --git a/cc/vndk.go b/cc/vndk.go
index 4578a7d..d0492fc 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -644,13 +644,13 @@
moduleNames[stem] = ctx.ModuleName(m)
modulePaths[stem] = ctx.ModuleDir(m)
- if m.NoticeFile().Valid() {
+ if len(m.NoticeFiles()) > 0 {
noticeName := stem + ".txt"
// skip already copied notice file
if _, ok := noticeBuilt[noticeName]; !ok {
noticeBuilt[noticeName] = true
- snapshotOutputs = append(snapshotOutputs, copyFile(
- ctx, m.NoticeFile().Path(), filepath.Join(noticeDir, noticeName)))
+ snapshotOutputs = append(snapshotOutputs, combineNotices(
+ ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName)))
}
}
diff --git a/java/app.go b/java/app.go
index 0745bf0..ed4462c 100755
--- a/java/app.go
+++ b/java/app.go
@@ -390,16 +390,20 @@
return false
}
- path := child.(android.Module).NoticeFile()
- if path.Valid() {
- noticePathSet[path.Path()] = true
+ paths := child.(android.Module).NoticeFiles()
+ if len(paths) > 0 {
+ for _, path := range paths {
+ noticePathSet[path] = true
+ }
}
return true
})
// If the app has one, add it too.
- if a.NoticeFile().Valid() {
- noticePathSet[a.NoticeFile().Path()] = true
+ if len(a.NoticeFiles()) > 0 {
+ for _, path := range a.NoticeFiles() {
+ noticePathSet[path] = true
+ }
}
if len(noticePathSet) == 0 {
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 4313964..40cfe4f 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -132,28 +132,28 @@
bootImage = artBootImageConfig(ctx)
}
- var archs []android.ArchType
- for _, a := range ctx.MultiTargets() {
- archs = append(archs, a.Arch.ArchType)
- }
- if len(archs) == 0 {
+ targets := ctx.MultiTargets()
+ if len(targets) == 0 {
// assume this is a java library, dexpreopt for all arches for now
for _, target := range ctx.Config().Targets[android.Android] {
if target.NativeBridge == android.NativeBridgeDisabled {
- archs = append(archs, target.Arch.ArchType)
+ targets = append(targets, target)
}
}
if inList(ctx.ModuleName(), global.SystemServerJars) && !d.isSDKLibrary {
// If the module is not an SDK library and it's a system server jar, only preopt the primary arch.
- archs = archs[:1]
+ targets = targets[:1]
}
}
+ var archs []android.ArchType
var images android.Paths
var imagesDeps []android.OutputPaths
- for _, arch := range archs {
- images = append(images, bootImage.images[arch])
- imagesDeps = append(imagesDeps, bootImage.imagesDeps[arch])
+ for _, target := range targets {
+ archs = append(archs, target.Arch.ArchType)
+ variant := bootImage.getVariant(target)
+ images = append(images, variant.images)
+ imagesDeps = append(imagesDeps, variant.imagesDeps)
}
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 655a476..d7adb40 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "sort"
"strings"
"android/soong/android"
@@ -48,6 +47,7 @@
// The location is passed as an argument to the ART tools like dex2oat instead of the real path. The ART tools
// will then reconstruct the real path, so the rules must have a dependency on the real path.
+// Target-independent description of pre-compiled boot image.
type bootImageConfig struct {
// Whether this image is an extension.
extension bool
@@ -67,9 +67,6 @@
// Subdirectory where the image files are installed.
installSubdir string
- // Targets for which the image is generated.
- targets []android.Target
-
// The names of jars that constitute this image.
modules []string
@@ -84,15 +81,43 @@
// The "locations" of the dependency images and in this image.
imageLocations []string
- // Paths to image files (grouped by target).
- images map[android.ArchType]android.OutputPath // first image file
- imagesDeps map[android.ArchType]android.OutputPaths // all files
-
- // Only for extensions, paths to the primary boot images (grouped by target).
- primaryImages map[android.ArchType]android.OutputPath
-
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath
+
+ // Rules which should be used in make to install the outputs.
+ profileInstalls android.RuleBuilderInstalls
+
+ // Target-dependent fields.
+ variants []*bootImageVariant
+}
+
+// Target-dependent description of pre-compiled boot image.
+type bootImageVariant struct {
+ *bootImageConfig
+
+ // Target for which the image is generated.
+ target android.Target
+
+ // Paths to image files.
+ images android.OutputPath // first image file
+ imagesDeps android.OutputPaths // all files
+
+ // Only for extensions, paths to the primary boot images.
+ primaryImages android.OutputPath
+
+ // Rules which should be used in make to install the outputs.
+ installs android.RuleBuilderInstalls
+ vdexInstalls android.RuleBuilderInstalls
+ unstrippedInstalls android.RuleBuilderInstalls
+}
+
+func (image bootImageConfig) getVariant(target android.Target) *bootImageVariant {
+ for _, variant := range image.variants {
+ if variant.target.Os == target.Os && variant.target.Arch.ArchType == target.Arch.ArchType {
+ return variant
+ }
+ }
+ return nil
}
func (image bootImageConfig) moduleName(idx int) string {
@@ -126,28 +151,6 @@
return ret
}
-type bootImage struct {
- bootImageConfig
-
- installs map[android.ArchType]android.RuleBuilderInstalls
- vdexInstalls map[android.ArchType]android.RuleBuilderInstalls
- unstrippedInstalls map[android.ArchType]android.RuleBuilderInstalls
-
- profileInstalls android.RuleBuilderInstalls
-}
-
-func newBootImage(ctx android.PathContext, config bootImageConfig) *bootImage {
- image := &bootImage{
- bootImageConfig: config,
-
- installs: make(map[android.ArchType]android.RuleBuilderInstalls),
- vdexInstalls: make(map[android.ArchType]android.RuleBuilderInstalls),
- unstrippedInstalls: make(map[android.ArchType]android.RuleBuilderInstalls),
- }
-
- return image
-}
-
func concat(lists ...[]string) []string {
var size int
for _, l := range lists {
@@ -182,8 +185,8 @@
}
type dexpreoptBootJars struct {
- defaultBootImage *bootImage
- otherImages []*bootImage
+ defaultBootImage *bootImageConfig
+ otherImages []*bootImageConfig
dexpreoptConfigForMake android.WritablePath
}
@@ -193,10 +196,11 @@
if skipDexpreoptBootJars(ctx) {
return nil
}
-
// Include dexpreopt files for the primary boot image.
- files := artBootImageConfig(ctx).imagesDeps
-
+ files := map[android.ArchType]android.OutputPaths{}
+ for _, variant := range artBootImageConfig(ctx).variants {
+ files[variant.target.Arch.ArchType] = variant.imagesDeps
+ }
return files
}
@@ -233,10 +237,8 @@
dumpOatRules(ctx, d.defaultBootImage)
}
-// buildBootImage takes a bootImageConfig, creates rules to build it, and returns a *bootImage.
-func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootImage {
- image := newBootImage(ctx, config)
-
+// buildBootImage takes a bootImageConfig, creates rules to build it, and returns the image.
+func buildBootImage(ctx android.SingletonContext, image *bootImageConfig) *bootImageConfig {
bootDexJars := make(android.Paths, len(image.modules))
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
@@ -277,8 +279,8 @@
bootFrameworkProfileRule(ctx, image, missingDeps)
var allFiles android.Paths
- for _, target := range image.targets {
- files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+ for _, variant := range image.variants {
+ files := buildBootImageVariant(ctx, variant, profile, missingDeps)
allFiles = append(allFiles, files.Paths()...)
}
@@ -296,12 +298,13 @@
return image
}
-func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
- arch android.ArchType, profile android.Path, missingDeps []string) android.WritablePaths {
+func buildBootImageVariant(ctx android.SingletonContext, image *bootImageVariant,
+ profile android.Path, missingDeps []string) android.WritablePaths {
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
+ arch := image.target.Arch.ArchType
symbolsDir := image.symbolsDir.Join(ctx, image.installSubdir, arch.String())
symbolsFile := symbolsDir.Join(ctx, image.stem+".oat")
outputDir := image.dir.Join(ctx, image.installSubdir, arch.String())
@@ -351,7 +354,7 @@
}
if image.extension {
- artImage := image.primaryImages[arch]
+ artImage := image.primaryImages
cmd.
Flag("--runtime-arg").FlagWithInputList("-Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
Flag("--runtime-arg").FlagWithList("-Xbootclasspath-locations:", image.dexLocationsDeps, ":").
@@ -426,9 +429,9 @@
rule.Build(pctx, ctx, image.name+"JarsDexpreopt_"+arch.String(), "dexpreopt "+image.name+" jars "+arch.String())
// save output and installed files for makevars
- image.installs[arch] = rule.Installs()
- image.vdexInstalls[arch] = vdexInstalls
- image.unstrippedInstalls[arch] = unstrippedInstalls
+ image.installs = rule.Installs()
+ image.vdexInstalls = vdexInstalls
+ image.unstrippedInstalls = unstrippedInstalls
return zipFiles
}
@@ -437,7 +440,7 @@
It is likely that the boot classpath is inconsistent.
Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.`
-func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath {
+func bootImageProfileRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -492,7 +495,7 @@
var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule")
-func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath {
+func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImageConfig, missingDeps []string) android.WritablePath {
globalSoong := dexpreopt.GetCachedGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
@@ -537,15 +540,10 @@
var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule")
-func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
- var archs []android.ArchType
- for arch := range image.images {
- archs = append(archs, arch)
- }
- sort.Slice(archs, func(i, j int) bool { return archs[i].String() < archs[j].String() })
-
+func dumpOatRules(ctx android.SingletonContext, image *bootImageConfig) {
var allPhonies android.Paths
- for _, arch := range archs {
+ for _, image := range image.variants {
+ arch := image.target.Arch.ArchType
// Create a rule to call oatdump.
output := android.PathForOutput(ctx, "boot."+arch.String()+".oatdump.txt")
rule := android.NewRuleBuilder()
@@ -554,7 +552,7 @@
BuiltTool(ctx, "oatdumpd").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocationsDeps, ":").
- FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps[arch].Paths()).
+ FlagWithArg("--image=", strings.Join(image.imageLocations, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
rule.Build(pctx, ctx, "dump-oat-boot-"+arch.String(), "dump oat boot "+arch.String())
@@ -609,20 +607,13 @@
var imageNames []string
for _, current := range append(d.otherImages, image) {
imageNames = append(imageNames, current.name)
- var arches []android.ArchType
- for arch, _ := range current.images {
- arches = append(arches, arch)
- }
-
- sort.Slice(arches, func(i, j int) bool { return arches[i].String() < arches[j].String() })
-
- for _, arch := range arches {
- sfx := current.name + "_" + arch.String()
- ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps[arch].Strings(), " "))
- ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs[arch].String())
- ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls[arch].String())
+ for _, current := range current.variants {
+ sfx := current.name + "_" + current.target.Arch.ArchType.String()
+ ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+sfx, current.vdexInstalls.String())
+ ctx.Strict("DEXPREOPT_IMAGE_"+sfx, current.images.String())
+ ctx.Strict("DEXPREOPT_IMAGE_DEPS_"+sfx, strings.Join(current.imagesDeps.Strings(), " "))
+ ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+sfx, current.installs.String())
+ ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+sfx, current.unstrippedInstalls.String())
}
ctx.Strict("DEXPREOPT_IMAGE_LOCATIONS_"+current.name, strings.Join(current.imageLocations, ":"))
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 28f56d2..a06aec4 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -146,8 +146,6 @@
// common to all configs
for _, c := range configs {
- c.targets = targets
-
c.dir = deviceDir.Join(ctx, "dex_"+c.name+"jars")
c.symbolsDir = deviceDir.Join(ctx, "dex_"+c.name+"jars_unstripped")
@@ -166,14 +164,17 @@
}
c.dexPathsDeps = c.dexPaths
- c.images = make(map[android.ArchType]android.OutputPath)
- c.imagesDeps = make(map[android.ArchType]android.OutputPaths)
-
+ // Create target-specific variants.
for _, target := range targets {
arch := target.Arch.ArchType
imageDir := c.dir.Join(ctx, c.installSubdir, arch.String())
- c.images[arch] = imageDir.Join(ctx, imageName)
- c.imagesDeps[arch] = c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex")
+ variant := &bootImageVariant{
+ bootImageConfig: c,
+ target: target,
+ images: imageDir.Join(ctx, imageName),
+ imagesDeps: c.moduleFiles(ctx, imageDir, ".art", ".oat", ".vdex"),
+ }
+ c.variants = append(c.variants, variant)
}
c.zip = c.dir.Join(ctx, c.name+".zip")
@@ -181,19 +182,21 @@
// specific to the framework config
frameworkCfg.dexPathsDeps = append(artCfg.dexPathsDeps, frameworkCfg.dexPathsDeps...)
- frameworkCfg.primaryImages = artCfg.images
+ for i := range targets {
+ frameworkCfg.variants[i].primaryImages = artCfg.variants[i].images
+ }
frameworkCfg.imageLocations = append(artCfg.imageLocations, frameworkCfg.imageLocations...)
return configs
}).(map[string]*bootImageConfig)
}
-func artBootImageConfig(ctx android.PathContext) bootImageConfig {
- return *genBootImageConfigs(ctx)[artBootImageName]
+func artBootImageConfig(ctx android.PathContext) *bootImageConfig {
+ return genBootImageConfigs(ctx)[artBootImageName]
}
-func defaultBootImageConfig(ctx android.PathContext) bootImageConfig {
- return *genBootImageConfigs(ctx)[frameworkBootImageName]
+func defaultBootImageConfig(ctx android.PathContext) *bootImageConfig {
+ return genBootImageConfigs(ctx)[frameworkBootImageName]
}
func defaultBootclasspath(ctx android.PathContext) []string {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index fd4b90d..5437499 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -773,6 +773,7 @@
}
func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, docletPath classpath) {
+ buildNumberFile := ctx.Config().BuildNumberFile(ctx)
// Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9
// sources, droiddoc will get sources produced by metalava which will have already stripped out the
// 1.9 language features.
@@ -782,7 +783,7 @@
Flag("-XDignore.symbol.file").
FlagWithArg("-doclet ", "com.google.doclava.Doclava").
FlagWithInputList("-docletpath ", docletPath.Paths(), ":").
- FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-"+ctx.Config().BuildNumberFromFile()).
+ FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-$(cat "+buildNumberFile.String()+")").OrderOnly(buildNumberFile).
FlagWithArg("-hdf page.now ", `"$(date -d @$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `)
if String(d.properties.Custom_template) == "" {
diff --git a/java/java.go b/java/java.go
index b3aca49..8d58a90 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1323,6 +1323,7 @@
j.compiledSrcJars = srcJars
enable_sharding := false
+ var headerJarFileWithoutJarjar android.Path
if ctx.Device() && !ctx.Config().IsEnvFalse("TURBINE_ENABLED") && !deps.disableTurbine {
if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
enable_sharding = true
@@ -1332,7 +1333,8 @@
// allow for the use of annotation processors that do function correctly
// with sharding enabled. See: b/77284273.
}
- j.headerJarFile = j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
+ headerJarFileWithoutJarjar, j.headerJarFile =
+ j.compileJavaHeader(ctx, uniqueSrcFiles, srcJars, deps, flags, jarName, kotlinJars)
if ctx.Failed() {
return
}
@@ -1351,7 +1353,7 @@
}
if enable_sharding {
- flags.classpath = append(flags.classpath, j.headerJarFile)
+ flags.classpath = append(flags.classpath, headerJarFileWithoutJarjar)
shardSize := int(*(j.properties.Javac_shard_size))
var shardSrcs []android.Paths
if len(uniqueSrcFiles) > 0 {
@@ -1650,7 +1652,8 @@
}
func (j *Module) compileJavaHeader(ctx android.ModuleContext, srcFiles, srcJars android.Paths,
- deps deps, flags javaBuilderFlags, jarName string, extraJars android.Paths) android.Path {
+ deps deps, flags javaBuilderFlags, jarName string,
+ extraJars android.Paths) (headerJar, jarjarHeaderJar android.Path) {
var jars android.Paths
if len(srcFiles) > 0 || len(srcJars) > 0 {
@@ -1658,7 +1661,7 @@
turbineJar := android.PathForModuleOut(ctx, "turbine", jarName)
TransformJavaToHeaderClasses(ctx, turbineJar, srcFiles, srcJars, flags)
if ctx.Failed() {
- return nil
+ return nil, nil
}
jars = append(jars, turbineJar)
}
@@ -1667,7 +1670,6 @@
// Combine any static header libraries into classes-header.jar. If there is only
// one input jar this step will be skipped.
- var headerJar android.Path
jars = append(jars, deps.staticHeaderJars...)
// we cannot skip the combine step for now if there is only one jar
@@ -1676,18 +1678,19 @@
TransformJarsToJar(ctx, combinedJar, "for turbine", jars, android.OptionalPath{},
false, nil, []string{"META-INF/TRANSITIVE"})
headerJar = combinedJar
+ jarjarHeaderJar = combinedJar
if j.expandJarjarRules != nil {
// Transform classes.jar into classes-jarjar.jar
jarjarFile := android.PathForModuleOut(ctx, "turbine-jarjar", jarName)
TransformJarJar(ctx, jarjarFile, headerJar, j.expandJarjarRules)
- headerJar = jarjarFile
+ jarjarHeaderJar = jarjarFile
if ctx.Failed() {
- return nil
+ return nil, nil
}
}
- return headerJar
+ return headerJar, jarjarHeaderJar
}
func (j *Module) instrument(ctx android.ModuleContext, flags javaBuilderFlags,
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 4976dc0..c194ac1 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -323,8 +323,10 @@
if s.Enabled() {
for _, memberListProperty := range s.memberListProperties() {
names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
- tag := memberListProperty.dependencyTag
- memberListProperty.memberType.AddDependencies(mctx, tag, names)
+ if len(names) > 0 {
+ tag := memberListProperty.dependencyTag
+ memberListProperty.memberType.AddDependencies(mctx, tag, names)
+ }
}
}
}
diff --git a/sdk/testing.go b/sdk/testing.go
index ae0620d..7352c74 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -61,6 +61,12 @@
config := android.TestArchConfig(buildDir, nil, bp, mockFS)
+ // Add windows as a default disable OS to test behavior when some OS variants
+ // are disabled.
+ config.Targets[android.Windows] = []android.Target{
+ {android.Windows, android.Arch{ArchType: android.X86_64}, android.NativeBridgeDisabled, "", ""},
+ }
+
ctx := android.NewTestArchContext()
// from android package
diff --git a/vnames.go.json b/vnames.go.json
index 5842097..7ce2d4b 100644
--- a/vnames.go.json
+++ b/vnames.go.json
@@ -3,7 +3,7 @@
"pattern": "(.*)",
"vname": {
"corpus": "android.googlesource.com/platform/superproject",
- "path": "build/soong/@1@"
+ "path": "@1@"
}
}
]