diff options
| author | Fumitoshi Ukai <ukai@google.com> | 2015-07-27 16:50:00 +0900 |
|---|---|---|
| committer | Fumitoshi Ukai <ukai@google.com> | 2015-07-27 16:50:00 +0900 |
| commit | d4a016e6d7e6e67d549c9e753494704a9df821a3 (patch) | |
| tree | 7a003fe14d2a5351b0eee77a4c49627335b7b4da /ninja.go | |
| parent | 41957e0349f042904a8dd5d7ba74f38c0a215c92 (diff) | |
[go] backport [C++] ninja file regeneration rules
Diffstat (limited to 'ninja.go')
| -rw-r--r-- | ninja.go | 117 |
1 files changed, 101 insertions, 16 deletions
@@ -28,10 +28,16 @@ import ( // NinjaGenerator generates ninja build files from DepGraph. type NinjaGenerator struct { + // Args is original arguments to generate the ninja file. + Args []string + // Suffix is suffix for generated files. + Suffix string // GomaDir is goma directory. If empty, goma will not be used. GomaDir string // DetectAndroidEcho detects echo as description. DetectAndroidEcho bool + // ErrorOnEnvChange cause error when env change is detected when run ninja. + ErrorOnEnvChange bool f *os.File nodes []*DepNode @@ -447,16 +453,85 @@ func (n *NinjaGenerator) emitNode(node *DepNode) error { return nil } -func (n *NinjaGenerator) shName(suffix string) string { - return fmt.Sprintf("ninja%s.sh", suffix) +func (n *NinjaGenerator) emitRegenRules() error { + if len(n.Args) == 0 { + return nil + } + mkfiles, err := n.ctx.ev.EvaluateVar("MAKEFILE_LIST") + if err != nil { + return err + } + fmt.Fprintf(n.f, ` +rule regen_ninja + description = Regenerate ninja files due to dependency + generator=1 + command=%s +`, strings.Join(n.Args, " ")) + fmt.Fprintf(n.f, "build %s: regen_ninja %s", n.ninjaName(), mkfiles) + // TODO: Add dependencies to directories read by $(wildcard) or + // $(shell find). + if len(usedEnvs) > 0 { + fmt.Fprintf(n.f, " %s", n.envlistName()) + } + fmt.Fprintf(n.f, "\n\n") + if len(usedEnvs) == 0 { + return nil + } + fmt.Fprint(n.f, ` +build .always_build: phony +rule regen_envlist + description = Check $out + generator = 1 + restat = 1 + command = rm -f $out.tmp`) + for env := range usedEnvs { + fmt.Fprintf(n.f, " && echo %s=$$%s >> $out.tmp", env, env) + } + if n.ErrorOnEnvChange { + fmt.Fprintln(n.f, " && (cmp -s $out.tmp $out || (echo Environment variable changes are detected && diff -u $out $out.tmp))") + } else { + fmt.Fprintln(n.f, " && (cmp -s $out.tmp $out || mv $out.tmp $out)") + } + + fmt.Fprintf(n.f, "build %s: regen_envlist .always_build\n\n", n.envlistName()) + return nil +} + +func (n *NinjaGenerator) shName() string { + return fmt.Sprintf("ninja%s.sh", n.Suffix) +} + +func (n *NinjaGenerator) ninjaName() string { + return fmt.Sprintf("build%s.ninja", n.Suffix) } -func (n *NinjaGenerator) ninjaName(suffix string) string { - return fmt.Sprintf("build%s.ninja", suffix) +func (n *NinjaGenerator) envlistName() string { + return fmt.Sprintf(".kati_env%s", n.Suffix) } -func (n *NinjaGenerator) generateShell(suffix string) (err error) { - f, err := os.Create(n.shName(suffix)) +func (n *NinjaGenerator) generateEnvlist() (err error) { + f, err := os.Create(n.envlistName()) + if err != nil { + return err + } + defer func() { + cerr := f.Close() + if err == nil { + err = cerr + } + }() + for k := range usedEnvs { + v, err := n.ctx.ev.EvaluateVar(k) + if err != nil { + return err + } + fmt.Fprintf(f, "%s=%s\n", k, v) + } + return nil +} + +func (n *NinjaGenerator) generateShell() (err error) { + f, err := os.Create(n.shName()) if err != nil { return err } @@ -471,6 +546,9 @@ func (n *NinjaGenerator) generateShell(suffix string) (err error) { fmt.Fprintf(f, "# Generated by kati %s\n", gitVersion) fmt.Fprintln(f) fmt.Fprintln(f, `cd $(dirname "$0")`) + if n.Suffix != "" { + fmt.Fprintf(f, "if [ -f %s ]; then\n export $(cat %s)\nfi\n", n.envlistName(), n.envlistName()) + } for name, export := range n.exports { if export { v, err := n.ctx.ev.EvaluateVar(name) @@ -483,16 +561,16 @@ func (n *NinjaGenerator) generateShell(suffix string) (err error) { } } if n.GomaDir == "" { - fmt.Fprintf(f, `exec ninja -f %s "$@"`+"\n", n.ninjaName(suffix)) + fmt.Fprintf(f, `exec ninja -f %s "$@"`+"\n", n.ninjaName()) } else { - fmt.Fprintf(f, `exec ninja -f %s -j500 "$@"`+"\n", n.ninjaName(suffix)) + fmt.Fprintf(f, `exec ninja -f %s -j500 "$@"`+"\n", n.ninjaName()) } return f.Chmod(0755) } -func (n *NinjaGenerator) generateNinja(suffix, defaultTarget string) (err error) { - f, err := os.Create(n.ninjaName(suffix)) +func (n *NinjaGenerator) generateNinja(defaultTarget string) (err error) { + f, err := os.Create(n.ninjaName()) if err != nil { return err } @@ -526,7 +604,12 @@ func (n *NinjaGenerator) generateNinja(suffix, defaultTarget string) (err error) if n.GomaDir != "" { fmt.Fprintf(n.f, "pool local_pool\n") - fmt.Fprintf(n.f, " depth = %d\n", runtime.NumCPU()) + fmt.Fprintf(n.f, " depth = %d\n\n", runtime.NumCPU()) + } + + err = n.emitRegenRules() + if err != nil { + return err } // defining $out for $@ and $in for $^ here doesn't work well, @@ -558,16 +641,18 @@ func (n *NinjaGenerator) generateNinja(suffix, defaultTarget string) (err error) } fmt.Fprintf(n.f, "build %s: phony %s\n", name, n.shortNames[name][0]) } - // TODO(ukai): regenerate build.ninja when Makefile or dir used for - // wildcard is newer than build.ninja? return nil } // Save generates build.ninja from DepGraph. -func (n *NinjaGenerator) Save(g *DepGraph, suffix string, targets []string) error { +func (n *NinjaGenerator) Save(g *DepGraph, name string, targets []string) error { startTime := time.Now() n.init(g) - err := n.generateShell(suffix) + err := n.generateEnvlist() + if err != nil { + return err + } + err = n.generateShell() if err != nil { return err } @@ -575,7 +660,7 @@ func (n *NinjaGenerator) Save(g *DepGraph, suffix string, targets []string) erro if len(targets) == 0 && len(g.nodes) > 0 { defaultTarget = g.nodes[0].Output } - err = n.generateNinja(suffix, defaultTarget) + err = n.generateNinja(defaultTarget) if err != nil { return err } |
