Merge "Allow guava to use java_host_for_device"
diff --git a/Android.bp b/Android.bp
index a4e6e7d..6b59f04 100644
--- a/Android.bp
+++ b/Android.bp
@@ -37,6 +37,7 @@
"blueprint-bootstrap",
"soong",
"soong-env",
+ "soong-shared",
],
srcs: [
"android/androidmk.go",
diff --git a/android/config.go b/android/config.go
index 0c9f957..0191e38 100644
--- a/android/config.go
+++ b/android/config.go
@@ -405,6 +405,10 @@
return fmt.Sprintf("%s/prebuilts/go/%s", c.srcDir, c.PrebuiltOS())
}
+func (c *config) PrebuiltBuildTool(ctx PathContext, tool string) Path {
+ return PathForSource(ctx, "prebuilts/build-tools", c.PrebuiltOS(), "bin", tool)
+}
+
func (c *config) CpPreserveSymlinksFlags() string {
switch runtime.GOOS {
case "darwin":
@@ -1048,3 +1052,7 @@
func (c *config) ProductHiddenAPIStubsTest() []string {
return c.productVariables.ProductHiddenAPIStubsTest
}
+
+func (c *deviceConfig) TargetFSConfigGen() *string {
+ return c.config.productVariables.TargetFSConfigGen
+}
diff --git a/android/paths.go b/android/paths.go
index 8cc7057..0f20b84 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1267,16 +1267,23 @@
// MaybeRel performs the same function as filepath.Rel, but reports errors to a PathContext, and returns false if
// targetPath is not inside basePath.
func MaybeRel(ctx PathContext, basePath string, targetPath string) (string, bool) {
+ rel, isRel, err := maybeRelErr(basePath, targetPath)
+ if err != nil {
+ reportPathError(ctx, err)
+ }
+ return rel, isRel
+}
+
+func maybeRelErr(basePath string, targetPath string) (string, bool, error) {
// filepath.Rel returns an error if one path is absolute and the other is not, handle that case first.
if filepath.IsAbs(basePath) != filepath.IsAbs(targetPath) {
- return "", false
+ return "", false, nil
}
rel, err := filepath.Rel(basePath, targetPath)
if err != nil {
- reportPathError(ctx, err)
- return "", false
+ return "", false, err
} else if rel == ".." || strings.HasPrefix(rel, "../") || strings.HasPrefix(rel, "/") {
- return "", false
+ return "", false, nil
}
- return rel, true
+ return rel, true, nil
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 2d0fac1..4a3b022 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -21,6 +21,8 @@
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+
+ "android/soong/shared"
)
// RuleBuilder provides an alternative to ModuleContext.Rule and ModuleContext.Build to add a command line to the build
@@ -30,6 +32,8 @@
installs RuleBuilderInstalls
temporariesSet map[WritablePath]bool
restat bool
+ sbox bool
+ sboxOutDir WritablePath
missingDeps []string
}
@@ -73,11 +77,36 @@
}
// Restat marks the rule as a restat rule, which will be passed to ModuleContext.Rule in BuildParams.Restat.
+//
+// Restat is not compatible with Sbox()
func (r *RuleBuilder) Restat() *RuleBuilder {
+ if r.sbox {
+ panic("Restat() is not compatible with Sbox()")
+ }
r.restat = true
return r
}
+// Sbox marks the rule as needing to be wrapped by sbox. The WritablePath should point to the output
+// directory that sbox will wipe. It should not be written to by any other rule. sbox will ensure
+// that all outputs have been written, and will discard any output files that were not specified.
+//
+// Sbox is not compatible with Restat()
+func (r *RuleBuilder) Sbox(outputDir WritablePath) *RuleBuilder {
+ if r.sbox {
+ panic("Sbox() may not be called more than once")
+ }
+ if len(r.commands) > 0 {
+ panic("Sbox() may not be called after Command()")
+ }
+ if r.restat {
+ panic("Sbox() is not compatible with Restat()")
+ }
+ r.sbox = true
+ r.sboxOutDir = outputDir
+ return r
+}
+
// Install associates an output of the rule with an install location, which can be retrieved later using
// RuleBuilder.Installs.
func (r *RuleBuilder) Install(from Path, to string) {
@@ -88,7 +117,10 @@
// created by this method. That can be mutated through their methods in any order, as long as the mutations do not
// race with any call to Build.
func (r *RuleBuilder) Command() *RuleBuilderCommand {
- command := &RuleBuilderCommand{}
+ command := &RuleBuilderCommand{
+ sbox: r.sbox,
+ sboxOutDir: r.sboxOutDir,
+ }
r.commands = append(r.commands, command)
return command
}
@@ -120,12 +152,16 @@
// that are also outputs of another command in the same RuleBuilder are filtered out.
func (r *RuleBuilder) Inputs() Paths {
outputs := r.outputSet()
+ depFiles := r.depFileSet()
inputs := make(map[string]Path)
for _, c := range r.commands {
for _, input := range c.inputs {
- if _, isOutput := outputs[input.String()]; !isOutput {
- inputs[input.String()] = input
+ inputStr := input.String()
+ if _, isOutput := outputs[inputStr]; !isOutput {
+ if _, isDepFile := depFiles[inputStr]; !isDepFile {
+ inputs[input.String()] = input
+ }
}
}
}
@@ -171,6 +207,16 @@
return outputList
}
+func (r *RuleBuilder) depFileSet() map[string]WritablePath {
+ depFiles := make(map[string]WritablePath)
+ for _, c := range r.commands {
+ for _, depFile := range c.depFiles {
+ depFiles[depFile.String()] = depFile
+ }
+ }
+ return depFiles
+}
+
// DepFiles returns the list of paths that were passed to the RuleBuilderCommand methods that take depfile paths, such
// as RuleBuilderCommand.DepFile or RuleBuilderCommand.FlagWithDepFile.
func (r *RuleBuilder) DepFiles() WritablePaths {
@@ -237,9 +283,9 @@
var _ BuilderContext = SingletonContext(nil)
func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand {
- return (&RuleBuilderCommand{}).
+ return r.Command().
Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).
- Flags(depFiles.Strings())
+ Inputs(depFiles.Paths())
}
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
@@ -259,9 +305,6 @@
return
}
- tools := r.Tools()
- commands := r.Commands()
-
var depFile WritablePath
var depFormat blueprint.Deps
if depFiles := r.DepFiles(); len(depFiles) > 0 {
@@ -269,37 +312,75 @@
depFormat = blueprint.DepsGCC
if len(depFiles) > 1 {
// Add a command locally that merges all depfiles together into the first depfile.
- cmd := r.depFileMergerCmd(ctx, depFiles)
- commands = append(commands, string(cmd.buf))
- tools = append(tools, cmd.tools...)
+ r.depFileMergerCmd(ctx, depFiles)
+
+ if r.sbox {
+ // Check for Rel() errors, as all depfiles should be in the output dir
+ for _, path := range depFiles[1:] {
+ Rel(ctx, r.sboxOutDir.String(), path.String())
+ }
+ }
}
}
+ tools := r.Tools()
+ commands := r.Commands()
+ outputs := r.Outputs()
+
+ if len(commands) == 0 {
+ return
+ }
+ if len(outputs) == 0 {
+ panic("No outputs specified from any Commands")
+ }
+
+ commandString := strings.Join(proptools.NinjaEscapeList(commands), " && ")
+
+ if r.sbox {
+ sboxOutputs := make([]string, len(outputs))
+ for i, output := range outputs {
+ sboxOutputs[i] = "__SBOX_OUT_DIR__/" + Rel(ctx, r.sboxOutDir.String(), output.String())
+ }
+
+ if depFile != nil {
+ sboxOutputs = append(sboxOutputs, "__SBOX_OUT_DIR__/"+Rel(ctx, r.sboxOutDir.String(), depFile.String()))
+ }
+
+ commandString = proptools.ShellEscape(commandString)
+ if !strings.HasPrefix(commandString, `'`) {
+ commandString = `'` + commandString + `'`
+ }
+
+ sboxCmd := &RuleBuilderCommand{}
+ sboxCmd.Tool(ctx.Config().HostToolPath(ctx, "sbox")).
+ Flag("-c").Text(commandString).
+ Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())).
+ Flag("--output-root").Text(r.sboxOutDir.String()).
+ Flags(sboxOutputs)
+
+ commandString = string(sboxCmd.buf)
+ tools = append(tools, sboxCmd.tools...)
+ }
+
// Ninja doesn't like multiple outputs when depfiles are enabled, move all but the first output to
// ImplicitOutputs. RuleBuilder never uses "$out", so the distinction between Outputs and ImplicitOutputs
// doesn't matter.
- var output WritablePath
- var implicitOutputs WritablePaths
- if outputs := r.Outputs(); len(outputs) > 0 {
- output = outputs[0]
- implicitOutputs = outputs[1:]
- }
+ output := outputs[0]
+ implicitOutputs := outputs[1:]
- if len(commands) > 0 {
- ctx.Build(pctx, BuildParams{
- Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
- Command: strings.Join(proptools.NinjaEscapeList(commands), " && "),
- CommandDeps: tools.Strings(),
- Restat: r.restat,
- }),
- Implicits: r.Inputs(),
- Output: output,
- ImplicitOutputs: implicitOutputs,
- Depfile: depFile,
- Deps: depFormat,
- Description: desc,
- })
- }
+ ctx.Build(pctx, BuildParams{
+ Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
+ Command: commandString,
+ CommandDeps: tools.Strings(),
+ Restat: r.restat,
+ }),
+ Implicits: r.Inputs(),
+ Output: output,
+ ImplicitOutputs: implicitOutputs,
+ Depfile: depFile,
+ Deps: depFormat,
+ Description: desc,
+ })
}
// RuleBuilderCommand is a builder for a command in a command line. It can be mutated by its methods to add to the
@@ -312,6 +393,28 @@
outputs WritablePaths
depFiles WritablePaths
tools Paths
+
+ sbox bool
+ sboxOutDir WritablePath
+}
+
+func (c *RuleBuilderCommand) addInput(path Path) string {
+ if c.sbox {
+ if rel, isRel, _ := maybeRelErr(c.sboxOutDir.String(), path.String()); isRel {
+ return "__SBOX_OUT_DIR__/" + rel
+ }
+ }
+ c.inputs = append(c.inputs, path)
+ return path.String()
+}
+
+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
+ rel, _, _ := maybeRelErr(c.sboxOutDir.String(), path.String())
+ return "__SBOX_OUT_DIR__/" + rel
+ }
+ return path.String()
}
// Text adds the specified raw text to the command line. The text should not contain input or output paths or the
@@ -378,8 +481,7 @@
// Input adds the specified input path to the command line. The path will also be added to the dependencies returned by
// RuleBuilder.Inputs.
func (c *RuleBuilderCommand) Input(path Path) *RuleBuilderCommand {
- c.inputs = append(c.inputs, path)
- return c.Text(path.String())
+ return c.Text(c.addInput(path))
}
// Inputs adds the specified input paths to the command line, separated by spaces. The paths will also be added to the
@@ -394,14 +496,16 @@
// Implicit adds the specified input path to the dependencies returned by RuleBuilder.Inputs without modifying the
// command line.
func (c *RuleBuilderCommand) Implicit(path Path) *RuleBuilderCommand {
- c.inputs = append(c.inputs, path)
+ c.addInput(path)
return c
}
// Implicits adds the specified input paths to the dependencies returned by RuleBuilder.Inputs without modifying the
// command line.
func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand {
- c.inputs = append(c.inputs, paths...)
+ for _, path := range paths {
+ c.addInput(path)
+ }
return c
}
@@ -409,7 +513,7 @@
// RuleBuilder.Outputs.
func (c *RuleBuilderCommand) Output(path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
- return c.Text(path.String())
+ return c.Text(c.outputStr(path))
}
// Outputs adds the specified output paths to the command line, separated by spaces. The paths will also be added to
@@ -426,7 +530,7 @@
// commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the depfiles together.
func (c *RuleBuilderCommand) DepFile(path WritablePath) *RuleBuilderCommand {
c.depFiles = append(c.depFiles, path)
- return c.Text(path.String())
+ return c.Text(c.outputStr(path))
}
// ImplicitOutput adds the specified output path to the dependencies returned by RuleBuilder.Outputs without modifying
@@ -455,16 +559,18 @@
// FlagWithInput adds the specified flag and input path to the command line, with no separator between them. The path
// will also be added to the dependencies returned by RuleBuilder.Inputs.
func (c *RuleBuilderCommand) FlagWithInput(flag string, path Path) *RuleBuilderCommand {
- c.inputs = append(c.inputs, path)
- return c.Text(flag + path.String())
+ return c.Text(flag + c.addInput(path))
}
// FlagWithInputList adds the specified flag and input paths to the command line, with the inputs joined by sep
// and no separator between the flag and inputs. The input paths will also be added to the dependencies returned by
// RuleBuilder.Inputs.
func (c *RuleBuilderCommand) FlagWithInputList(flag string, paths Paths, sep string) *RuleBuilderCommand {
- c.inputs = append(c.inputs, paths...)
- return c.FlagWithList(flag, paths.Strings(), sep)
+ strs := make([]string, len(paths))
+ for i, path := range paths {
+ strs[i] = c.addInput(path)
+ }
+ return c.FlagWithList(flag, strs, sep)
}
// FlagForEachInput adds the specified flag joined with each input path to the command line. The input paths will also
@@ -481,14 +587,14 @@
// will also be added to the outputs returned by RuleBuilder.Outputs.
func (c *RuleBuilderCommand) FlagWithOutput(flag string, path WritablePath) *RuleBuilderCommand {
c.outputs = append(c.outputs, path)
- return c.Text(flag + path.String())
+ return c.Text(flag + c.outputStr(path))
}
// FlagWithDepFile adds the specified flag and depfile path to the command line, with no separator between them. The path
// will also be added to the outputs returned by RuleBuilder.Outputs.
func (c *RuleBuilderCommand) FlagWithDepFile(flag string, path WritablePath) *RuleBuilderCommand {
c.depFiles = append(c.depFiles, path)
- return c.Text(flag + path.String())
+ return c.Text(flag + c.outputStr(path))
}
// String returns the command line.
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index 7bad025..df0f256 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -22,6 +22,10 @@
"reflect"
"strings"
"testing"
+
+ "github.com/google/blueprint"
+
+ "android/soong/shared"
)
func pathContext() PathContext {
@@ -234,8 +238,6 @@
}
func TestRuleBuilder(t *testing.T) {
- rule := NewRuleBuilder()
-
fs := map[string][]byte{
"dep_fixer": nil,
"input": nil,
@@ -249,73 +251,114 @@
ctx := PathContextForTesting(TestConfig("out", nil), fs)
- cmd := rule.Command().
- DepFile(PathForOutput(ctx, "DepFile")).
- Flag("Flag").
- FlagWithArg("FlagWithArg=", "arg").
- FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "depfile")).
- FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
- FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "output")).
- Implicit(PathForSource(ctx, "Implicit")).
- ImplicitDepFile(PathForOutput(ctx, "ImplicitDepFile")).
- ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
- Input(PathForSource(ctx, "Input")).
- Output(PathForOutput(ctx, "Output")).
- Text("Text").
- Tool(PathForSource(ctx, "Tool"))
+ addCommands := func(rule *RuleBuilder) {
+ cmd := rule.Command().
+ DepFile(PathForOutput(ctx, "DepFile")).
+ Flag("Flag").
+ FlagWithArg("FlagWithArg=", "arg").
+ FlagWithDepFile("FlagWithDepFile=", PathForOutput(ctx, "depfile")).
+ FlagWithInput("FlagWithInput=", PathForSource(ctx, "input")).
+ FlagWithOutput("FlagWithOutput=", PathForOutput(ctx, "output")).
+ Implicit(PathForSource(ctx, "Implicit")).
+ ImplicitDepFile(PathForOutput(ctx, "ImplicitDepFile")).
+ ImplicitOutput(PathForOutput(ctx, "ImplicitOutput")).
+ Input(PathForSource(ctx, "Input")).
+ Output(PathForOutput(ctx, "Output")).
+ Text("Text").
+ Tool(PathForSource(ctx, "Tool"))
- rule.Command().
- Text("command2").
- DepFile(PathForOutput(ctx, "depfile2")).
- Input(PathForSource(ctx, "input2")).
- Output(PathForOutput(ctx, "output2")).
- Tool(PathForSource(ctx, "tool2"))
+ rule.Command().
+ Text("command2").
+ DepFile(PathForOutput(ctx, "depfile2")).
+ Input(PathForSource(ctx, "input2")).
+ Output(PathForOutput(ctx, "output2")).
+ Tool(PathForSource(ctx, "tool2"))
- // Test updates to the first command after the second command has been started
- cmd.Text("after command2")
- // Test updating a command when the previous update did not replace the cmd variable
- cmd.Text("old cmd")
+ // Test updates to the first command after the second command has been started
+ cmd.Text("after command2")
+ // Test updating a command when the previous update did not replace the cmd variable
+ cmd.Text("old cmd")
- // Test a command that uses the output of a previous command as an input
- rule.Command().
- Text("command3").
- Input(PathForSource(ctx, "input3")).
- Input(PathForOutput(ctx, "output2")).
- Output(PathForOutput(ctx, "output3"))
-
- wantCommands := []string{
- "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd",
- "command2 out/depfile2 input2 out/output2 tool2",
- "command3 input3 out/output2 out/output3",
+ // Test a command that uses the output of a previous command as an input
+ rule.Command().
+ Text("command3").
+ Input(PathForSource(ctx, "input3")).
+ Input(PathForOutput(ctx, "output2")).
+ Output(PathForOutput(ctx, "output3"))
}
- wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer out/DepFile out/depfile out/ImplicitDepFile out/depfile2"
-
wantInputs := PathsForSource(ctx, []string{"Implicit", "Input", "input", "input2", "input3"})
wantOutputs := PathsForOutput(ctx, []string{"ImplicitOutput", "Output", "output", "output2", "output3"})
wantDepFiles := PathsForOutput(ctx, []string{"DepFile", "depfile", "ImplicitDepFile", "depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
- if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
- t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
- }
+ t.Run("normal", func(t *testing.T) {
+ rule := NewRuleBuilder()
+ addCommands(rule)
- if g, w := rule.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
- t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
- }
+ wantCommands := []string{
+ "out/DepFile Flag FlagWithArg=arg FlagWithDepFile=out/depfile FlagWithInput=input FlagWithOutput=out/output Input out/Output Text Tool after command2 old cmd",
+ "command2 out/depfile2 input2 out/output2 tool2",
+ "command3 input3 out/output2 out/output3",
+ }
- if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
- }
- if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
- }
- if g, w := rule.Tools(), wantTools; !reflect.DeepEqual(w, g) {
- t.Errorf("\nwant rule.Tools() = %#v\n got %#v", w, g)
- }
+ wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer out/DepFile out/depfile out/ImplicitDepFile out/depfile2"
+
+ if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
+ t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
+ }
+
+ if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
+ }
+ 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.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
+ t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
+ }
+ })
+
+ t.Run("sbox", func(t *testing.T) {
+ rule := NewRuleBuilder().Sbox(PathForOutput(ctx))
+ addCommands(rule)
+
+ wantCommands := []string{
+ "__SBOX_OUT_DIR__/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_OUT_DIR__/depfile FlagWithInput=input FlagWithOutput=__SBOX_OUT_DIR__/output Input __SBOX_OUT_DIR__/Output Text Tool after command2 old cmd",
+ "command2 __SBOX_OUT_DIR__/depfile2 input2 __SBOX_OUT_DIR__/output2 tool2",
+ "command3 input3 __SBOX_OUT_DIR__/output2 __SBOX_OUT_DIR__/output3",
+ }
+
+ wantDepMergerCommand := "out/host/" + ctx.Config().PrebuiltOS() + "/bin/dep_fixer __SBOX_OUT_DIR__/DepFile __SBOX_OUT_DIR__/depfile __SBOX_OUT_DIR__/ImplicitDepFile __SBOX_OUT_DIR__/depfile2"
+
+ if g, w := rule.Commands(), wantCommands; !reflect.DeepEqual(g, w) {
+ t.Errorf("\nwant rule.Commands() = %#v\n got %#v", w, g)
+ }
+
+ if g, w := rule.Inputs(), wantInputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Inputs() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.Outputs(), wantOutputs; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.Outputs() = %#v\n got %#v", w, g)
+ }
+ if g, w := rule.DepFiles(), wantDepFiles; !reflect.DeepEqual(w, g) {
+ t.Errorf("\nwant rule.DepFiles() = %#v\n got %#v", w, g)
+ }
+ 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.depFileMergerCmd(ctx, rule.DepFiles()).String(), wantDepMergerCommand; g != w {
+ t.Errorf("\nwant rule.depFileMergerCmd() = %#v\n got %#v", w, g)
+ }
+ })
}
func testRuleBuilderFactory() Module {
@@ -329,14 +372,19 @@
ModuleBase
properties struct {
Src string
+
+ Restat bool
+ Sbox bool
}
}
func (t *testRuleBuilderModule) GenerateAndroidBuildActions(ctx ModuleContext) {
in := PathForSource(ctx, t.properties.Src)
out := PathForModuleOut(ctx, ctx.ModuleName())
+ outDep := PathForModuleOut(ctx, ctx.ModuleName()+".d")
+ outDir := PathForModuleOut(ctx)
- testRuleBuilder_Build(ctx, in, out)
+ testRuleBuilder_Build(ctx, in, out, outDep, outDir, t.properties.Restat, t.properties.Sbox)
}
type testRuleBuilderSingleton struct{}
@@ -348,15 +396,23 @@
func (t *testRuleBuilderSingleton) GenerateBuildActions(ctx SingletonContext) {
in := PathForSource(ctx, "bar")
out := PathForOutput(ctx, "baz")
- testRuleBuilder_Build(ctx, in, out)
+ outDep := PathForOutput(ctx, "baz.d")
+ outDir := PathForOutput(ctx)
+ testRuleBuilder_Build(ctx, in, out, outDep, outDir, true, false)
}
-func testRuleBuilder_Build(ctx BuilderContext, in Path, out WritablePath) {
+func testRuleBuilder_Build(ctx BuilderContext, in Path, out, outDep, outDir WritablePath, restat, sbox bool) {
rule := NewRuleBuilder()
- rule.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out)
+ if sbox {
+ rule.Sbox(outDir)
+ }
- rule.Restat()
+ rule.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out).ImplicitDepFile(outDep)
+
+ if restat {
+ rule.Restat()
+ }
rule.Build(pctx, ctx, "rule", "desc")
}
@@ -372,6 +428,12 @@
rule_builder_test {
name: "foo",
src: "bar",
+ restat: true,
+ }
+ rule_builder_test {
+ name: "foo_sbox",
+ src: "bar",
+ sbox: true,
}
`
@@ -391,9 +453,18 @@
_, errs = ctx.PrepareBuildActions(config)
FailIfErrored(t, errs)
- check := func(t *testing.T, params TestingBuildParams, wantOutput string) {
- if len(params.RuleParams.CommandDeps) != 1 || params.RuleParams.CommandDeps[0] != "cp" {
- t.Errorf("want RuleParams.CommandDeps = [%q], got %q", "cp", params.RuleParams.CommandDeps)
+ check := func(t *testing.T, params TestingBuildParams, wantCommand, wantOutput, wantDepfile string, wantRestat bool, extraCmdDeps []string) {
+ if params.RuleParams.Command != wantCommand {
+ t.Errorf("\nwant RuleParams.Command = %q\n got %q", wantCommand, params.RuleParams.Command)
+ }
+
+ wantDeps := append([]string{"cp"}, extraCmdDeps...)
+ if !reflect.DeepEqual(params.RuleParams.CommandDeps, wantDeps) {
+ t.Errorf("\nwant RuleParams.CommandDeps = %q\n got %q", wantDeps, params.RuleParams.CommandDeps)
+ }
+
+ if params.RuleParams.Restat != wantRestat {
+ t.Errorf("want RuleParams.Restat = %v, got %v", wantRestat, params.RuleParams.Restat)
}
if len(params.Implicits) != 1 || params.Implicits[0].String() != "bar" {
@@ -404,17 +475,39 @@
t.Errorf("want Output = %q, got %q", wantOutput, params.Output)
}
- if !params.RuleParams.Restat {
- t.Errorf("want RuleParams.Restat = true, got %v", params.RuleParams.Restat)
+ if len(params.ImplicitOutputs) != 0 {
+ t.Errorf("want ImplicitOutputs = [], got %q", params.ImplicitOutputs.Strings())
+ }
+
+ if params.Depfile.String() != wantDepfile {
+ t.Errorf("want Depfile = %q, got %q", wantDepfile, params.Depfile)
+ }
+
+ if params.Deps != blueprint.DepsGCC {
+ t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
}
}
t.Run("module", func(t *testing.T) {
+ outFile := filepath.Join(buildDir, ".intermediates", "foo", "foo")
check(t, ctx.ModuleForTests("foo", "").Rule("rule"),
- filepath.Join(buildDir, ".intermediates", "foo", "foo"))
+ "cp bar "+outFile,
+ outFile, outFile+".d", true, nil)
+ })
+ t.Run("sbox", func(t *testing.T) {
+ outDir := filepath.Join(buildDir, ".intermediates", "foo_sbox")
+ outFile := filepath.Join(outDir, "foo_sbox")
+ sbox := filepath.Join(buildDir, "host", config.PrebuiltOS(), "bin/sbox")
+ sandboxPath := shared.TempDirForOutDir(buildDir)
+
+ cmd := sbox + ` -c 'cp bar __SBOX_OUT_DIR__/foo_sbox' --sandbox-path ` + sandboxPath + " --output-root " + outDir + " __SBOX_OUT_DIR__/foo_sbox __SBOX_OUT_DIR__/foo_sbox.d"
+
+ check(t, ctx.ModuleForTests("foo_sbox", "").Rule("rule"),
+ cmd, outFile, outFile+".d", false, []string{sbox})
})
t.Run("singleton", func(t *testing.T) {
+ outFile := filepath.Join(buildDir, "baz")
check(t, ctx.SingletonForTests("rule_builder_test").Rule("rule"),
- filepath.Join(buildDir, "baz"))
+ "cp bar "+outFile, outFile, outFile+".d", true, nil)
})
}
diff --git a/android/variable.go b/android/variable.go
index 16d7b13..666f29f 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -287,6 +287,8 @@
ProductHiddenAPIStubs []string `json:",omitempty"`
ProductHiddenAPIStubsSystem []string `json:",omitempty"`
ProductHiddenAPIStubsTest []string `json:",omitempty"`
+
+ TargetFSConfigGen *string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index e0932af..b54ad5e 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -131,7 +131,7 @@
"LOCAL_OVERRIDES_MODULES": "overrides",
"LOCAL_LDLIBS": "host_ldlibs",
"LOCAL_CLANG_CFLAGS": "clang_cflags",
- "LOCAL_YACCFLAGS": "yaccflags",
+ "LOCAL_YACCFLAGS": "yacc.flags",
"LOCAL_SANITIZE_RECOVER": "sanitize.recover",
"LOCAL_LOGTAGS_FILES": "logtags",
"LOCAL_EXPORT_HEADER_LIBRARY_HEADERS": "export_header_lib_headers",
diff --git a/apex/key.go b/apex/key.go
index a627e4b..229d593 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -55,8 +55,7 @@
func apexKeyFactory() android.Module {
module := &apexKey{}
module.AddProperties(&module.properties)
- // This module is device-only
- android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
+ android.InitAndroidArchModule(module, android.HostAndDeviceDefault, android.MultilibCommon)
return module
}
diff --git a/cc/builder.go b/cc/builder.go
index 65369d6..87db645 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -239,7 +239,6 @@
cppFlags string
ldFlags string
libFlags string
- yaccFlags string
tidyFlags string
sAbiFlags string
yasmFlags string
@@ -262,6 +261,8 @@
proto android.ProtoFlags
protoC bool
protoOptionsFile bool
+
+ yacc *YaccProperties
}
type Objects struct {
diff --git a/cc/cc.go b/cc/cc.go
index 0668fd9..bec39ca 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -136,7 +136,6 @@
ConlyFlags []string // Flags that apply to C source files
CppFlags []string // Flags that apply to C++ source files
ToolingCppFlags []string // Flags that apply to C++ source files parsed by clang LibTooling tools
- YaccFlags []string // Flags that apply to Yacc source files
aidlFlags []string // Flags that apply to aidl source files
rsFlags []string // Flags that apply to renderscript source files
LdFlags []string // Flags that apply to linker command lines
@@ -165,6 +164,8 @@
proto android.ProtoFlags
protoC bool // Whether to use C instead of C++
protoOptionsFile bool // Whether to look for a .options file next to the .proto
+
+ Yacc *YaccProperties
}
type ObjectLinkerProperties struct {
diff --git a/cc/compiler.go b/cc/compiler.go
index f9af4d8..7667ae7 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -57,9 +57,6 @@
// compiling with clang
Clang_asflags []string `android:"arch_variant"`
- // list of module-specific flags that will be used for .y and .yy compiles
- Yaccflags []string
-
// the instruction set architecture to use to compile the C/C++
// module.
Instruction_set *string `android:"arch_variant"`
@@ -103,6 +100,8 @@
// if set to false, use -std=c++* instead of -std=gnu++*
Gnu_extensions *bool
+ Yacc *YaccProperties
+
Aidl struct {
// list of directories that will be added to the aidl include paths.
Include_dirs []string
@@ -275,7 +274,8 @@
flags.ConlyFlags = append(flags.ConlyFlags, esc(compiler.Properties.Conlyflags)...)
flags.AsFlags = append(flags.AsFlags, esc(compiler.Properties.Asflags)...)
flags.YasmFlags = append(flags.YasmFlags, esc(compiler.Properties.Asflags)...)
- flags.YaccFlags = append(flags.YaccFlags, esc(compiler.Properties.Yaccflags)...)
+
+ flags.Yacc = compiler.Properties.Yacc
// Include dir cflags
localIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Local_include_dirs)
diff --git a/cc/config/global.go b/cc/config/global.go
index 78f24f2..8fc9ff2 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -83,6 +83,7 @@
"-Wl,--warn-shared-textrel",
"-Wl,--fatal-warnings",
"-Wl,--no-undefined-version",
+ "-Wl,--exclude-libs,libgcc.a",
}
deviceGlobalLldflags = append(ClangFilterUnknownLldflags(deviceGlobalLdflags),
diff --git a/cc/gen.go b/cc/gen.go
index 0c3d089..ae761d0 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -24,21 +24,12 @@
func init() {
pctx.SourcePathVariable("lexCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/flex")
- pctx.SourcePathVariable("yaccCmd", "prebuilts/build-tools/${config.HostPrebuiltTag}/bin/bison")
- pctx.SourcePathVariable("yaccDataDir", "prebuilts/build-tools/common/bison")
pctx.HostBinToolVariable("aidlCmd", "aidl-cpp")
pctx.HostBinToolVariable("syspropCmd", "sysprop_cpp")
}
var (
- yacc = pctx.AndroidStaticRule("yacc",
- blueprint.RuleParams{
- Command: "BISON_PKGDATADIR=$yaccDataDir $yaccCmd -d $yaccFlags --defines=$hFile -o $out $in",
- CommandDeps: []string{"$yaccCmd"},
- },
- "yaccFlags", "hFile")
-
lex = pctx.AndroidStaticRule("lex",
blueprint.RuleParams{
Command: "$lexCmd -o$out $in",
@@ -70,22 +61,57 @@
"windmcCmd")
)
-func genYacc(ctx android.ModuleContext, yaccFile android.Path, outFile android.ModuleGenPath, yaccFlags string) (headerFile android.ModuleGenPath) {
- headerFile = android.GenPathWithExt(ctx, "yacc", yaccFile, "h")
+type YaccProperties struct {
+ // list of module-specific flags that will be used for .y and .yy compiles
+ Flags []string
- ctx.Build(pctx, android.BuildParams{
- Rule: yacc,
- Description: "yacc " + yaccFile.Rel(),
- Output: outFile,
- ImplicitOutput: headerFile,
- Input: yaccFile,
- Args: map[string]string{
- "yaccFlags": yaccFlags,
- "hFile": headerFile.String(),
- },
- })
+ // whether the yacc files will produce a location.hh file
+ Gen_location_hh *bool
- return headerFile
+ // whether the yacc files will product a position.hh file
+ Gen_position_hh *bool
+}
+
+func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile android.Path,
+ outFile android.ModuleGenPath, props *YaccProperties) (headerFiles android.Paths) {
+
+ outDir := android.PathForModuleGen(ctx, "yacc")
+ headerFile := android.GenPathWithExt(ctx, "yacc", yaccFile, "h")
+ ret := android.Paths{headerFile}
+
+ cmd := rule.Command()
+
+ // Fix up #line markers to not use the sbox temporary directory
+ sedCmd := "sed -i.bak 's#__SBOX_OUT_DIR__#" + outDir.String() + "#'"
+ rule.Command().Text(sedCmd).Input(outFile)
+ rule.Command().Text(sedCmd).Input(headerFile)
+
+ var flags []string
+ if props != nil {
+ flags = props.Flags
+
+ if Bool(props.Gen_location_hh) {
+ locationHeader := outFile.InSameDir(ctx, "location.hh")
+ ret = append(ret, locationHeader)
+ cmd.ImplicitOutput(locationHeader)
+ rule.Command().Text(sedCmd).Input(locationHeader)
+ }
+ if Bool(props.Gen_position_hh) {
+ positionHeader := outFile.InSameDir(ctx, "position.hh")
+ ret = append(ret, positionHeader)
+ cmd.ImplicitOutput(positionHeader)
+ rule.Command().Text(sedCmd).Input(positionHeader)
+ }
+ }
+
+ cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison").
+ Tool(ctx.Config().PrebuiltBuildTool(ctx, "bison")).
+ Flag("-d").
+ Flags(flags).
+ FlagWithOutput("--defines=", headerFile).
+ Flag("-o").Output(outFile).Input(yaccFile)
+
+ return ret
}
func genAidl(ctx android.ModuleContext, aidlFile android.Path, outFile android.ModuleGenPath, aidlFlags string) android.Paths {
@@ -159,19 +185,26 @@
buildFlags builderFlags) (android.Paths, android.Paths) {
var deps android.Paths
-
var rsFiles android.Paths
+ var yaccRule_ *android.RuleBuilder
+ yaccRule := func() *android.RuleBuilder {
+ if yaccRule_ == nil {
+ yaccRule_ = android.NewRuleBuilder().Sbox(android.PathForModuleGen(ctx, "yacc"))
+ }
+ return yaccRule_
+ }
+
for i, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".y":
cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c")
srcFiles[i] = cFile
- deps = append(deps, genYacc(ctx, srcFile, cFile, buildFlags.yaccFlags))
+ deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...)
case ".yy":
cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp")
srcFiles[i] = cppFile
- deps = append(deps, genYacc(ctx, srcFile, cppFile, buildFlags.yaccFlags))
+ deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...)
case ".l":
cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c")
srcFiles[i] = cFile
@@ -203,6 +236,10 @@
}
}
+ if yaccRule_ != nil {
+ yaccRule_.Build(pctx, ctx, "yacc", "gen yacc")
+ }
+
if len(rsFiles) > 0 {
deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...)
}
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 5a36b7f..3e25481 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -189,6 +189,14 @@
return module
}
+// llndk_library creates a stub llndk shared library based on the provided
+// version file. Example:
+//
+// llndk_library {
+// name: "libfoo",
+// symbol_file: "libfoo.map.txt",
+// export_include_dirs: ["include_vndk"],
+// }
func LlndkLibraryFactory() android.Module {
module := NewLLndkStubLibrary()
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
@@ -203,6 +211,8 @@
return name + llndkHeadersSuffix
}
+// llndk_headers contains a set of c/c++ llndk headers files which are imported
+// by other soongs cc modules.
func llndkHeadersFactory() android.Module {
module, library := NewLibrary(android.DeviceSupported)
library.HeaderOnly()
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index 5e45c1a..4065128 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -159,6 +159,16 @@
}
}
+// ndk_headers installs the sets of ndk headers defined in the srcs property
+// to the sysroot base + "usr/include" + to directory + directory component.
+// ndk_headers requires the license file to be specified. Example:
+//
+// Given:
+// sysroot base = "ndk/sysroot"
+// from = "include/foo"
+// to = "bar"
+// header = "include/foo/woodly/doodly.h"
+// output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
func ndkHeadersFactory() android.Module {
module := &headerModule{}
module.AddProperties(&module.properties)
@@ -278,6 +288,11 @@
return timestampFile
}
+// versioned_ndk_headers preprocesses the headers with the bionic versioner:
+// https://android.googlesource.com/platform/bionic/+/master/tools/versioner/README.md.
+// Unlike the ndk_headers soong module, versioned_ndk_headers operates on a
+// directory level specified in `from` property. This is only used to process
+// the bionic/libc/include directory.
func versionedNdkHeadersFactory() android.Module {
module := &versionedHeaderModule{}
@@ -360,6 +375,8 @@
}
}
+// preprocessed_ndk_headers preprocesses all the ndk headers listed in the srcs
+// property by executing the command defined in the preprocessor property.
func preprocessedNdkHeadersFactory() android.Module {
module := &preprocessedHeadersModule{}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 7199467..c63b200 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -377,6 +377,8 @@
return module
}
+// ndk_library creates a stub library that exposes dummy implementation
+// of functions and variables for use at build time only.
func ndkLibraryFactory() android.Module {
module := newStubLibrary()
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
diff --git a/cc/stl.go b/cc/stl.go
index e59f677..1a5dd79 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -245,7 +245,10 @@
ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String())
case "ndk_libc++_shared", "ndk_libc++_static":
- // Nothing.
+ if ctx.Arch().ArchType == android.Arm {
+ // Make sure the _Unwind_XXX symbols are not re-exported.
+ flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind.a")
+ }
case "":
// None or error.
if !ctx.toolchain().Bionic() {
diff --git a/cc/toolchain_library.go b/cc/toolchain_library.go
index ae08b1c..6494a26 100644
--- a/cc/toolchain_library.go
+++ b/cc/toolchain_library.go
@@ -48,6 +48,9 @@
return append(props, &library.Properties)
}
+// toolchain_library is used internally by the build tool to link the specified
+// static library in src property to the device libraries that are shipped with
+// gcc.
func ToolchainLibraryFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
diff --git a/cc/util.go b/cc/util.go
index 5dcbaef..3862728 100644
--- a/cc/util.go
+++ b/cc/util.go
@@ -67,7 +67,6 @@
toolingCppFlags: strings.Join(in.ToolingCppFlags, " "),
conlyFlags: strings.Join(in.ConlyFlags, " "),
cppFlags: strings.Join(in.CppFlags, " "),
- yaccFlags: strings.Join(in.YaccFlags, " "),
aidlFlags: strings.Join(in.aidlFlags, " "),
rsFlags: strings.Join(in.rsFlags, " "),
ldFlags: strings.Join(in.LdFlags, " "),
@@ -87,6 +86,8 @@
proto: in.proto,
protoC: in.protoC,
protoOptionsFile: in.protoOptionsFile,
+
+ yacc: in.Yacc,
}
}
diff --git a/cc/vendor_public_library.go b/cc/vendor_public_library.go
index da41cbc..2072ad9 100644
--- a/cc/vendor_public_library.go
+++ b/cc/vendor_public_library.go
@@ -122,6 +122,15 @@
return stub.libraryDecorator.link(ctx, flags, deps, objs)
}
+// vendor_public_library creates a stub shared library for a vendor public
+// library. This stub library is a build-time only artifact that provides
+// symbols that are exposed from a vendor public library. Example:
+//
+// vendor_public_library {
+// name: "libfoo",
+// symbol_file: "libfoo.map.txt",
+// export_public_headers: ["libfoo_headers"],
+// }
func vendorPublicLibraryFactory() android.Module {
module, library := NewLibrary(android.DeviceSupported)
library.BuildOnlyShared()
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index a399b28..c2ad944 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -328,6 +328,9 @@
{{- if .IsAar}}
min_sdk_version: "{{.MinSdkVersion}}",
static_libs: [
+ {{- range .BpJarDeps}}
+ "{{.}}",
+ {{- end}}
{{- range .BpAarDeps}}
"{{.}}",
{{- end}}
@@ -349,7 +352,7 @@
{{- end}}
static_libs: [
"{{.BpName}}-nodeps",
- {{- range .BpJarDeps}}
+ {{- range .BpJarDeps}}
"{{.}}",
{{- end}}
{{- range .BpAarDeps}}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index 4167edb..4ac9295 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -56,7 +56,7 @@
}
fmt.Fprintf(os.Stderr,
- "Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> --overwrite [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
+ "Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
"\n"+
"Deletes <outputRoot>,"+
"runs <commandToRun>,"+
diff --git a/cmd/soong_build/writedocs.go b/cmd/soong_build/writedocs.go
index d011e77..9424b6c 100644
--- a/cmd/soong_build/writedocs.go
+++ b/cmd/soong_build/writedocs.go
@@ -152,7 +152,6 @@
<html>
<head>
<title>Build Docs</title>
-<link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/vc67ef93e81a468795c57df87eca3f8427d65cbe85f09fbb51c82a12b89aa3d7e/androidsource/css/app.css">
<style>
#main {
padding: 48px;
@@ -165,6 +164,99 @@
td {
word-wrap:break-word;
}
+
+/* The following entries are copied from source.android.com's css file. */
+td,td code {
+ color: #202124
+}
+
+th,th code {
+ color: #fff;
+ font: 500 16px/24px Roboto,sans-serif
+}
+
+td,table.responsive tr:not(.alt) td td:first-child,table.responsive td tr:not(.alt) td:first-child {
+ background: rgba(255,255,255,.95);
+ vertical-align: top
+}
+
+td,td code {
+ padding: 7px 8px 8px
+}
+
+tr {
+ border: 0;
+ background: #78909c;
+ border-top: 1px solid #cfd8dc
+}
+
+th,td {
+ border: 0;
+ margin: 0;
+ text-align: left
+}
+
+th {
+ height: 48px;
+ padding: 8px;
+ vertical-align: middle
+}
+
+table {
+ border: 0;
+ border-collapse: collapse;
+ border-spacing: 0;
+ font: 14px/20px Roboto,sans-serif;
+ margin: 16px 0;
+ width: 100%
+}
+
+h1 {
+ color: #80868b;
+ font: 300 34px/40px Roboto,sans-serif;
+ letter-spacing: -0.01em;
+ margin: 40px 0 20px
+}
+
+h1,h2,h3,h4,h5,h6 {
+ overflow: hidden;
+ padding: 0;
+ text-overflow: ellipsis
+}
+
+:link,:visited {
+ color: #039be5;
+ outline: 0;
+ text-decoration: none
+}
+
+body,html {
+ color: #202124;
+ font: 400 16px/24px Roboto,sans-serif;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-font-smoothing: antialiased;
+ height: 100%;
+ margin: 0;
+ -webkit-text-size-adjust: 100%;
+ -moz-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+ text-size-adjust: 100%
+}
+
+html {
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box
+}
+
+*,*::before,*::after {
+ -webkit-box-sizing: inherit;
+ box-sizing: inherit
+}
+
+body,div,dl,dd,form,img,input,figure,menu {
+ margin: 0;
+ padding: 0
+}
</style>
{{template "copyBaseUrl"}}
</head>
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index a23b477..cb2ea9f 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -57,6 +57,7 @@
dir android.OutputPath
symbolsDir android.OutputPath
images map[android.ArchType]android.OutputPath
+ zip android.WritablePath
}
type bootImage struct {
@@ -187,6 +188,8 @@
profile := bootImageProfileRule(ctx, image, missingDeps)
+ var allFiles android.Paths
+
if !global.DisablePreopt {
targets := ctx.Config().Targets[android.Android]
if ctx.Config().SecondArchIsTranslated() {
@@ -194,15 +197,27 @@
}
for _, target := range targets {
- buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+ files := buildBootImageRuleForArch(ctx, image, target.Arch.ArchType, profile, missingDeps)
+ allFiles = append(allFiles, files.Paths()...)
}
}
+ if image.zip != nil {
+ rule := android.NewRuleBuilder()
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
+ FlagWithOutput("-o ", image.zip).
+ FlagWithArg("-C ", image.dir.String()).
+ FlagWithInputList("-f ", allFiles, " -f ")
+
+ rule.Build(pctx, ctx, "zip_"+image.name, "zip "+image.name+" image")
+ }
+
return image
}
func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage,
- arch android.ArchType, profile android.Path, missingDeps []string) {
+ arch android.ArchType, profile android.Path, missingDeps []string) android.WritablePaths {
global := dexpreoptGlobalConfig(ctx)
@@ -290,6 +305,8 @@
var vdexInstalls android.RuleBuilderInstalls
var unstrippedInstalls android.RuleBuilderInstalls
+ var zipFiles android.WritablePaths
+
// dex preopt on the bootclasspath produces multiple files. The first dex file
// is converted into to 'name'.art (to match the legacy assumption that 'name'.art
// exists), and the rest are converted to 'name'-<jar>.art.
@@ -308,6 +325,8 @@
extraFiles = append(extraFiles, art, oat, vdex, unstrippedOat)
+ zipFiles = append(zipFiles, art, oat, vdex)
+
// Install the .oat and .art files.
rule.Install(art, filepath.Join(installDir, art.Base()))
rule.Install(oat, filepath.Join(installDir, oat.Base()))
@@ -331,6 +350,8 @@
image.installs[arch] = rule.Installs()
image.vdexInstalls[arch] = vdexInstalls
image.unstrippedInstalls[arch] = unstrippedInstalls
+
+ return zipFiles
}
const failureMessage = `ERROR: Dex2oat failed to compile a boot image.
@@ -443,15 +464,25 @@
ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_FILES", strings.Join(image.dexPaths.Strings(), " "))
ctx.Strict("DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS", strings.Join(image.dexLocations, " "))
+ ctx.Strict("DEXPREOPT_IMAGE_ZIP_"+image.name, image.zip.String())
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 {
ctx.Strict("DEXPREOPT_IMAGE_VDEX_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.vdexInstalls[arch].String())
ctx.Strict("DEXPREOPT_IMAGE_"+current.name+"_"+arch.String(), current.images[arch].String())
ctx.Strict("DEXPREOPT_IMAGE_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.installs[arch].String())
ctx.Strict("DEXPREOPT_IMAGE_UNSTRIPPED_BUILT_INSTALLED_"+current.name+"_"+arch.String(), current.unstrippedInstalls[arch].String())
+ if current.zip != nil {
+ }
}
}
ctx.Strict("DEXPREOPT_IMAGE_NAMES", strings.Join(imageNames, " "))
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 409b4b1..b30bd00 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -111,6 +111,7 @@
dir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars")
symbolsDir := android.PathForOutput(ctx, ctx.Config().DeviceName(), "dex_bootjars_unstripped")
images := make(map[android.ArchType]android.OutputPath)
+ zip := dir.Join(ctx, "boot.zip")
for _, target := range ctx.Config().Targets[android.Android] {
images[target.Arch.ArchType] = dir.Join(ctx,
@@ -125,6 +126,7 @@
dir: dir,
symbolsDir: symbolsDir,
images: images,
+ zip: zip,
}
}).(bootImageConfig)
}
diff --git a/java/kotlin.go b/java/kotlin.go
index 054998f..54c6b0e 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -27,11 +27,12 @@
var kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
blueprint.RuleParams{
- Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" && mkdir -p "$classesDir" "$srcJarDir" && ` +
+ Command: `rm -rf "$classesDir" "$srcJarDir" "$kotlinBuildFile" "$emptyDir" && ` +
+ `mkdir -p "$classesDir" "$srcJarDir" "$emptyDir" && ` +
`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
`${config.GenKotlinBuildFileCmd} $classpath $classesDir $out.rsp $srcJarDir/list > $kotlinBuildFile &&` +
`${config.KotlincCmd} ${config.JavacHeapFlags} $kotlincFlags ` +
- `-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile && ` +
+ `-jvm-target $kotlinJvmTarget -Xbuild-file=$kotlinBuildFile -kotlin-home $emptyDir && ` +
`${config.SoongZipCmd} -jar -o $out -C $classesDir -D $classesDir && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
@@ -49,7 +50,7 @@
Rspfile: "$out.rsp",
RspfileContent: `$in`,
},
- "kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile")
+ "kotlincFlags", "classpath", "srcJars", "srcJarDir", "classesDir", "kotlinJvmTarget", "kotlinBuildFile", "emptyDir")
// kotlinCompile takes .java and .kt sources and srcJars, and compiles the .kt sources into a classes jar in outputFile.
func kotlinCompile(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -73,6 +74,7 @@
"classesDir": android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
"srcJarDir": android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
"kotlinBuildFile": android.PathForModuleOut(ctx, "kotlinc-build.xml").String(),
+ "emptyDir": android.PathForModuleOut(ctx, "kotlinc", "empty").String(),
// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
"kotlinJvmTarget": "1.8",
},