diff --git a/android/rule_builder.go b/android/rule_builder.go index b4f144a0d..9005f072a 100644 --- a/android/rule_builder.go +++ b/android/rule_builder.go @@ -162,9 +162,10 @@ func (r *RuleBuilder) DeleteTemporaryFiles() { 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 @@ func (r *RuleBuilder) Inputs() Paths { 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 @@ func (r *RuleBuilder) outputSet() map[string]WritablePath { 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 @@ func (r *RuleBuilder) toolsSet() map[string]Path { 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 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string 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 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string type RuleBuilderCommand struct { buf strings.Builder inputs Paths + orderOnlys Paths outputs WritablePaths depFiles WritablePaths tools Paths @@ -475,6 +502,10 @@ func (c *RuleBuilderCommand) addInput(path Path) string { 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 @@ func (c *RuleBuilderCommand) Implicits(paths Paths) *RuleBuilderCommand { 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 acf81272c..c41b06734 100644 --- a/android/rule_builder_test.go +++ b/android/rule_builder_test.go @@ -265,14 +265,16 @@ func ExampleRuleBuilderCommand_NinjaEscapedString() { 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 @@ func TestRuleBuilder(t *testing.T) { 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 @@ func TestRuleBuilder(t *testing.T) { 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 @@ func TestRuleBuilder(t *testing.T) { 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 @@ func TestRuleBuilder(t *testing.T) { 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 @@ func TestRuleBuilder(t *testing.T) { 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)