Merge changes from topic "buildnumberfromfile"

am: 223e6a65b6

Change-Id: I4e2f0514434ddf6833d03334dbf36869d762214e
This commit is contained in:
Colin Cross
2019-07-16 19:59:12 -07:00
committed by android-build-merger
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

@@ -24,84 +24,107 @@ var vars = map[string]string{
"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
out_escaped string
err bool 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,
@@ -393,6 +428,10 @@ type RuleBuilderCommand struct {
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} "$@"