Merge changes I43e61218,Iea36ecaa

* changes:
  Add an option to gather CPU profile.
  Allow $(filter ...) with arbitrary args if its result is compared to the empty string
This commit is contained in:
Treehugger Robot 2021-08-02 20:18:17 +00:00 committed by Gerrit Code Review
commit e083a05ad0
4 changed files with 87 additions and 46 deletions

View file

@ -28,6 +28,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"runtime/debug" "runtime/debug"
"runtime/pprof"
"sort" "sort"
"strings" "strings"
"time" "time"
@ -52,6 +53,7 @@ var (
outputTop = flag.String("outdir", "", "write output files into this directory hierarchy") outputTop = flag.String("outdir", "", "write output files into this directory hierarchy")
launcher = flag.String("launcher", "", "generated launcher path. If set, the non-flag argument is _product_name_") launcher = flag.String("launcher", "", "generated launcher path. If set, the non-flag argument is _product_name_")
printProductConfigMap = flag.Bool("print_product_config_map", false, "print product config map and exit") printProductConfigMap = flag.Bool("print_product_config_map", false, "print product config map and exit")
cpuProfile = flag.String("cpu_profile", "", "write cpu profile to file")
traceCalls = flag.Bool("trace_calls", false, "trace function calls") traceCalls = flag.Bool("trace_calls", false, "trace function calls")
) )
@ -122,6 +124,14 @@ func main() {
tracedVariables = strings.Split(*traceVar, ",") tracedVariables = strings.Split(*traceVar, ",")
} }
if *cpuProfile != "" {
f, err := os.Create(*cpuProfile)
if err != nil {
quit(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
// Find out global variables // Find out global variables
getConfigVariables() getConfigVariables()
getSoongVariables() getSoongVariables()

View file

@ -240,22 +240,21 @@ func (eq *eqExpr) eval(valueMap map[string]starlarkExpr) (res starlarkExpr, same
} }
func (eq *eqExpr) emit(gctx *generationContext) { func (eq *eqExpr) emit(gctx *generationContext) {
// Are we checking that a variable is empty? emitSimple := func(expr starlarkExpr) {
var varRef *variableRefExpr
if s, ok := maybeString(eq.left); ok && s == "" {
varRef, ok = eq.right.(*variableRefExpr)
} else if s, ok := maybeString(eq.right); ok && s == "" {
varRef, ok = eq.left.(*variableRefExpr)
}
if varRef != nil {
// Yes.
if eq.isEq { if eq.isEq {
gctx.write("not ") gctx.write("not ")
} }
varRef.emit(gctx) expr.emit(gctx)
return
} }
// Are we checking that a variable is empty?
if isEmptyString(eq.left) {
emitSimple(eq.right)
return
} else if isEmptyString(eq.right) {
emitSimple(eq.left)
return
}
// General case // General case
eq.left.emit(gctx) eq.left.emit(gctx)
if eq.isEq { if eq.isEq {
@ -578,3 +577,8 @@ func maybeConvertToStringList(expr starlarkExpr) starlarkExpr {
} }
return expr return expr
} }
func isEmptyString(expr starlarkExpr) bool {
x, ok := expr.(*stringLiteralExpr)
return ok && x.literal == ""
}

View file

@ -938,14 +938,14 @@ func (ctx *parseContext) parseCheckFunctionCallResult(directive *mkparser.Direct
func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive, func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
filterFuncCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr { filterFuncCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
// We handle: // We handle:
// * ifeq/ifneq (,$(filter v1 v2 ..., $(VAR)) becomes if VAR not in/in ["v1", "v2", ...] // * ifeq/ifneq (,$(filter v1 v2 ..., EXPR) becomes if EXPR not in/in ["v1", "v2", ...]
// * ifeq/ifneq (,$(filter $(VAR), v1 v2 ...) becomes if VAR not in/in ["v1", "v2", ...] // * ifeq/ifneq (,$(filter EXPR, v1 v2 ...) becomes if EXPR not in/in ["v1", "v2", ...]
// * ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...) becomes if VAR in/not in ["v1", "v2"] // * ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...) becomes if VAR in/not in ["v1", "v2"]
// TODO(Asmundak): check the last case works for filter-out, too. // TODO(Asmundak): check the last case works for filter-out, too.
xPattern := filterFuncCall.args[0] xPattern := filterFuncCall.args[0]
xText := filterFuncCall.args[1] xText := filterFuncCall.args[1]
var xInList *stringLiteralExpr var xInList *stringLiteralExpr
var xVar starlarkExpr var expr starlarkExpr
var ok bool var ok bool
switch x := xValue.(type) { switch x := xValue.(type) {
case *stringLiteralExpr: case *stringLiteralExpr:
@ -955,34 +955,42 @@ func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
// Either pattern or text should be const, and the // Either pattern or text should be const, and the
// non-const one should be varRefExpr // non-const one should be varRefExpr
if xInList, ok = xPattern.(*stringLiteralExpr); ok { if xInList, ok = xPattern.(*stringLiteralExpr); ok {
xVar = xText expr = xText
} else if xInList, ok = xText.(*stringLiteralExpr); ok { } else if xInList, ok = xText.(*stringLiteralExpr); ok {
xVar = xPattern expr = xPattern
} else {
return &callExpr{
object: nil,
name: filterFuncCall.name,
args: filterFuncCall.args,
returnType: starlarkTypeBool,
}
} }
case *variableRefExpr: case *variableRefExpr:
if v, ok := xPattern.(*variableRefExpr); ok { if v, ok := xPattern.(*variableRefExpr); ok {
if xInList, ok = xText.(*stringLiteralExpr); ok && v.ref.name() == x.ref.name() { if xInList, ok = xText.(*stringLiteralExpr); ok && v.ref.name() == x.ref.name() {
// ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...), flip negate, // ifeq/ifneq ($(VAR),$(filter $(VAR), v1 v2 ...), flip negate,
// it's the opposite to what is done when comparing to empty. // it's the opposite to what is done when comparing to empty.
xVar = xPattern expr = xPattern
negate = !negate negate = !negate
} }
} }
} }
if xVar != nil && xInList != nil { if expr != nil && xInList != nil {
if _, ok := xVar.(*variableRefExpr); ok { slExpr := newStringListExpr(strings.Fields(xInList.literal))
slExpr := newStringListExpr(strings.Fields(xInList.literal)) // Generate simpler code for the common cases:
// Generate simpler code for the common cases: if expr.typ() == starlarkTypeList {
if xVar.typ() == starlarkTypeList { if len(slExpr.items) == 1 {
if len(slExpr.items) == 1 { // Checking that a string belongs to list
// Checking that a string belongs to list return &inExpr{isNot: negate, list: expr, expr: slExpr.items[0]}
return &inExpr{isNot: negate, list: xVar, expr: slExpr.items[0]} } else {
} else { // TODO(asmundak):
// TODO(asmundak): panic("TBD")
panic("TBD")
}
} }
return &inExpr{isNot: negate, list: newStringListExpr(strings.Fields(xInList.literal)), expr: xVar} } else if len(slExpr.items) == 1 {
return &eqExpr{left: expr, right: slExpr.items[0], isEq: !negate}
} else {
return &inExpr{isNot: negate, list: newStringListExpr(strings.Fields(xInList.literal)), expr: expr}
} }
} }
return ctx.newBadExpr(cond, "filter arguments are too complex: %s", cond.Dump()) return ctx.newBadExpr(cond, "filter arguments are too complex: %s", cond.Dump())
@ -990,7 +998,7 @@ func (ctx *parseContext) parseCompareFilterFuncResult(cond *mkparser.Directive,
func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Directive, func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Directive,
xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr { xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
if x, ok := xValue.(*stringLiteralExpr); !ok || x.literal != "" { if !isEmptyString(xValue) {
return ctx.newBadExpr(directive, "wildcard result can be compared only to empty: %s", xValue) return ctx.newBadExpr(directive, "wildcard result can be compared only to empty: %s", xValue)
} }
callFunc := wildcardExistsPhony callFunc := wildcardExistsPhony
@ -1006,19 +1014,19 @@ func (ctx *parseContext) parseCompareWildcardFuncResult(directive *mkparser.Dire
func (ctx *parseContext) parseCheckFindstringFuncResult(directive *mkparser.Directive, func (ctx *parseContext) parseCheckFindstringFuncResult(directive *mkparser.Directive,
xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr { xCall *callExpr, xValue starlarkExpr, negate bool) starlarkExpr {
if x, ok := xValue.(*stringLiteralExpr); !ok || x.literal != "" { if isEmptyString(xValue) {
return ctx.newBadExpr(directive, "findstring result can be compared only to empty: %s", xValue) return &eqExpr{
} left: &callExpr{
return &eqExpr{ object: xCall.args[1],
left: &callExpr{ name: "find",
object: xCall.args[1], args: []starlarkExpr{xCall.args[0]},
name: "find", returnType: starlarkTypeInt,
args: []starlarkExpr{xCall.args[0]}, },
returnType: starlarkTypeInt, right: &intLiteralExpr{-1},
}, isEq: !negate,
right: &intLiteralExpr{-1}, }
isEq: !negate,
} }
return ctx.newBadExpr(directive, "findstring result can be compared only to empty: %s", xValue)
} }
func (ctx *parseContext) parseCompareStripFuncResult(directive *mkparser.Directive, func (ctx *parseContext) parseCompareStripFuncResult(directive *mkparser.Directive,

View file

@ -342,6 +342,8 @@ ifneq (,$(filter plaf,$(PLATFORM_LIST)))
endif endif
ifeq ($(TARGET_BUILD_VARIANT), $(filter $(TARGET_BUILD_VARIANT), userdebug eng)) ifeq ($(TARGET_BUILD_VARIANT), $(filter $(TARGET_BUILD_VARIANT), userdebug eng))
endif endif
ifneq (,$(filter true, $(v1)$(v2)))
endif
`, `,
expected: `load("//build/make/core:product_config.rbc", "rblf") expected: `load("//build/make/core:product_config.rbc", "rblf")
@ -349,12 +351,14 @@ def init(g, handle):
cfg = rblf.cfg(handle) cfg = rblf.cfg(handle)
if g["TARGET_BUILD_VARIANT"] not in ["userdebug", "eng"]: if g["TARGET_BUILD_VARIANT"] not in ["userdebug", "eng"]:
pass pass
if g["TARGET_BUILD_VARIANT"] in ["userdebug"]: if g["TARGET_BUILD_VARIANT"] == "userdebug":
pass pass
if "plaf" in g.get("PLATFORM_LIST", []): if "plaf" in g.get("PLATFORM_LIST", []):
pass pass
if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]: if g["TARGET_BUILD_VARIANT"] in ["userdebug", "eng"]:
pass pass
if "%s%s" % (_v1, _v2) == "true":
pass
`, `,
}, },
{ {
@ -385,8 +389,23 @@ endif
def init(g, handle): def init(g, handle):
cfg = rblf.cfg(handle) cfg = rblf.cfg(handle)
if g["TARGET_PRODUCT"] not in ["yukawa_gms", "yukawa_sei510_gms"]: if g["TARGET_PRODUCT"] not in ["yukawa_gms", "yukawa_sei510_gms"]:
if g["TARGET_PRODUCT"] in ["yukawa_gms"]: if g["TARGET_PRODUCT"] == "yukawa_gms":
pass pass
`,
},
{
desc: "filter $(V1), $(V2)",
mkname: "product.mk",
in: `
ifneq (, $(filter $(PRODUCT_LIST), $(TARGET_PRODUCT)))
endif
`,
expected: `load("//build/make/core:product_config.rbc", "rblf")
def init(g, handle):
cfg = rblf.cfg(handle)
if rblf.filter(g.get("PRODUCT_LIST", ""), g["TARGET_PRODUCT"]):
pass
`, `,
}, },
{ {
@ -779,7 +798,7 @@ endif
def init(g, handle): def init(g, handle):
cfg = rblf.cfg(handle) cfg = rblf.cfg(handle)
if rblf.mkstrip(g.get("TARGET_VENDOR", "")) != "": if rblf.mkstrip(g.get("TARGET_VENDOR", "")):
pass pass
`, `,
}, },