Merge changes from topic "buildnumberfromfile"

* changes:
  Allow jar wrapper to take quoted arguments
  Add rspfile support to RuleBuilder
  Prepare droiddoc for using RuleBuilder
  Manually escape BuildNumberFromFile
  Fix android.Expand and ninja escaping
  Add RuleBuilder helper functions for built and prebuilt tools
  Add documentation to droiddoc.go module types
This commit is contained in:
Colin Cross
2019-07-17 02:45:03 +00:00
committed by Gerrit Code Review
16 changed files with 383 additions and 106 deletions

View File

@@ -18,12 +18,30 @@ import (
"fmt" "fmt"
"strings" "strings"
"unicode" "unicode"
"github.com/google/blueprint/proptools"
) )
// ExpandNinjaEscaped substitutes $() variables in a string
// $(var) is passed to mapping(var), which should return the expanded value, a bool for whether the result should
// be left unescaped when using in a ninja value (generally false, true if the expanded value is a ninja variable like
// '${in}'), and an error.
// $$ is converted to $, which is escaped back to $$.
func ExpandNinjaEscaped(s string, mapping func(string) (string, bool, error)) (string, error) {
return expand(s, true, mapping)
}
// Expand substitutes $() variables in a string // Expand substitutes $() variables in a string
// $(var) is passed to Expander(var) // $(var) is passed to mapping(var), which should return the expanded value and an error.
// $$ is converted to $ // $$ is converted to $.
func Expand(s string, mapping func(string) (string, error)) (string, error) { func Expand(s string, mapping func(string) (string, error)) (string, error) {
return expand(s, false, func(s string) (string, bool, error) {
s, err := mapping(s)
return s, false, err
})
}
func expand(s string, ninjaEscape bool, mapping func(string) (string, bool, error)) (string, error) {
// based on os.Expand // based on os.Expand
buf := make([]byte, 0, 2*len(s)) buf := make([]byte, 0, 2*len(s))
i := 0 i := 0
@@ -33,10 +51,13 @@ func Expand(s string, mapping func(string) (string, error)) (string, error) {
return "", fmt.Errorf("expected character after '$'") return "", fmt.Errorf("expected character after '$'")
} }
buf = append(buf, s[i:j]...) buf = append(buf, s[i:j]...)
value, w, err := getMapping(s[j+1:], mapping) value, ninjaVariable, w, err := getMapping(s[j+1:], mapping)
if err != nil { if err != nil {
return "", err return "", err
} }
if !ninjaVariable && ninjaEscape {
value = proptools.NinjaEscape(value)
}
buf = append(buf, value...) buf = append(buf, value...)
j += w j += w
i = j + 1 i = j + 1
@@ -45,26 +66,26 @@ func Expand(s string, mapping func(string) (string, error)) (string, error) {
return string(buf) + s[i:], nil return string(buf) + s[i:], nil
} }
func getMapping(s string, mapping func(string) (string, error)) (string, int, error) { func getMapping(s string, mapping func(string) (string, bool, error)) (string, bool, int, error) {
switch s[0] { switch s[0] {
case '(': case '(':
// Scan to closing brace // Scan to closing brace
for i := 1; i < len(s); i++ { for i := 1; i < len(s); i++ {
if s[i] == ')' { if s[i] == ')' {
ret, err := mapping(strings.TrimSpace(s[1:i])) ret, ninjaVariable, err := mapping(strings.TrimSpace(s[1:i]))
return ret, i + 1, err return ret, ninjaVariable, i + 1, err
} }
} }
return "", len(s), fmt.Errorf("missing )") return "", false, len(s), fmt.Errorf("missing )")
case '$': case '$':
return "$$", 1, nil return "$", false, 1, nil
default: default:
i := strings.IndexFunc(s, unicode.IsSpace) i := strings.IndexFunc(s, unicode.IsSpace)
if i == 0 { if i == 0 {
return "", 0, fmt.Errorf("unexpected character '%c' after '$'", s[0]) return "", false, 0, fmt.Errorf("unexpected character '%c' after '$'", s[0])
} else if i == -1 { } else if i == -1 {
i = len(s) i = len(s)
} }
return "", 0, fmt.Errorf("expected '(' after '$', did you mean $(%s)?", s[:i]) return "", false, 0, fmt.Errorf("expected '(' after '$', did you mean $(%s)?", s[:i])
} }
} }

View File

@@ -20,88 +20,111 @@ import (
) )
var vars = map[string]string{ var vars = map[string]string{
"var1": "abc", "var1": "abc",
"var2": "", "var2": "",
"var3": "def", "var3": "def",
"💩": "😃", "💩": "😃",
"escape": "${in}",
} }
func expander(s string) (string, error) { func expander(s string) (string, bool, error) {
if val, ok := vars[s]; ok { if val, ok := vars[s]; ok {
return val, nil return val, s == "escape", nil
} else { } else {
return "", fmt.Errorf("unknown variable %q", s) return "", false, fmt.Errorf("unknown variable %q", s)
} }
} }
var expandTestCases = []struct { var expandTestCases = []struct {
in string in string
out string out string
err bool out_escaped string
err bool
}{ }{
{ {
in: "$(var1)", in: "$(var1)",
out: "abc", out: "abc",
out_escaped: "abc",
}, },
{ {
in: "$( var1 )", in: "$( var1 )",
out: "abc", out: "abc",
out_escaped: "abc",
}, },
{ {
in: "def$(var1)", in: "def$(var1)",
out: "defabc", out: "defabc",
out_escaped: "defabc",
}, },
{ {
in: "$(var1)def", in: "$(var1)def",
out: "abcdef", out: "abcdef",
out_escaped: "abcdef",
}, },
{ {
in: "def$(var1)def", in: "def$(var1)def",
out: "defabcdef", out: "defabcdef",
out_escaped: "defabcdef",
}, },
{ {
in: "$(var2)", in: "$(var2)",
out: "", out: "",
out_escaped: "",
}, },
{ {
in: "def$(var2)", in: "def$(var2)",
out: "def", out: "def",
out_escaped: "def",
}, },
{ {
in: "$(var2)def", in: "$(var2)def",
out: "def", out: "def",
out_escaped: "def",
}, },
{ {
in: "def$(var2)def", in: "def$(var2)def",
out: "defdef", out: "defdef",
out_escaped: "defdef",
}, },
{ {
in: "$(var1)$(var3)", in: "$(var1)$(var3)",
out: "abcdef", out: "abcdef",
out_escaped: "abcdef",
}, },
{ {
in: "$(var1)g$(var3)", in: "$(var1)g$(var3)",
out: "abcgdef", out: "abcgdef",
out_escaped: "abcgdef",
}, },
{ {
in: "$$", in: "$$",
out: "$$", out: "$",
out_escaped: "$$",
}, },
{ {
in: "$$(var1)", in: "$$(var1)",
out: "$$(var1)", out: "$(var1)",
out_escaped: "$$(var1)",
}, },
{ {
in: "$$$(var1)", in: "$$$(var1)",
out: "$$abc", out: "$abc",
out_escaped: "$$abc",
}, },
{ {
in: "$(var1)$$", in: "$(var1)$$",
out: "abc$$", out: "abc$",
out_escaped: "abc$$",
}, },
{ {
in: "$(💩)", in: "$(💩)",
out: "😃", out: "😃",
out_escaped: "😃",
},
{
in: "$$a$(escape)$$b",
out: "$a${in}$b",
out_escaped: "$$a${in}$$b",
}, },
// Errors // Errors
@@ -141,7 +164,10 @@ var expandTestCases = []struct {
func TestExpand(t *testing.T) { func TestExpand(t *testing.T) {
for _, test := range expandTestCases { for _, test := range expandTestCases {
got, err := Expand(test.in, expander) got, err := Expand(test.in, func(s string) (string, error) {
s, _, err := expander(s)
return s, err
})
if err != nil && !test.err { if err != nil && !test.err {
t.Errorf("%q: unexpected error %s", test.in, err.Error()) t.Errorf("%q: unexpected error %s", test.in, err.Error())
} else if err == nil && test.err { } else if err == nil && test.err {
@@ -151,3 +177,16 @@ func TestExpand(t *testing.T) {
} }
} }
} }
func TestExpandNinjaEscaped(t *testing.T) {
for _, test := range expandTestCases {
got, err := ExpandNinjaEscaped(test.in, expander)
if err != nil && !test.err {
t.Errorf("%q: unexpected error %s", test.in, err.Error())
} else if err == nil && test.err {
t.Errorf("%q: expected error, got %q", test.in, got)
} else if !test.err && got != test.out_escaped {
t.Errorf("%q: expected %q, got %q", test.in, test.out, got)
}
}
}

View File

@@ -135,7 +135,7 @@ func ProtoRule(ctx ModuleContext, rule *RuleBuilder, protoFile Path, flags Proto
} }
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "aprotoc")). BuiltTool(ctx, "aprotoc").
FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()). FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()).
FlagWithDepFile("--dependency_out=", depFile). FlagWithDepFile("--dependency_out=", depFile).
FlagWithArg("-I ", protoBase). FlagWithArg("-I ", protoBase).
@@ -145,5 +145,5 @@ func ProtoRule(ctx ModuleContext, rule *RuleBuilder, protoFile Path, flags Proto
ImplicitOutputs(outputs) ImplicitOutputs(outputs)
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).Flag(depFile.String()) BuiltTool(ctx, "dep_fixer").Flag(depFile.String())
} }

View File

@@ -263,11 +263,36 @@ func (r *RuleBuilder) Tools() Paths {
return toolsList return toolsList
} }
// Commands returns a slice containing a the built command line for each call to RuleBuilder.Command. // RspFileInputs returns the list of paths that were passed to the RuleBuilderCommand.FlagWithRspFileInputList method.
func (r *RuleBuilder) RspFileInputs() Paths {
var rspFileInputs Paths
for _, c := range r.commands {
if c.rspFileInputs != nil {
if rspFileInputs != nil {
panic("Multiple commands in a rule may not have rsp file inputs")
}
rspFileInputs = c.rspFileInputs
}
}
return rspFileInputs
}
// Commands returns a slice containing the built command line for each call to RuleBuilder.Command.
func (r *RuleBuilder) Commands() []string { func (r *RuleBuilder) Commands() []string {
var commands []string var commands []string
for _, c := range r.commands { for _, c := range r.commands {
commands = append(commands, c.buf.String()) commands = append(commands, c.String())
}
return commands
}
// NinjaEscapedCommands returns a slice containin the built command line after ninja escaping for each call to
// RuleBuilder.Command.
func (r *RuleBuilder) NinjaEscapedCommands() []string {
var commands []string
for _, c := range r.commands {
commands = append(commands, c.NinjaEscapedString())
} }
return commands return commands
} }
@@ -284,7 +309,7 @@ var _ BuilderContext = SingletonContext(nil)
func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand { func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand {
return r.Command(). return r.Command().
Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")). BuiltTool(ctx, "dep_fixer").
Inputs(depFiles.Paths()) Inputs(depFiles.Paths())
} }
@@ -324,7 +349,7 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
} }
tools := r.Tools() tools := r.Tools()
commands := r.Commands() commands := r.NinjaEscapedCommands()
outputs := r.Outputs() outputs := r.Outputs()
if len(commands) == 0 { if len(commands) == 0 {
@@ -334,7 +359,7 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
panic("No outputs specified from any Commands") panic("No outputs specified from any Commands")
} }
commandString := strings.Join(proptools.NinjaEscapeList(commands), " && ") commandString := strings.Join(commands, " && ")
if r.sbox { if r.sbox {
sboxOutputs := make([]string, len(outputs)) sboxOutputs := make([]string, len(outputs))
@@ -352,7 +377,7 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
} }
sboxCmd := &RuleBuilderCommand{} sboxCmd := &RuleBuilderCommand{}
sboxCmd.Tool(ctx.Config().HostToolPath(ctx, "sbox")). sboxCmd.BuiltTool(ctx, "sbox").
Flag("-c").Text(commandString). Flag("-c").Text(commandString).
Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())). Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).String())).
Flag("--output-root").Text(r.sboxOutDir.String()). Flag("--output-root").Text(r.sboxOutDir.String()).
@@ -363,17 +388,27 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
} }
// Ninja doesn't like multiple outputs when depfiles are enabled, move all but the first output to // 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 // ImplicitOutputs. RuleBuilder only uses "$out" for the rsp file location, so the distinction between Outputs and
// doesn't matter. // ImplicitOutputs doesn't matter.
output := outputs[0] output := outputs[0]
implicitOutputs := outputs[1:] implicitOutputs := outputs[1:]
var rspFile, rspFileContent string
rspFileInputs := r.RspFileInputs()
if rspFileInputs != nil {
rspFile = "$out.rsp"
rspFileContent = "$in"
}
ctx.Build(pctx, BuildParams{ ctx.Build(pctx, BuildParams{
Rule: ctx.Rule(pctx, name, blueprint.RuleParams{ Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
Command: commandString, Command: commandString,
CommandDeps: tools.Strings(), CommandDeps: tools.Strings(),
Restat: r.restat, Restat: r.restat,
Rspfile: rspFile,
RspfileContent: rspFileContent,
}), }),
Inputs: rspFileInputs,
Implicits: r.Inputs(), Implicits: r.Inputs(),
Output: output, Output: output,
ImplicitOutputs: implicitOutputs, ImplicitOutputs: implicitOutputs,
@@ -388,11 +423,15 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
// RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single // RuleBuilderCommand, so they can be used chained or unchained. All methods that add text implicitly add a single
// space as a separator from the previous method. // space as a separator from the previous method.
type RuleBuilderCommand struct { type RuleBuilderCommand struct {
buf strings.Builder buf strings.Builder
inputs Paths inputs Paths
outputs WritablePaths outputs WritablePaths
depFiles WritablePaths depFiles WritablePaths
tools Paths tools Paths
rspFileInputs Paths
// spans [start,end) of the command that should not be ninja escaped
unescapedSpans [][2]int
sbox bool sbox bool
sboxOutDir WritablePath sboxOutDir WritablePath
@@ -478,6 +517,24 @@ func (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand {
return c.Text(path.String()) return c.Text(path.String())
} }
// BuiltTool adds the specified tool path that was built using a host Soong module to the command line. The path will
// be also added to the dependencies returned by RuleBuilder.Tools.
//
// It is equivalent to:
// cmd.Tool(ctx.Config().HostToolPath(ctx, tool))
func (c *RuleBuilderCommand) BuiltTool(ctx PathContext, tool string) *RuleBuilderCommand {
return c.Tool(ctx.Config().HostToolPath(ctx, tool))
}
// PrebuiltBuildTool adds the specified tool path from prebuils/build-tools. The path will be also added to the
// dependencies returned by RuleBuilder.Tools.
//
// It is equivalent to:
// cmd.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool))
func (c *RuleBuilderCommand) PrebuiltBuildTool(ctx PathContext, tool string) *RuleBuilderCommand {
return c.Tool(ctx.Config().PrebuiltBuildTool(ctx, tool))
}
// Input adds the specified input path to the command line. The path will also be added to the dependencies returned by // Input adds the specified input path to the command line. The path will also be added to the dependencies returned by
// RuleBuilder.Inputs. // RuleBuilder.Inputs.
func (c *RuleBuilderCommand) Input(path Path) *RuleBuilderCommand { func (c *RuleBuilderCommand) Input(path Path) *RuleBuilderCommand {
@@ -606,11 +663,56 @@ func (c *RuleBuilderCommand) FlagWithDepFile(flag string, path WritablePath) *Ru
return c.Text(flag + c.outputStr(path)) return c.Text(flag + c.outputStr(path))
} }
// FlagWithRspFileInputList adds the specified flag and path to an rspfile to the command line, with no separator
// between them. The paths will be written to the rspfile.
func (c *RuleBuilderCommand) FlagWithRspFileInputList(flag string, paths Paths) *RuleBuilderCommand {
if c.rspFileInputs != nil {
panic("FlagWithRspFileInputList cannot be called if rsp file inputs have already been provided")
}
// Use an empty slice if paths is nil, the non-nil slice is used as an indicator that the rsp file must be
// generated.
if paths == nil {
paths = Paths{}
}
c.rspFileInputs = paths
rspFile := "$out.rsp"
c.FlagWithArg(flag, rspFile)
c.unescapedSpans = append(c.unescapedSpans, [2]int{c.buf.Len() - len(rspFile), c.buf.Len()})
return c
}
// String returns the command line. // String returns the command line.
func (c *RuleBuilderCommand) String() string { func (c *RuleBuilderCommand) String() string {
return c.buf.String() return c.buf.String()
} }
// String returns the command line.
func (c *RuleBuilderCommand) NinjaEscapedString() string {
return ninjaEscapeExceptForSpans(c.String(), c.unescapedSpans)
}
func ninjaEscapeExceptForSpans(s string, spans [][2]int) string {
if len(spans) == 0 {
return proptools.NinjaEscape(s)
}
sb := strings.Builder{}
sb.Grow(len(s) * 11 / 10)
i := 0
for _, span := range spans {
sb.WriteString(proptools.NinjaEscape(s[i:span[0]]))
sb.WriteString(s[span[0]:span[1]])
i = span[1]
}
sb.WriteString(proptools.NinjaEscape(s[i:]))
return sb.String()
}
func ninjaNameEscape(s string) string { func ninjaNameEscape(s string) string {
b := []byte(s) b := []byte(s)
escaped := false escaped := false

View File

@@ -38,6 +38,7 @@ func pathContext() PathContext {
"ls": nil, "ls": nil,
"turbine": nil, "turbine": nil,
"java": nil, "java": nil,
"javac": nil,
}) })
} }
@@ -235,6 +236,34 @@ func ExampleRuleBuilderCommand_FlagWithList() {
// ls --sort=time,size // ls --sort=time,size
} }
func ExampleRuleBuilderCommand_FlagWithRspFileInputList() {
ctx := pathContext()
fmt.Println(NewRuleBuilder().Command().
Tool(PathForSource(ctx, "javac")).
FlagWithRspFileInputList("@", PathsForTesting("a.java", "b.java")).
NinjaEscapedString())
// Output:
// javac @$out.rsp
}
func ExampleRuleBuilderCommand_String() {
fmt.Println(NewRuleBuilder().Command().
Text("FOO=foo").
Text("echo $FOO").
String())
// Output:
// FOO=foo echo $FOO
}
func ExampleRuleBuilderCommand_NinjaEscapedString() {
fmt.Println(NewRuleBuilder().Command().
Text("FOO=foo").
Text("echo $FOO").
NinjaEscapedString())
// Output:
// FOO=foo echo $$FOO
}
func TestRuleBuilder(t *testing.T) { func TestRuleBuilder(t *testing.T) {
fs := map[string][]byte{ fs := map[string][]byte{
"dep_fixer": nil, "dep_fixer": nil,
@@ -503,3 +532,77 @@ func TestRuleBuilder_Build(t *testing.T) {
"cp bar "+outFile, outFile, outFile+".d", true, nil) "cp bar "+outFile, outFile, outFile+".d", true, nil)
}) })
} }
func Test_ninjaEscapeExceptForSpans(t *testing.T) {
type args struct {
s string
spans [][2]int
}
tests := []struct {
name string
args args
want string
}{
{
name: "empty",
args: args{
s: "",
},
want: "",
},
{
name: "unescape none",
args: args{
s: "$abc",
},
want: "$$abc",
},
{
name: "unescape all",
args: args{
s: "$abc",
spans: [][2]int{{0, 4}},
},
want: "$abc",
},
{
name: "unescape first",
args: args{
s: "$abc$",
spans: [][2]int{{0, 1}},
},
want: "$abc$$",
},
{
name: "unescape last",
args: args{
s: "$abc$",
spans: [][2]int{{4, 5}},
},
want: "$$abc$",
},
{
name: "unescape middle",
args: args{
s: "$a$b$c$",
spans: [][2]int{{2, 5}},
},
want: "$$a$b$c$$",
},
{
name: "unescape multiple",
args: args{
s: "$a$b$c$",
spans: [][2]int{{2, 3}, {4, 5}},
},
want: "$$a$b$c$$",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ninjaEscapeExceptForSpans(tt.args.s, tt.args.spans); got != tt.want {
t.Errorf("ninjaEscapeExceptForSpans() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -99,7 +99,7 @@ func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile andr
cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison"). cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison").
FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")). FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")).
Tool(ctx.Config().PrebuiltBuildTool(ctx, "bison")). PrebuiltBuildTool(ctx, "bison").
Flag("-d"). Flag("-d").
Flags(flags). Flags(flags).
FlagWithOutput("--defines=", headerFile). FlagWithOutput("--defines=", headerFile).
@@ -121,7 +121,7 @@ func genAidl(ctx android.ModuleContext, rule *android.RuleBuilder, aidlFile andr
headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h") headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h")
cmd := rule.Command() cmd := rule.Command()
cmd.Tool(ctx.Config().HostToolPath(ctx, "aidl-cpp")). cmd.BuiltTool(ctx, "aidl-cpp").
FlagWithDepFile("-d", depFile). FlagWithDepFile("-d", depFile).
Flag("--ninja"). Flag("--ninja").
Flag(aidlFlags). Flag(aidlFlags).

View File

@@ -483,7 +483,7 @@ func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path
Input: in, Input: in,
Output: out, Output: out,
Args: map[string]string{ Args: map[string]string{
"buildNumberFromFile": ctx.Config().BuildNumberFromFile(), "buildNumberFromFile": proptools.NinjaEscape(ctx.Config().BuildNumberFromFile()),
}, },
}) })
} }

View File

@@ -284,12 +284,12 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
referencedDepfile := false referencedDepfile := false
rawCommand, err := android.Expand(task.cmd, func(name string) (string, error) { rawCommand, err := android.ExpandNinjaEscaped(task.cmd, func(name string) (string, bool, error) {
// report the error directly without returning an error to android.Expand to catch multiple errors in a // report the error directly without returning an error to android.Expand to catch multiple errors in a
// single run // single run
reportError := func(fmt string, args ...interface{}) (string, error) { reportError := func(fmt string, args ...interface{}) (string, bool, error) {
ctx.PropertyErrorf("cmd", fmt, args...) ctx.PropertyErrorf("cmd", fmt, args...)
return "SOONG_ERROR", nil return "SOONG_ERROR", false, nil
} }
switch name { switch name {
@@ -304,19 +304,19 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return reportError("default label %q has multiple files, use $(locations %s) to reference it", return reportError("default label %q has multiple files, use $(locations %s) to reference it",
firstLabel, firstLabel) firstLabel, firstLabel)
} }
return locationLabels[firstLabel][0], nil return locationLabels[firstLabel][0], false, nil
case "in": case "in":
return "${in}", nil return "${in}", true, nil
case "out": case "out":
return "__SBOX_OUT_FILES__", nil return "__SBOX_OUT_FILES__", false, nil
case "depfile": case "depfile":
referencedDepfile = true referencedDepfile = true
if !Bool(g.properties.Depfile) { if !Bool(g.properties.Depfile) {
return reportError("$(depfile) used without depfile property") return reportError("$(depfile) used without depfile property")
} }
return "__SBOX_DEPFILE__", nil return "__SBOX_DEPFILE__", false, nil
case "genDir": case "genDir":
return "__SBOX_OUT_DIR__", nil return "__SBOX_OUT_DIR__", false, nil
default: default:
if strings.HasPrefix(name, "location ") { if strings.HasPrefix(name, "location ") {
label := strings.TrimSpace(strings.TrimPrefix(name, "location ")) label := strings.TrimSpace(strings.TrimPrefix(name, "location "))
@@ -327,7 +327,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
return reportError("label %q has multiple files, use $(locations %s) to reference it", return reportError("label %q has multiple files, use $(locations %s) to reference it",
label, label) label, label)
} }
return paths[0], nil return paths[0], false, nil
} else { } else {
return reportError("unknown location label %q", label) return reportError("unknown location label %q", label)
} }
@@ -337,7 +337,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(paths) == 0 { if len(paths) == 0 {
return reportError("label %q has no files", label) return reportError("label %q has no files", label)
} }
return strings.Join(paths, " "), nil return strings.Join(paths, " "), false, nil
} else { } else {
return reportError("unknown locations label %q", label) return reportError("unknown locations label %q", label)
} }

View File

@@ -816,7 +816,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
rule.Command(). rule.Command().
Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). BuiltTool(ctx, "zip2zip").
FlagWithInput("-i ", inputPath). FlagWithInput("-i ", inputPath).
FlagWithOutput("-o ", outputPath). FlagWithOutput("-o ", outputPath).
FlagWithArg("-0 ", "'lib/**/*.so'"). FlagWithArg("-0 ", "'lib/**/*.so'").
@@ -843,7 +843,7 @@ func (a *AndroidAppImport) uncompressDex(
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
rule.Command(). rule.Command().
Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath).
Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). BuiltTool(ctx, "zip2zip").
FlagWithInput("-i ", inputPath). FlagWithInput("-i ", inputPath).
FlagWithOutput("-o ", outputPath). FlagWithOutput("-o ", outputPath).
FlagWithArg("-0 ", "'classes*.dex'"). FlagWithArg("-0 ", "'classes*.dex'").
@@ -1067,7 +1067,7 @@ func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, man
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml") outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")). cmd := rule.Command().BuiltTool(ctx, "manifest_check").
Flag("--enforce-uses-libraries"). Flag("--enforce-uses-libraries").
Input(manifest). Input(manifest).
FlagWithOutput("-o ", outputFile) FlagWithOutput("-o ", outputFile)

View File

@@ -229,7 +229,7 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI
if image.zip != nil { if image.zip != nil {
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). BuiltTool(ctx, "soong_zip").
FlagWithOutput("-o ", image.zip). FlagWithOutput("-o ", image.zip).
FlagWithArg("-C ", image.dir.String()). FlagWithArg("-C ", image.dir.String()).
FlagWithInputList("-f ", allFiles, " -f ") FlagWithInputList("-f ", allFiles, " -f ")
@@ -438,7 +438,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
rule := android.NewRuleBuilder() rule := android.NewRuleBuilder()
rule.Command(). rule.Command().
// TODO: for now, use the debug version for better error reporting // TODO: for now, use the debug version for better error reporting
Tool(ctx.Config().HostToolPath(ctx, "oatdumpd")). BuiltTool(ctx, "oatdumpd").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPaths.Paths(), ":"). FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPaths.Paths(), ":").
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":"). FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":").
FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]). FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]).

View File

@@ -500,6 +500,7 @@ func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
} }
} }
// javadoc converts .java source files to documentation using javadoc.
func JavadocFactory() android.Module { func JavadocFactory() android.Module {
module := &Javadoc{} module := &Javadoc{}
@@ -509,6 +510,7 @@ func JavadocFactory() android.Module {
return module return module
} }
// javadoc_host converts .java source files to documentation using javadoc.
func JavadocHostFactory() android.Module { func JavadocHostFactory() android.Module {
module := &Javadoc{} module := &Javadoc{}
@@ -798,7 +800,7 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
"srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
"stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
"srcJars": strings.Join(j.srcJars.Strings(), " "), "srcJars": strings.Join(j.srcJars.Strings(), " "),
"opts": opts, "opts": proptools.NinjaEscape(opts),
"bootclasspathArgs": bootClasspathArgs, "bootclasspathArgs": bootClasspathArgs,
"classpathArgs": classpathArgs, "classpathArgs": classpathArgs,
"sourcepathArgs": sourcepathArgs, "sourcepathArgs": sourcepathArgs,
@@ -831,6 +833,7 @@ type Droiddoc struct {
apiFilePath android.Path apiFilePath android.Path
} }
// droiddoc converts .java source files to documentation using doclava or dokka.
func DroiddocFactory() android.Module { func DroiddocFactory() android.Module {
module := &Droiddoc{} module := &Droiddoc{}
@@ -841,6 +844,7 @@ func DroiddocFactory() android.Module {
return module return module
} }
// droiddoc_host converts .java source files to documentation using doclava or dokka.
func DroiddocHostFactory() android.Module { func DroiddocHostFactory() android.Module {
module := &Droiddoc{} module := &Droiddoc{}
@@ -918,7 +922,7 @@ func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits
args := " -source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " + args := " -source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " +
"-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " + "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
"-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " + "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " +
`-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" ` `-hdf page.now "$(` + date + ` @$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" `
if String(d.properties.Custom_template) == "" { if String(d.properties.Custom_template) == "" {
// TODO: This is almost always droiddoc-templates-sdk // TODO: This is almost always droiddoc-templates-sdk
@@ -1095,7 +1099,7 @@ func (d *Droiddoc) transformDoclava(ctx android.ModuleContext, implicits android
"srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
"stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"opts": opts, "opts": proptools.NinjaEscape(opts),
"bootclasspathArgs": bootclasspathArgs, "bootclasspathArgs": bootclasspathArgs,
"classpathArgs": classpathArgs, "classpathArgs": classpathArgs,
"sourcepathArgs": sourcepathArgs, "sourcepathArgs": sourcepathArgs,
@@ -1117,7 +1121,7 @@ func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removed
Args: map[string]string{ Args: map[string]string{
"msg": msg, "msg": msg,
"classpath": checkApiClasspath.FormJavaClassPath(""), "classpath": checkApiClasspath.FormJavaClassPath(""),
"opts": opts, "opts": proptools.NinjaEscape(opts),
"apiFile": apiFile.String(), "apiFile": apiFile.String(),
"apiFileToCheck": d.apiFile.String(), "apiFileToCheck": d.apiFile.String(),
"removedApiFile": removedApiFile.String(), "removedApiFile": removedApiFile.String(),
@@ -1140,7 +1144,7 @@ func (d *Droiddoc) transformDokka(ctx android.ModuleContext, implicits android.P
"stubsDir": android.PathForModuleOut(ctx, "dokka-stubsDir").String(), "stubsDir": android.PathForModuleOut(ctx, "dokka-stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"classpathArgs": classpathArgs, "classpathArgs": classpathArgs,
"opts": opts, "opts": proptools.NinjaEscape(opts),
"docZip": d.Javadoc.docZip.String(), "docZip": d.Javadoc.docZip.String(),
}, },
}) })
@@ -1258,6 +1262,9 @@ type Droidstubs struct {
jdiffStubsSrcJar android.WritablePath jdiffStubsSrcJar android.WritablePath
} }
// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
// a droiddoc module to generate documentation.
func DroidstubsFactory() android.Module { func DroidstubsFactory() android.Module {
module := &Droidstubs{} module := &Droidstubs{}
@@ -1268,6 +1275,10 @@ func DroidstubsFactory() android.Module {
return module return module
} }
// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API
// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be
// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs
// module when symbols needed by the source files are provided by java_library_host modules.
func DroidstubsHostFactory() android.Module { func DroidstubsHostFactory() android.Module {
module := &Droidstubs{} module := &Droidstubs{}
@@ -1558,7 +1569,7 @@ func (d *Droidstubs) transformMetalava(ctx android.ModuleContext, implicits andr
"bootclasspathArgs": bootclasspathArgs, "bootclasspathArgs": bootclasspathArgs,
"classpathArgs": classpathArgs, "classpathArgs": classpathArgs,
"sourcepathArgs": sourcepathArgs, "sourcepathArgs": sourcepathArgs,
"opts": opts, "opts": proptools.NinjaEscape(opts),
}, },
}) })
} }
@@ -1581,7 +1592,7 @@ func (d *Droidstubs) transformCheckApi(ctx android.ModuleContext,
"bootclasspathArgs": bootclasspathArgs, "bootclasspathArgs": bootclasspathArgs,
"classpathArgs": classpathArgs, "classpathArgs": classpathArgs,
"sourcepathArgs": sourcepathArgs, "sourcepathArgs": sourcepathArgs,
"opts": opts, "opts": proptools.NinjaEscape(opts),
"msg": msg, "msg": msg,
}, },
}) })
@@ -1602,7 +1613,7 @@ func (d *Droidstubs) transformJdiff(ctx android.ModuleContext, implicits android
"srcJarDir": android.PathForModuleOut(ctx, "jdiff-srcjars").String(), "srcJarDir": android.PathForModuleOut(ctx, "jdiff-srcjars").String(),
"stubsDir": android.PathForModuleOut(ctx, "jdiff-stubsDir").String(), "stubsDir": android.PathForModuleOut(ctx, "jdiff-stubsDir").String(),
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
"opts": opts, "opts": proptools.NinjaEscape(opts),
"bootclasspathArgs": bootclasspathArgs, "bootclasspathArgs": bootclasspathArgs,
"classpathArgs": classpathArgs, "classpathArgs": classpathArgs,
"sourcepathArgs": sourcepathArgs, "sourcepathArgs": sourcepathArgs,
@@ -1781,6 +1792,7 @@ type ExportedDroiddocDir struct {
dir android.Path dir android.Path
} }
// droiddoc_exported_dir exports a directory of html templates or nullability annotations for use by doclava.
func ExportedDroiddocDirFactory() android.Module { func ExportedDroiddocDirFactory() android.Module {
module := &ExportedDroiddocDir{} module := &ExportedDroiddocDir{}
module.AddProperties(&module.properties) module.AddProperties(&module.properties)

View File

@@ -2088,14 +2088,14 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// use zip2zip to uncompress classes*.dex files // use zip2zip to uncompress classes*.dex files
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). BuiltTool(ctx, "zip2zip").
FlagWithInput("-i ", inputJar). FlagWithInput("-i ", inputJar).
FlagWithOutput("-o ", temporary). FlagWithOutput("-o ", temporary).
FlagWithArg("-0 ", "'classes*.dex'") FlagWithArg("-0 ", "'classes*.dex'")
// use zipalign to align uncompressed classes*.dex files // use zipalign to align uncompressed classes*.dex files
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "zipalign")). BuiltTool(ctx, "zipalign").
Flag("-f"). Flag("-f").
Text("4"). Text("4").
Input(temporary). Input(temporary).

View File

@@ -34,7 +34,7 @@ func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.P
// Proto generated java files have an unknown package name in the path, so package the entire output directory // Proto generated java files have an unknown package name in the path, so package the entire output directory
// into a srcjar. // into a srcjar.
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). BuiltTool(ctx, "soong_zip").
Flag("-jar"). Flag("-jar").
FlagWithOutput("-o ", srcJarFile). FlagWithOutput("-o ", srcJarFile).
FlagWithArg("-C ", outDir.String()). FlagWithArg("-C ", outDir.String()).

View File

@@ -296,7 +296,7 @@ func createSdkFrameworkAidl(ctx android.SingletonContext) {
rule.Command(). rule.Command().
Text("rm -f").Output(aidl) Text("rm -f").Output(aidl)
rule.Command(). rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "sdkparcelables")). BuiltTool(ctx, "sdkparcelables").
Input(jar). Input(jar).
Output(aidl) Output(aidl)

View File

@@ -34,7 +34,7 @@ func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.P
// Proto generated python files have an unknown package name in the path, so package the entire output directory // Proto generated python files have an unknown package name in the path, so package the entire output directory
// into a srcszip. // into a srcszip.
zipCmd := rule.Command(). zipCmd := rule.Command().
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). BuiltTool(ctx, "soong_zip").
FlagWithOutput("-o ", srcsZipFile) FlagWithOutput("-o ", srcsZipFile)
if pkgPath != "" { if pkgPath != "" {
zipCmd.FlagWithArg("-P ", pkgPath) zipCmd.FlagWithArg("-P ", pkgPath)

View File

@@ -48,11 +48,11 @@ if [ ! -r "${jardir}/${jarfile}" ]; then
exit 1 exit 1
fi fi
javaOpts="" declare -a javaOpts=()
while expr "x$1" : 'x-J' >/dev/null; do while expr "x$1" : 'x-J' >/dev/null; do
opt=`expr "$1" : '-J\(.*\)'` opt=`expr "$1" : '-J-\{0,1\}\(.*\)'`
javaOpts="${javaOpts} -${opt}" javaOpts+=("-${opt}")
shift shift
done done
exec java ${javaOpts} -jar ${jardir}/${jarfile} "$@" exec java "${javaOpts[@]}" -jar ${jardir}/${jarfile} "$@"