diff options
| -rw-r--r-- | Android.bp | 1 | ||||
| -rw-r--r-- | android/config.go | 8 | ||||
| -rw-r--r-- | android/paths.go | 17 | ||||
| -rw-r--r-- | android/rule_builder.go | 196 | ||||
| -rw-r--r-- | android/rule_builder_test.go | 237 | ||||
| -rw-r--r-- | android/variable.go | 2 | ||||
| -rw-r--r-- | androidmk/cmd/androidmk/android.go | 2 | ||||
| -rw-r--r-- | apex/key.go | 3 | ||||
| -rw-r--r-- | cc/builder.go | 3 | ||||
| -rw-r--r-- | cc/cc.go | 3 | ||||
| -rw-r--r-- | cc/compiler.go | 8 | ||||
| -rw-r--r-- | cc/gen.go | 89 | ||||
| -rw-r--r-- | cc/util.go | 3 | ||||
| -rw-r--r-- | cmd/sbox/sbox.go | 2 | ||||
| -rw-r--r-- | cmd/soong_build/writedocs.go | 94 | ||||
| -rw-r--r-- | java/dexpreopt_bootjars.go | 7 |
16 files changed, 515 insertions, 160 deletions
diff --git a/Android.bp b/Android.bp index 910fe4bc5..60ecc4ca4 100644 --- a/Android.bp +++ b/Android.bp @@ -37,6 +37,7 @@ bootstrap_go_package { "blueprint-bootstrap", "soong", "soong-env", + "soong-shared", ], srcs: [ "android/androidmk.go", diff --git a/android/config.go b/android/config.go index 0c9f95769..0191e3850 100644 --- a/android/config.go +++ b/android/config.go @@ -405,6 +405,10 @@ func (c *config) GoRoot() string { 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) ProductHiddenAPIStubsSystem() []string { 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 8cc7057ad..0f20b844d 100644 --- a/android/paths.go +++ b/android/paths.go @@ -1267,16 +1267,23 @@ func Rel(ctx PathContext, basePath string, targetPath string) string { // 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 2d0fac168..4a3b02233 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -21,6 +21,8 @@ import ( "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 @@ type RuleBuilder struct { installs RuleBuilderInstalls temporariesSet map[WritablePath]bool restat bool + sbox bool + sboxOutDir WritablePath missingDeps []string } @@ -73,11 +77,36 @@ func (r *RuleBuilder) MissingDeps(missingDeps []string) { } // 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 @@ func (r *RuleBuilder) Install(from Path, to string) { // 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 @@ func (r *RuleBuilder) DeleteTemporaryFiles() { // 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 @@ func (r *RuleBuilder) Outputs() WritablePaths { 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 = ModuleContext(nil) 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 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string 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 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string 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()) + } + } } } - // 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:] + 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") } - 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, - }) + 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. + output := outputs[0] + implicitOutputs := outputs[1:] + + 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 @@ type RuleBuilderCommand struct { 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 @@ func (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand { // 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 @@ func (c *RuleBuilderCommand) Inputs(paths Paths) *RuleBuilderCommand { // 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 @@ func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand { // 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 @@ func (c *RuleBuilderCommand) Outputs(paths WritablePaths) *RuleBuilderCommand { // 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 @@ func (c *RuleBuilderCommand) ImplicitDepFile(path WritablePath) *RuleBuilderComm // 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 @@ func (c *RuleBuilderCommand) FlagForEachInput(flag string, paths Paths) *RuleBui // 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 7bad02586..df0f25640 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -22,6 +22,10 @@ import ( "reflect" "strings" "testing" + + "github.com/google/blueprint" + + "android/soong/shared" ) func pathContext() PathContext { @@ -234,8 +238,6 @@ func ExampleRuleBuilderCommand_FlagWithList() { } func TestRuleBuilder(t *testing.T) { - rule := NewRuleBuilder() - fs := map[string][]byte{ "dep_fixer": nil, "input": nil, @@ -249,73 +251,114 @@ func TestRuleBuilder(t *testing.T) { 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")) - - 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 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", + 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")) + + // 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")) } - 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 @@ type testRuleBuilderModule struct { 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 testRuleBuilderSingletonFactory() Singleton { 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.Command().Tool(PathForSource(ctx, "cp")).Input(in).Output(out).ImplicitDepFile(outDep) - rule.Restat() + if restat { + rule.Restat() + } rule.Build(pctx, ctx, "rule", "desc") } @@ -372,6 +428,12 @@ func TestRuleBuilder_Build(t *testing.T) { rule_builder_test { name: "foo", src: "bar", + restat: true, + } + rule_builder_test { + name: "foo_sbox", + src: "bar", + sbox: true, } ` @@ -391,9 +453,18 @@ func TestRuleBuilder_Build(t *testing.T) { _, 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 @@ func TestRuleBuilder_Build(t *testing.T) { 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 16d7b1384..666f29f81 100644 --- a/android/variable.go +++ b/android/variable.go @@ -287,6 +287,8 @@ type productVariables struct { 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 e0932af38..b54ad5e00 100644 --- a/androidmk/cmd/androidmk/android.go +++ b/androidmk/cmd/androidmk/android.go @@ -131,7 +131,7 @@ func init() { "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 a627e4bc6..229d59358 100644 --- a/apex/key.go +++ b/apex/key.go @@ -55,8 +55,7 @@ type apexKeyProperties struct { 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 65369d621..87db6455a 100644 --- a/cc/builder.go +++ b/cc/builder.go @@ -239,7 +239,6 @@ type builderFlags struct { cppFlags string ldFlags string libFlags string - yaccFlags string tidyFlags string sAbiFlags string yasmFlags string @@ -262,6 +261,8 @@ type builderFlags struct { proto android.ProtoFlags protoC bool protoOptionsFile bool + + yacc *YaccProperties } type Objects struct { @@ -136,7 +136,6 @@ type Flags struct { 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 @@ type Flags struct { 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 f9af4d829..7667ae7ab 100644 --- a/cc/compiler.go +++ b/cc/compiler.go @@ -57,9 +57,6 @@ type BaseCompilerProperties struct { // 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 @@ type BaseCompilerProperties struct { // 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 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps 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) @@ -24,21 +24,12 @@ import ( 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 @@ var ( "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 + + // 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() - return headerFile + // 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 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, 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 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths, } } + 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/util.go b/cc/util.go index 5dcbaeffb..3862728bb 100644 --- a/cc/util.go +++ b/cc/util.go @@ -67,7 +67,6 @@ func flagsToBuilderFlags(in Flags) builderFlags { 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 @@ func flagsToBuilderFlags(in Flags) builderFlags { proto: in.proto, protoC: in.protoC, protoOptionsFile: in.protoOptionsFile, + + yacc: in.Yacc, } } diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go index 4167edb3e..4ac92953e 100644 --- a/cmd/sbox/sbox.go +++ b/cmd/sbox/sbox.go @@ -56,7 +56,7 @@ func usageViolation(violation string) { } 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 d011e77fe..9424b6cc1 100644 --- a/cmd/soong_build/writedocs.go +++ b/cmd/soong_build/writedocs.go @@ -152,7 +152,6 @@ const ( <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 @@ table{ 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 e857fe81a..cb2ea9f0a 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -469,7 +469,14 @@ func (d *dexpreoptBootJars) MakeVars(ctx android.MakeVarsContext) { 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()) |