blob: e50275186f51c1bf8361a1bcf7795acaf57bd2de [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package query
import (
"context"
"errors"
"flag"
"fmt"
"os"
"github.com/maruel/subcommands"
"go.chromium.org/luci/common/cli"
"infra/build/siso/toolsupport/ninjautil"
)
const ruleUsage = `query build rule
$ siso query rule -C <dir> <targets>
prints filtered ninja build rules for <targets>.
`
// cmdRule returns the Command for the `rule` subcommand provided by this package.
func cmdRule() *subcommands.Command {
return &subcommands.Command{
UsageLine: "rule [-C <dir>] [<targets>...]",
ShortDesc: "query build step rule",
LongDesc: ruleUsage,
CommandRun: func() subcommands.CommandRun {
c := &ruleRun{}
c.init()
return c
},
}
}
type ruleRun struct {
subcommands.CommandRunBase
dir string
fname string
}
func (c *ruleRun) init() {
c.Flags.StringVar(&c.dir, "C", ".", "ninja running directory to find build.ninja")
c.Flags.StringVar(&c.fname, "f", "build.ninja", "input build filename (relative to -C")
}
func (c *ruleRun) Run(a subcommands.Application, args []string, env subcommands.Env) int {
ctx := cli.GetContext(a, c, env)
err := c.run(ctx, args)
if err != nil {
switch {
case errors.Is(err, flag.ErrHelp):
fmt.Fprintf(os.Stderr, "%v\n%s\n", err, ruleUsage)
default:
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
}
return 1
}
return 0
}
func (c *ruleRun) run(ctx context.Context, args []string) error {
state := ninjautil.NewState()
p := ninjautil.NewManifestParser(state)
err := os.Chdir(c.dir)
if err != nil {
return err
}
err = p.Load(ctx, c.fname)
if err != nil {
return err
}
nodes, err := state.Targets(args)
if err != nil {
return err
}
for _, node := range nodes {
edge, ok := node.InEdge()
if !ok {
fmt.Printf("# no rule to build %s\n\n", node.Path())
continue
}
edge.Print(os.Stdout)
fmt.Printf("# %s is used by the following targets\n", node.Path())
for _, edge := range node.OutEdges() {
outs := edge.Outputs()
if len(outs) == 0 {
continue
}
fmt.Printf("# %s\n", outs[0].Path())
}
fmt.Printf("\n\n")
}
return nil
}