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:
@@ -18,12 +18,30 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"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
|
||||
// $(var) is passed to Expander(var)
|
||||
// $$ is converted to $
|
||||
// $(var) is passed to mapping(var), which should return the expanded value and an error.
|
||||
// $$ is converted to $.
|
||||
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
|
||||
buf := make([]byte, 0, 2*len(s))
|
||||
i := 0
|
||||
@@ -33,10 +51,13 @@ func Expand(s string, mapping func(string) (string, error)) (string, error) {
|
||||
return "", fmt.Errorf("expected character after '$'")
|
||||
}
|
||||
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 {
|
||||
return "", err
|
||||
}
|
||||
if !ninjaVariable && ninjaEscape {
|
||||
value = proptools.NinjaEscape(value)
|
||||
}
|
||||
buf = append(buf, value...)
|
||||
j += w
|
||||
i = j + 1
|
||||
@@ -45,26 +66,26 @@ func Expand(s string, mapping func(string) (string, error)) (string, error) {
|
||||
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] {
|
||||
case '(':
|
||||
// Scan to closing brace
|
||||
for i := 1; i < len(s); i++ {
|
||||
if s[i] == ')' {
|
||||
ret, err := mapping(strings.TrimSpace(s[1:i]))
|
||||
return ret, i + 1, err
|
||||
ret, ninjaVariable, err := mapping(strings.TrimSpace(s[1:i]))
|
||||
return ret, ninjaVariable, i + 1, err
|
||||
}
|
||||
}
|
||||
return "", len(s), fmt.Errorf("missing )")
|
||||
return "", false, len(s), fmt.Errorf("missing )")
|
||||
case '$':
|
||||
return "$$", 1, nil
|
||||
return "$", false, 1, nil
|
||||
default:
|
||||
i := strings.IndexFunc(s, unicode.IsSpace)
|
||||
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 {
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
@@ -20,88 +20,111 @@ import (
|
||||
)
|
||||
|
||||
var vars = map[string]string{
|
||||
"var1": "abc",
|
||||
"var2": "",
|
||||
"var3": "def",
|
||||
"💩": "😃",
|
||||
"var1": "abc",
|
||||
"var2": "",
|
||||
"var3": "def",
|
||||
"💩": "😃",
|
||||
"escape": "${in}",
|
||||
}
|
||||
|
||||
func expander(s string) (string, error) {
|
||||
func expander(s string) (string, bool, error) {
|
||||
if val, ok := vars[s]; ok {
|
||||
return val, nil
|
||||
return val, s == "escape", nil
|
||||
} else {
|
||||
return "", fmt.Errorf("unknown variable %q", s)
|
||||
return "", false, fmt.Errorf("unknown variable %q", s)
|
||||
}
|
||||
}
|
||||
|
||||
var expandTestCases = []struct {
|
||||
in string
|
||||
out string
|
||||
err bool
|
||||
in string
|
||||
out string
|
||||
out_escaped string
|
||||
err bool
|
||||
}{
|
||||
{
|
||||
in: "$(var1)",
|
||||
out: "abc",
|
||||
in: "$(var1)",
|
||||
out: "abc",
|
||||
out_escaped: "abc",
|
||||
},
|
||||
{
|
||||
in: "$( var1 )",
|
||||
out: "abc",
|
||||
in: "$( var1 )",
|
||||
out: "abc",
|
||||
out_escaped: "abc",
|
||||
},
|
||||
{
|
||||
in: "def$(var1)",
|
||||
out: "defabc",
|
||||
in: "def$(var1)",
|
||||
out: "defabc",
|
||||
out_escaped: "defabc",
|
||||
},
|
||||
{
|
||||
in: "$(var1)def",
|
||||
out: "abcdef",
|
||||
in: "$(var1)def",
|
||||
out: "abcdef",
|
||||
out_escaped: "abcdef",
|
||||
},
|
||||
{
|
||||
in: "def$(var1)def",
|
||||
out: "defabcdef",
|
||||
in: "def$(var1)def",
|
||||
out: "defabcdef",
|
||||
out_escaped: "defabcdef",
|
||||
},
|
||||
{
|
||||
in: "$(var2)",
|
||||
out: "",
|
||||
in: "$(var2)",
|
||||
out: "",
|
||||
out_escaped: "",
|
||||
},
|
||||
{
|
||||
in: "def$(var2)",
|
||||
out: "def",
|
||||
in: "def$(var2)",
|
||||
out: "def",
|
||||
out_escaped: "def",
|
||||
},
|
||||
{
|
||||
in: "$(var2)def",
|
||||
out: "def",
|
||||
in: "$(var2)def",
|
||||
out: "def",
|
||||
out_escaped: "def",
|
||||
},
|
||||
{
|
||||
in: "def$(var2)def",
|
||||
out: "defdef",
|
||||
in: "def$(var2)def",
|
||||
out: "defdef",
|
||||
out_escaped: "defdef",
|
||||
},
|
||||
{
|
||||
in: "$(var1)$(var3)",
|
||||
out: "abcdef",
|
||||
in: "$(var1)$(var3)",
|
||||
out: "abcdef",
|
||||
out_escaped: "abcdef",
|
||||
},
|
||||
{
|
||||
in: "$(var1)g$(var3)",
|
||||
out: "abcgdef",
|
||||
in: "$(var1)g$(var3)",
|
||||
out: "abcgdef",
|
||||
out_escaped: "abcgdef",
|
||||
},
|
||||
{
|
||||
in: "$$",
|
||||
out: "$$",
|
||||
in: "$$",
|
||||
out: "$",
|
||||
out_escaped: "$$",
|
||||
},
|
||||
{
|
||||
in: "$$(var1)",
|
||||
out: "$$(var1)",
|
||||
in: "$$(var1)",
|
||||
out: "$(var1)",
|
||||
out_escaped: "$$(var1)",
|
||||
},
|
||||
{
|
||||
in: "$$$(var1)",
|
||||
out: "$$abc",
|
||||
in: "$$$(var1)",
|
||||
out: "$abc",
|
||||
out_escaped: "$$abc",
|
||||
},
|
||||
{
|
||||
in: "$(var1)$$",
|
||||
out: "abc$$",
|
||||
in: "$(var1)$$",
|
||||
out: "abc$",
|
||||
out_escaped: "abc$$",
|
||||
},
|
||||
{
|
||||
in: "$(💩)",
|
||||
out: "😃",
|
||||
in: "$(💩)",
|
||||
out: "😃",
|
||||
out_escaped: "😃",
|
||||
},
|
||||
{
|
||||
in: "$$a$(escape)$$b",
|
||||
out: "$a${in}$b",
|
||||
out_escaped: "$$a${in}$$b",
|
||||
},
|
||||
|
||||
// Errors
|
||||
@@ -141,7 +164,10 @@ var expandTestCases = []struct {
|
||||
|
||||
func TestExpand(t *testing.T) {
|
||||
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 {
|
||||
t.Errorf("%q: unexpected error %s", test.in, err.Error())
|
||||
} 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -135,7 +135,7 @@ func ProtoRule(ctx ModuleContext, rule *RuleBuilder, protoFile Path, flags Proto
|
||||
}
|
||||
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "aprotoc")).
|
||||
BuiltTool(ctx, "aprotoc").
|
||||
FlagWithArg(flags.OutTypeFlag+"=", strings.Join(flags.OutParams, ",")+":"+outDir.String()).
|
||||
FlagWithDepFile("--dependency_out=", depFile).
|
||||
FlagWithArg("-I ", protoBase).
|
||||
@@ -145,5 +145,5 @@ func ProtoRule(ctx ModuleContext, rule *RuleBuilder, protoFile Path, flags Proto
|
||||
ImplicitOutputs(outputs)
|
||||
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).Flag(depFile.String())
|
||||
BuiltTool(ctx, "dep_fixer").Flag(depFile.String())
|
||||
}
|
||||
|
@@ -263,11 +263,36 @@ func (r *RuleBuilder) Tools() Paths {
|
||||
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 {
|
||||
var commands []string
|
||||
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
|
||||
}
|
||||
@@ -284,7 +309,7 @@ var _ BuilderContext = SingletonContext(nil)
|
||||
|
||||
func (r *RuleBuilder) depFileMergerCmd(ctx PathContext, depFiles WritablePaths) *RuleBuilderCommand {
|
||||
return r.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "dep_fixer")).
|
||||
BuiltTool(ctx, "dep_fixer").
|
||||
Inputs(depFiles.Paths())
|
||||
}
|
||||
|
||||
@@ -324,7 +349,7 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
|
||||
}
|
||||
|
||||
tools := r.Tools()
|
||||
commands := r.Commands()
|
||||
commands := r.NinjaEscapedCommands()
|
||||
outputs := r.Outputs()
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
commandString := strings.Join(proptools.NinjaEscapeList(commands), " && ")
|
||||
commandString := strings.Join(commands, " && ")
|
||||
|
||||
if r.sbox {
|
||||
sboxOutputs := make([]string, len(outputs))
|
||||
@@ -352,7 +377,7 @@ func (r *RuleBuilder) Build(pctx PackageContext, ctx BuilderContext, name string
|
||||
}
|
||||
|
||||
sboxCmd := &RuleBuilderCommand{}
|
||||
sboxCmd.Tool(ctx.Config().HostToolPath(ctx, "sbox")).
|
||||
sboxCmd.BuiltTool(ctx, "sbox").
|
||||
Flag("-c").Text(commandString).
|
||||
Flag("--sandbox-path").Text(shared.TempDirForOutDir(PathForOutput(ctx).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
|
||||
// ImplicitOutputs. RuleBuilder never uses "$out", so the distinction between Outputs and ImplicitOutputs
|
||||
// doesn't matter.
|
||||
// ImplicitOutputs. RuleBuilder only uses "$out" for the rsp file location, so the distinction between Outputs and
|
||||
// ImplicitOutputs doesn't matter.
|
||||
output := outputs[0]
|
||||
implicitOutputs := outputs[1:]
|
||||
|
||||
var rspFile, rspFileContent string
|
||||
rspFileInputs := r.RspFileInputs()
|
||||
if rspFileInputs != nil {
|
||||
rspFile = "$out.rsp"
|
||||
rspFileContent = "$in"
|
||||
}
|
||||
|
||||
ctx.Build(pctx, BuildParams{
|
||||
Rule: ctx.Rule(pctx, name, blueprint.RuleParams{
|
||||
Command: commandString,
|
||||
CommandDeps: tools.Strings(),
|
||||
Restat: r.restat,
|
||||
Command: commandString,
|
||||
CommandDeps: tools.Strings(),
|
||||
Restat: r.restat,
|
||||
Rspfile: rspFile,
|
||||
RspfileContent: rspFileContent,
|
||||
}),
|
||||
Inputs: rspFileInputs,
|
||||
Implicits: r.Inputs(),
|
||||
Output: output,
|
||||
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
|
||||
// space as a separator from the previous method.
|
||||
type RuleBuilderCommand struct {
|
||||
buf strings.Builder
|
||||
inputs Paths
|
||||
outputs WritablePaths
|
||||
depFiles WritablePaths
|
||||
tools Paths
|
||||
buf strings.Builder
|
||||
inputs Paths
|
||||
outputs WritablePaths
|
||||
depFiles WritablePaths
|
||||
tools Paths
|
||||
rspFileInputs Paths
|
||||
|
||||
// spans [start,end) of the command that should not be ninja escaped
|
||||
unescapedSpans [][2]int
|
||||
|
||||
sbox bool
|
||||
sboxOutDir WritablePath
|
||||
@@ -478,6 +517,24 @@ func (c *RuleBuilderCommand) Tool(path Path) *RuleBuilderCommand {
|
||||
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
|
||||
// RuleBuilder.Inputs.
|
||||
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))
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (c *RuleBuilderCommand) String() 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 {
|
||||
b := []byte(s)
|
||||
escaped := false
|
||||
|
@@ -38,6 +38,7 @@ func pathContext() PathContext {
|
||||
"ls": nil,
|
||||
"turbine": nil,
|
||||
"java": nil,
|
||||
"javac": nil,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -235,6 +236,34 @@ func ExampleRuleBuilderCommand_FlagWithList() {
|
||||
// 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) {
|
||||
fs := map[string][]byte{
|
||||
"dep_fixer": nil,
|
||||
@@ -503,3 +532,77 @@ func TestRuleBuilder_Build(t *testing.T) {
|
||||
"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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -99,7 +99,7 @@ func genYacc(ctx android.ModuleContext, rule *android.RuleBuilder, yaccFile andr
|
||||
|
||||
cmd.Text("BISON_PKGDATADIR=prebuilts/build-tools/common/bison").
|
||||
FlagWithInput("M4=", ctx.Config().PrebuiltBuildTool(ctx, "m4")).
|
||||
Tool(ctx.Config().PrebuiltBuildTool(ctx, "bison")).
|
||||
PrebuiltBuildTool(ctx, "bison").
|
||||
Flag("-d").
|
||||
Flags(flags).
|
||||
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")
|
||||
|
||||
cmd := rule.Command()
|
||||
cmd.Tool(ctx.Config().HostToolPath(ctx, "aidl-cpp")).
|
||||
cmd.BuiltTool(ctx, "aidl-cpp").
|
||||
FlagWithDepFile("-d", depFile).
|
||||
Flag("--ninja").
|
||||
Flag(aidlFlags).
|
||||
|
@@ -483,7 +483,7 @@ func (linker *baseLinker) injectVersionSymbol(ctx ModuleContext, in android.Path
|
||||
Input: in,
|
||||
Output: out,
|
||||
Args: map[string]string{
|
||||
"buildNumberFromFile": ctx.Config().BuildNumberFromFile(),
|
||||
"buildNumberFromFile": proptools.NinjaEscape(ctx.Config().BuildNumberFromFile()),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@@ -284,12 +284,12 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
|
||||
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
|
||||
// single run
|
||||
reportError := func(fmt string, args ...interface{}) (string, error) {
|
||||
reportError := func(fmt string, args ...interface{}) (string, bool, error) {
|
||||
ctx.PropertyErrorf("cmd", fmt, args...)
|
||||
return "SOONG_ERROR", nil
|
||||
return "SOONG_ERROR", false, nil
|
||||
}
|
||||
|
||||
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",
|
||||
firstLabel, firstLabel)
|
||||
}
|
||||
return locationLabels[firstLabel][0], nil
|
||||
return locationLabels[firstLabel][0], false, nil
|
||||
case "in":
|
||||
return "${in}", nil
|
||||
return "${in}", true, nil
|
||||
case "out":
|
||||
return "__SBOX_OUT_FILES__", nil
|
||||
return "__SBOX_OUT_FILES__", false, nil
|
||||
case "depfile":
|
||||
referencedDepfile = true
|
||||
if !Bool(g.properties.Depfile) {
|
||||
return reportError("$(depfile) used without depfile property")
|
||||
}
|
||||
return "__SBOX_DEPFILE__", nil
|
||||
return "__SBOX_DEPFILE__", false, nil
|
||||
case "genDir":
|
||||
return "__SBOX_OUT_DIR__", nil
|
||||
return "__SBOX_OUT_DIR__", false, nil
|
||||
default:
|
||||
if strings.HasPrefix(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",
|
||||
label, label)
|
||||
}
|
||||
return paths[0], nil
|
||||
return paths[0], false, nil
|
||||
} else {
|
||||
return reportError("unknown location label %q", label)
|
||||
}
|
||||
@@ -337,7 +337,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
if len(paths) == 0 {
|
||||
return reportError("label %q has no files", label)
|
||||
}
|
||||
return strings.Join(paths, " "), nil
|
||||
return strings.Join(paths, " "), false, nil
|
||||
} else {
|
||||
return reportError("unknown locations label %q", label)
|
||||
}
|
||||
|
@@ -816,7 +816,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs(
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.Command().
|
||||
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).
|
||||
FlagWithOutput("-o ", outputPath).
|
||||
FlagWithArg("-0 ", "'lib/**/*.so'").
|
||||
@@ -843,7 +843,7 @@ func (a *AndroidAppImport) uncompressDex(
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.Command().
|
||||
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).
|
||||
FlagWithOutput("-o ", outputPath).
|
||||
FlagWithArg("-0 ", "'classes*.dex'").
|
||||
@@ -1067,7 +1067,7 @@ func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, man
|
||||
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
|
||||
|
||||
rule := android.NewRuleBuilder()
|
||||
cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")).
|
||||
cmd := rule.Command().BuiltTool(ctx, "manifest_check").
|
||||
Flag("--enforce-uses-libraries").
|
||||
Input(manifest).
|
||||
FlagWithOutput("-o ", outputFile)
|
||||
|
@@ -229,7 +229,7 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI
|
||||
if image.zip != nil {
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
|
||||
BuiltTool(ctx, "soong_zip").
|
||||
FlagWithOutput("-o ", image.zip).
|
||||
FlagWithArg("-C ", image.dir.String()).
|
||||
FlagWithInputList("-f ", allFiles, " -f ")
|
||||
@@ -438,7 +438,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImage) {
|
||||
rule := android.NewRuleBuilder()
|
||||
rule.Command().
|
||||
// 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(), ":").
|
||||
FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":").
|
||||
FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]).
|
||||
|
@@ -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 {
|
||||
module := &Javadoc{}
|
||||
|
||||
@@ -509,6 +510,7 @@ func JavadocFactory() android.Module {
|
||||
return module
|
||||
}
|
||||
|
||||
// javadoc_host converts .java source files to documentation using javadoc.
|
||||
func JavadocHostFactory() android.Module {
|
||||
module := &Javadoc{}
|
||||
|
||||
@@ -798,7 +800,7 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
"srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(),
|
||||
"stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
|
||||
"srcJars": strings.Join(j.srcJars.Strings(), " "),
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
"bootclasspathArgs": bootClasspathArgs,
|
||||
"classpathArgs": classpathArgs,
|
||||
"sourcepathArgs": sourcepathArgs,
|
||||
@@ -831,6 +833,7 @@ type Droiddoc struct {
|
||||
apiFilePath android.Path
|
||||
}
|
||||
|
||||
// droiddoc converts .java source files to documentation using doclava or dokka.
|
||||
func DroiddocFactory() android.Module {
|
||||
module := &Droiddoc{}
|
||||
|
||||
@@ -841,6 +844,7 @@ func DroiddocFactory() android.Module {
|
||||
return module
|
||||
}
|
||||
|
||||
// droiddoc_host converts .java source files to documentation using doclava or dokka.
|
||||
func DroiddocHostFactory() android.Module {
|
||||
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 " +
|
||||
"-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " +
|
||||
"-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) == "" {
|
||||
// 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(),
|
||||
"stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(),
|
||||
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
"bootclasspathArgs": bootclasspathArgs,
|
||||
"classpathArgs": classpathArgs,
|
||||
"sourcepathArgs": sourcepathArgs,
|
||||
@@ -1117,7 +1121,7 @@ func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removed
|
||||
Args: map[string]string{
|
||||
"msg": msg,
|
||||
"classpath": checkApiClasspath.FormJavaClassPath(""),
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
"apiFile": apiFile.String(),
|
||||
"apiFileToCheck": d.apiFile.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(),
|
||||
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
|
||||
"classpathArgs": classpathArgs,
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
"docZip": d.Javadoc.docZip.String(),
|
||||
},
|
||||
})
|
||||
@@ -1258,6 +1262,9 @@ type Droidstubs struct {
|
||||
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 {
|
||||
module := &Droidstubs{}
|
||||
|
||||
@@ -1268,6 +1275,10 @@ func DroidstubsFactory() android.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 {
|
||||
module := &Droidstubs{}
|
||||
|
||||
@@ -1558,7 +1569,7 @@ func (d *Droidstubs) transformMetalava(ctx android.ModuleContext, implicits andr
|
||||
"bootclasspathArgs": bootclasspathArgs,
|
||||
"classpathArgs": classpathArgs,
|
||||
"sourcepathArgs": sourcepathArgs,
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
},
|
||||
})
|
||||
}
|
||||
@@ -1581,7 +1592,7 @@ func (d *Droidstubs) transformCheckApi(ctx android.ModuleContext,
|
||||
"bootclasspathArgs": bootclasspathArgs,
|
||||
"classpathArgs": classpathArgs,
|
||||
"sourcepathArgs": sourcepathArgs,
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
"msg": msg,
|
||||
},
|
||||
})
|
||||
@@ -1602,7 +1613,7 @@ func (d *Droidstubs) transformJdiff(ctx android.ModuleContext, implicits android
|
||||
"srcJarDir": android.PathForModuleOut(ctx, "jdiff-srcjars").String(),
|
||||
"stubsDir": android.PathForModuleOut(ctx, "jdiff-stubsDir").String(),
|
||||
"srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "),
|
||||
"opts": opts,
|
||||
"opts": proptools.NinjaEscape(opts),
|
||||
"bootclasspathArgs": bootclasspathArgs,
|
||||
"classpathArgs": classpathArgs,
|
||||
"sourcepathArgs": sourcepathArgs,
|
||||
@@ -1781,6 +1792,7 @@ type ExportedDroiddocDir struct {
|
||||
dir android.Path
|
||||
}
|
||||
|
||||
// droiddoc_exported_dir exports a directory of html templates or nullability annotations for use by doclava.
|
||||
func ExportedDroiddocDirFactory() android.Module {
|
||||
module := &ExportedDroiddocDir{}
|
||||
module.AddProperties(&module.properties)
|
||||
|
@@ -2088,14 +2088,14 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
|
||||
// use zip2zip to uncompress classes*.dex files
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "zip2zip")).
|
||||
BuiltTool(ctx, "zip2zip").
|
||||
FlagWithInput("-i ", inputJar).
|
||||
FlagWithOutput("-o ", temporary).
|
||||
FlagWithArg("-0 ", "'classes*.dex'")
|
||||
|
||||
// use zipalign to align uncompressed classes*.dex files
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "zipalign")).
|
||||
BuiltTool(ctx, "zipalign").
|
||||
Flag("-f").
|
||||
Text("4").
|
||||
Input(temporary).
|
||||
|
@@ -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
|
||||
// into a srcjar.
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
|
||||
BuiltTool(ctx, "soong_zip").
|
||||
Flag("-jar").
|
||||
FlagWithOutput("-o ", srcJarFile).
|
||||
FlagWithArg("-C ", outDir.String()).
|
||||
|
@@ -296,7 +296,7 @@ func createSdkFrameworkAidl(ctx android.SingletonContext) {
|
||||
rule.Command().
|
||||
Text("rm -f").Output(aidl)
|
||||
rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "sdkparcelables")).
|
||||
BuiltTool(ctx, "sdkparcelables").
|
||||
Input(jar).
|
||||
Output(aidl)
|
||||
|
||||
|
@@ -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
|
||||
// into a srcszip.
|
||||
zipCmd := rule.Command().
|
||||
Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
|
||||
BuiltTool(ctx, "soong_zip").
|
||||
FlagWithOutput("-o ", srcsZipFile)
|
||||
if pkgPath != "" {
|
||||
zipCmd.FlagWithArg("-P ", pkgPath)
|
||||
|
@@ -48,11 +48,11 @@ if [ ! -r "${jardir}/${jarfile}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
javaOpts=""
|
||||
declare -a javaOpts=()
|
||||
while expr "x$1" : 'x-J' >/dev/null; do
|
||||
opt=`expr "$1" : '-J\(.*\)'`
|
||||
javaOpts="${javaOpts} -${opt}"
|
||||
opt=`expr "$1" : '-J-\{0,1\}\(.*\)'`
|
||||
javaOpts+=("-${opt}")
|
||||
shift
|
||||
done
|
||||
|
||||
exec java ${javaOpts} -jar ${jardir}/${jarfile} "$@"
|
||||
exec java "${javaOpts[@]}" -jar ${jardir}/${jarfile} "$@"
|
||||
|
Reference in New Issue
Block a user