aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile17
-rw-r--r--ast.cc2
-rw-r--r--ast.go6
-rw-r--r--bootstrap.go56
-rw-r--r--cmd/kati/main.go289
-rw-r--r--cmdline.go48
-rw-r--r--dep.cc2
-rw-r--r--dep.go6
-rw-r--r--depgraph.go115
-rw-r--r--doc.go8
-rw-r--r--eval.cc2
-rw-r--r--eval.go31
-rw-r--r--exec.cc2
-rw-r--r--exec.go25
-rw-r--r--expr.go4
-rw-r--r--expr_test.go2
-rw-r--r--file.cc2
-rw-r--r--file_cache.cc2
-rw-r--r--fileutil.cc2
-rw-r--r--fileutil.go2
-rw-r--r--flags.go30
-rw-r--r--func.cc2
-rw-r--r--func.go20
-rw-r--r--func_test.go8
-rw-r--r--ioutil.go2
-rw-r--r--log.go20
-rw-r--r--main.cc2
-rw-r--r--main.go412
-rw-r--r--ninja.go24
-rw-r--r--ninja_test.go2
-rw-r--r--para.cc2
-rw-r--r--para.go8
-rw-r--r--para_test.go6
-rw-r--r--parser.cc2
-rw-r--r--parser.go8
-rw-r--r--pathutil.go20
-rw-r--r--query.go2
-rw-r--r--rule.cc2
-rw-r--r--rule_parser.go2
-rw-r--r--rule_parser_test.go2
-rw-r--r--serialize.go6
-rw-r--r--shellutil.go24
-rw-r--r--shellutil_test.go8
-rw-r--r--stats.go30
-rw-r--r--string_piece.cc2
-rw-r--r--string_piece_test.cc2
-rw-r--r--string_pool.cc2
-rw-r--r--stringprintf.cc2
-rw-r--r--strutil.cc2
-rw-r--r--strutil.go2
-rw-r--r--strutil_test.cc2
-rw-r--r--strutil_test.go2
-rw-r--r--symtab.go2
-rw-r--r--value.cc2
-rw-r--r--var.cc2
-rw-r--r--var.go2
-rw-r--r--worker.go38
58 files changed, 779 insertions, 552 deletions
diff --git a/.gitignore b/.gitignore
index 6fa2b88..61de556 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
kati
+!cmd/kati/
ckati
para
*.o
@@ -12,3 +13,4 @@ bench-old.out
bench-new.out
string_piece_test
strutil_test
+go_src_stamp
diff --git a/Makefile b/Makefile
index 57e82c5..1641884 100644
--- a/Makefile
+++ b/Makefile
@@ -41,8 +41,18 @@ CXXFLAGS:=-g -W -Wall -MMD # -O
all: kati para ckati $(CXX_TEST_EXES)
-kati: $(GO_SRCS)
- env $(shell go env) go build -o $@ *.go
+kati: go_src_stamp
+ GOPATH=$$(pwd)/out go install github.com/google/kati/cmd/kati
+ cp out/bin/kati $@
+
+go_src_stamp: $(GO_SRCS) cmd/*/*.go
+ -rm -rf out/src/github.com/google/kati
+ mkdir -p out/src/github.com/google/kati
+ cp -a $(GO_SRCS) cmd out/src/github.com/google/kati
+ touch $@
+
+go_test: $(GO_SRCS) para
+ go test *.go
ckati: $(CXX_OBJS)
$(CXX) -std=c++11 $(CXXFLAGS) -o $@ $(CXX_OBJS)
@@ -54,9 +64,6 @@ $(CXX_TEST_EXES): $(filter-out main.o,$(CXX_OBJS))
$(CXX_TEST_EXES): %: %.o
$(CXX) $^ -o $@
-go_test: $(GO_SRCS) para
- env $(shell go env) go test *.go
-
para: para.cc
$(CXX) -std=c++11 -g -O -W -Wall -MMD -o $@ $<
diff --git a/ast.cc b/ast.cc
index 344b42c..fdcfeb3 100644
--- a/ast.cc
+++ b/ast.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "ast.h"
#include "eval.h"
diff --git a/ast.go b/ast.go
index a8a2d8b..05256ff 100644
--- a/ast.go
+++ b/ast.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -20,8 +20,6 @@ import (
"strings"
)
-const BootstrapMakefile = "*bootstrap*"
-
type AST interface {
eval(*Evaluator)
show()
@@ -46,7 +44,7 @@ func (ast *AssignAST) eval(ev *Evaluator) {
func (ast *AssignAST) evalRHS(ev *Evaluator, lhs string) Var {
origin := "file"
- if ast.filename == BootstrapMakefile {
+ if ast.filename == bootstrapMakefileName {
origin = "default"
}
if ast.opt == "override" {
diff --git a/bootstrap.go b/bootstrap.go
new file mode 100644
index 0000000..de13b2b
--- /dev/null
+++ b/bootstrap.go
@@ -0,0 +1,56 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kati
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+)
+
+const bootstrapMakefileName = "*bootstrap*"
+
+func BootstrapMakefile(targets []string) Makefile {
+ bootstrap := `
+CC:=cc
+CXX:=g++
+AR:=ar
+MAKE:=kati
+# Pretend to be GNU make 3.81, for compatibility.
+MAKE_VERSION:=3.81
+SHELL:=/bin/sh
+# TODO: Add more builtin vars.
+
+# http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
+# The document above is actually not correct. See default.c:
+# http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
+.c.o:
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<
+.cc.o:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<
+# TODO: Add more builtin rules.
+`
+ bootstrap += fmt.Sprintf("MAKECMDGOALS:=%s\n", strings.Join(targets, " "))
+ cwd, err := filepath.Abs(".")
+ if err != nil {
+ panic(err)
+ }
+ bootstrap += fmt.Sprintf("CURDIR:=%s\n", cwd)
+ mk, err := ParseMakefileString(bootstrap, bootstrapMakefileName, 0)
+ if err != nil {
+ panic(err)
+ }
+ return mk
+}
diff --git a/cmd/kati/main.go b/cmd/kati/main.go
new file mode 100644
index 0000000..2128a07
--- /dev/null
+++ b/cmd/kati/main.go
@@ -0,0 +1,289 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "os"
+ "path/filepath"
+ "runtime"
+ "runtime/pprof"
+ "strings"
+ "text/template"
+ "time"
+
+ "github.com/google/kati"
+)
+
+const shellDateTimeformat = time.RFC3339
+
+var (
+ makefileFlag string
+ jobsFlag int
+
+ loadJSON string
+ saveJSON string
+ loadGOB string
+ saveGOB string
+ useCache bool
+
+ cpuprofile string
+ heapprofile string
+ memstats string
+ traceEventFile string
+ syntaxCheckOnlyFlag bool
+ queryFlag string
+ eagerCmdEvalFlag bool
+ generateNinja bool
+ gomaDir string
+ usePara bool
+ findCachePrunes string
+ findCacheLeafNames string
+ shellDate string
+)
+
+func init() {
+ // TODO: Make this default and replace this by -d flag.
+ flag.StringVar(&makefileFlag, "f", "", "Use it as a makefile")
+ flag.IntVar(&jobsFlag, "j", 1, "Allow N jobs at once.")
+
+ flag.StringVar(&loadGOB, "load", "", "")
+ flag.StringVar(&saveGOB, "save", "", "")
+ flag.StringVar(&loadJSON, "load_json", "", "")
+ flag.StringVar(&saveJSON, "save_json", "", "")
+ flag.BoolVar(&useCache, "use_cache", false, "Use cache.")
+
+ flag.StringVar(&cpuprofile, "kati_cpuprofile", "", "write cpu profile to `file`")
+ flag.StringVar(&heapprofile, "kati_heapprofile", "", "write heap profile to `file`")
+ flag.StringVar(&memstats, "kati_memstats", "", "Show memstats with given templates")
+ flag.StringVar(&traceEventFile, "kati_trace_event", "", "write trace event to `file`")
+ flag.BoolVar(&syntaxCheckOnlyFlag, "c", false, "Syntax check only.")
+ flag.StringVar(&queryFlag, "query", "", "Show the target info")
+ flag.BoolVar(&eagerCmdEvalFlag, "eager_cmd_eval", false, "Eval commands first.")
+ flag.BoolVar(&generateNinja, "ninja", false, "Generate build.ninja.")
+ flag.StringVar(&gomaDir, "goma_dir", "", "If specified, use goma to build C/C++ files.")
+ flag.BoolVar(&usePara, "use_para", false, "Use para.")
+
+ flag.StringVar(&findCachePrunes, "find_cache_prunes", "",
+ "space separated prune directories for find cache.")
+ flag.StringVar(&findCacheLeafNames, "find_cache_leaf_names", "",
+ "space separated leaf names for find cache.")
+ flag.StringVar(&shellDate, "shell_date", "", "specify $(shell date) time as "+shellDateTimeformat)
+
+ flag.BoolVar(&kati.LogFlag, "kati_log", false, "Verbose kati specific log")
+ flag.BoolVar(&kati.StatsFlag, "kati_stats", false, "Show a bunch of statistics")
+ flag.BoolVar(&kati.PeriodicStatsFlag, "kati_periodic_stats", false, "Show a bunch of periodic statistics")
+ flag.BoolVar(&kati.EvalStatsFlag, "kati_eval_stats", false, "Show eval statistics")
+
+ flag.BoolVar(&kati.DryRunFlag, "n", false, "Only print the commands that would be executed")
+
+ // TODO: Make this default.
+ flag.BoolVar(&kati.UseFindCache, "use_find_cache", false, "Use find cache.")
+ flag.BoolVar(&kati.UseWildcardCache, "use_wildcard_cache", true, "Use wildcard cache.")
+ flag.BoolVar(&kati.UseShellBuiltins, "use_shell_builtins", true, "Use shell builtins")
+ flag.StringVar(&kati.IgnoreOptionalInclude, "ignore_optional_include", "", "If specified, skip reading -include directives start with the specified path.")
+}
+
+func writeHeapProfile() {
+ f, err := os.Create(heapprofile)
+ if err != nil {
+ panic(err)
+ }
+ pprof.WriteHeapProfile(f)
+ f.Close()
+}
+
+type memStatsDumper struct {
+ *template.Template
+}
+
+func (t memStatsDumper) dump() {
+ var ms runtime.MemStats
+ runtime.ReadMemStats(&ms)
+ var buf bytes.Buffer
+ err := t.Template.Execute(&buf, ms)
+ fmt.Println(buf.String())
+ if err != nil {
+ panic(err)
+ }
+}
+
+func findPara() string {
+ switch runtime.GOOS {
+ case "linux":
+ katicmd, err := os.Readlink("/proc/self/exe")
+ if err != nil {
+ panic(err)
+ }
+ return filepath.Join(filepath.Dir(katicmd), "para")
+ default:
+ panic(fmt.Sprintf("unknown OS: %s", runtime.GOOS))
+ }
+}
+
+func load(makefile string, opt kati.LoadOpt) (*kati.DepGraph, error) {
+ startTime := time.Now()
+
+ if loadGOB != "" {
+ g := kati.LoadDepGraph(loadGOB)
+ kati.LogStats("deserialize time: %q", time.Since(startTime))
+ return g, nil
+ }
+ if loadJSON != "" {
+ g := kati.LoadDepGraphFromJSON(loadJSON)
+ kati.LogStats("deserialize time: %q", time.Since(startTime))
+ return g, nil
+ }
+ return kati.Load(makefile, opt)
+}
+
+func save(g *kati.DepGraph, targets []string) {
+ startTime := time.Now()
+ if saveGOB != "" {
+ kati.DumpDepGraph(g, saveGOB, targets)
+ kati.LogStats("serialize time: %q", time.Since(startTime))
+ }
+ if saveJSON != "" {
+ kati.DumpDepGraphAsJSON(g, saveJSON, targets)
+ kati.LogStats("serialize time: %q", time.Since(startTime))
+ }
+
+ if useCache && !g.IsCached() {
+ kati.DumpDepGraphCache(g, targets)
+ kati.LogStats("serialize time: %q", time.Since(startTime))
+ }
+}
+
+func main() {
+ runtime.GOMAXPROCS(runtime.NumCPU())
+ flag.Parse()
+ if cpuprofile != "" {
+ f, err := os.Create(cpuprofile)
+ if err != nil {
+ panic(err)
+ }
+ pprof.StartCPUProfile(f)
+ defer pprof.StopCPUProfile()
+ kati.AtError(pprof.StopCPUProfile)
+ }
+ if heapprofile != "" {
+ defer writeHeapProfile()
+ kati.AtError(writeHeapProfile)
+ }
+ defer kati.DumpStats()
+ kati.AtError(kati.DumpStats)
+ if memstats != "" {
+ ms := memStatsDumper{
+ Template: template.Must(template.New("memstats").Parse(memstats)),
+ }
+ ms.dump()
+ defer ms.dump()
+ kati.AtError(ms.dump)
+ }
+ if traceEventFile != "" {
+ f, err := os.Create(traceEventFile)
+ if err != nil {
+ panic(err)
+ }
+ kati.TraceEventStart(f)
+ defer kati.TraceEventStop()
+ kati.AtError(kati.TraceEventStop)
+ }
+
+ if shellDate != "" {
+ if shellDate == "ref" {
+ shellDate = shellDateTimeformat[:20] // until Z, drop 07:00
+ }
+ t, err := time.Parse(shellDateTimeformat, shellDate)
+ if err != nil {
+ panic(err)
+ }
+ kati.ShellDateTimestamp = t
+ }
+
+ var leafNames []string
+ if findCacheLeafNames != "" {
+ leafNames = strings.Fields(findCacheLeafNames)
+ }
+ if findCachePrunes != "" {
+ kati.UseFindCache = true
+ kati.AndroidFindCacheInit(strings.Fields(findCachePrunes), leafNames)
+ }
+
+ clvars, targets := kati.ParseCommandLine(flag.Args())
+
+ g, err := load(makefileFlag, kati.LoadOpt{
+ Targets: targets,
+ CommandLineVars: clvars,
+ EnvironmentVars: os.Environ(),
+ UseCache: useCache,
+ })
+ if err != nil {
+ panic(err)
+ }
+ nodes := g.Nodes()
+ vars := g.Vars()
+
+ if eagerCmdEvalFlag {
+ startTime := time.Now()
+ kati.EvalCommands(nodes, vars)
+ kati.LogStats("eager eval command time: %q", time.Since(startTime))
+ }
+
+ save(g, targets)
+
+ if generateNinja {
+ startTime := time.Now()
+ kati.GenerateNinja(g, gomaDir)
+ kati.LogStats("generate ninja time: %q", time.Since(startTime))
+ return
+ }
+
+ if syntaxCheckOnlyFlag {
+ return
+ }
+
+ if queryFlag != "" {
+ kati.HandleQuery(queryFlag, g)
+ return
+ }
+
+ // TODO: Handle target specific variables.
+ ev := kati.NewEvaluator(vars)
+ for name, export := range g.Exports() {
+ if export {
+ os.Setenv(name, ev.EvaluateVar(name))
+ } else {
+ os.Unsetenv(name)
+ }
+ }
+
+ startTime := time.Now()
+ execOpt := &kati.ExecutorOpt{
+ NumJobs: jobsFlag,
+ }
+ if usePara {
+ execOpt.ParaPath = findPara()
+ }
+ ex := kati.NewExecutor(vars, execOpt)
+ err = ex.Exec(nodes)
+ if err != nil {
+ panic(err)
+ }
+ kati.LogStats("exec time: %q", time.Since(startTime))
+
+}
diff --git a/cmdline.go b/cmdline.go
new file mode 100644
index 0000000..fa75451
--- /dev/null
+++ b/cmdline.go
@@ -0,0 +1,48 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kati
+
+import (
+ "fmt"
+ "strings"
+)
+
+func ParseCommandLine(cmdline []string) ([]string, []string) {
+ var vars []string
+ var targets []string
+ for _, arg := range cmdline {
+ if strings.IndexByte(arg, '=') >= 0 {
+ vars = append(vars, arg)
+ continue
+ }
+ targets = append(targets, arg)
+ }
+ return vars, targets
+}
+
+func InitVars(vars Vars, kvlist []string, origin string) error {
+ for _, v := range kvlist {
+ kv := strings.SplitN(v, "=", 2)
+ Logf("%s var %q", origin, v)
+ if len(kv) < 2 {
+ return fmt.Errorf("A weird %s variable %q", origin, kv)
+ }
+ vars.Assign(kv[0], &RecursiveVar{
+ expr: literal(kv[1]),
+ origin: origin,
+ })
+ }
+ return nil
+}
diff --git a/dep.cc b/dep.cc
index 0c429d2..9668400 100644
--- a/dep.cc
+++ b/dep.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "dep.h"
#include <algorithm>
diff --git a/dep.go b/dep.go
index 0e29789..1126336 100644
--- a/dep.go
+++ b/dep.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"fmt"
@@ -272,7 +272,7 @@ func (db *DepBuilder) buildPlan(output string, neededBy string, tsvs Vars) (*Dep
if !present || oldVar.String() == "" {
db.vars[name] = tsv
} else {
- v = oldVar.AppendVar(newEvaluator(db.vars), tsv)
+ v = oldVar.AppendVar(NewEvaluator(db.vars), tsv)
db.vars[name] = v
}
tsvs[name] = v
@@ -489,7 +489,7 @@ func (s bySuffix) Less(i, j int) bool {
}
func (db *DepBuilder) reportStats() {
- if !katiLogFlag && !katiPeriodicStatsFlag {
+ if !LogFlag && !PeriodicStatsFlag {
return
}
diff --git a/depgraph.go b/depgraph.go
new file mode 100644
index 0000000..a349980
--- /dev/null
+++ b/depgraph.go
@@ -0,0 +1,115 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kati
+
+import (
+ "crypto/sha1"
+ "io/ioutil"
+ "time"
+)
+
+type DepGraph struct {
+ nodes []*DepNode
+ vars Vars
+ readMks []*ReadMakefile
+ exports map[string]bool
+ isCached bool
+}
+
+func (g *DepGraph) Nodes() []*DepNode { return g.nodes }
+func (g *DepGraph) Vars() Vars { return g.vars }
+func (g *DepGraph) Exports() map[string]bool { return g.exports }
+func (g *DepGraph) IsCached() bool { return g.isCached }
+
+type LoadOpt struct {
+ Targets []string
+ CommandLineVars []string
+ EnvironmentVars []string
+ UseCache bool
+}
+
+func Load(makefile string, opt LoadOpt) (*DepGraph, error) {
+ startTime := time.Now()
+ if makefile == "" {
+ makefile = DefaultMakefile()
+ }
+
+ if opt.UseCache {
+ g := LoadDepGraphCache(makefile, opt.Targets)
+ if g != nil {
+ return g, nil
+ }
+ }
+
+ bmk := BootstrapMakefile(opt.Targets)
+
+ content, err := ioutil.ReadFile(makefile)
+ if err != nil {
+ return nil, err
+ }
+ mk, err := ParseMakefile(content, makefile)
+ if err != nil {
+ return nil, err
+ }
+
+ for _, stmt := range mk.stmts {
+ stmt.show()
+ }
+
+ mk.stmts = append(bmk.stmts, mk.stmts...)
+
+ vars := make(Vars)
+ err = InitVars(vars, opt.EnvironmentVars, "environment")
+ if err != nil {
+ return nil, err
+ }
+ err = InitVars(vars, opt.CommandLineVars, "command line")
+ if err != nil {
+ return nil, err
+ }
+ er, err := Eval(mk, vars, opt.UseCache)
+ if err != nil {
+ return nil, err
+ }
+ vars.Merge(er.vars)
+
+ LogStats("eval time: %q", time.Since(startTime))
+ LogStats("shell func time: %q %d", shellStats.Duration(), shellStats.Count())
+
+ startTime = time.Now()
+ db := NewDepBuilder(er, vars)
+ LogStats("dep build prepare time: %q", time.Since(startTime))
+
+ startTime = time.Now()
+ nodes, err := db.Eval(opt.Targets)
+ if err != nil {
+ return nil, err
+ }
+ LogStats("dep build time: %q", time.Since(startTime))
+ var readMks []*ReadMakefile
+ // Always put the root Makefile as the first element.
+ readMks = append(readMks, &ReadMakefile{
+ Filename: makefile,
+ Hash: sha1.Sum(content),
+ State: FileExists,
+ })
+ readMks = append(readMks, er.readMks...)
+ return &DepGraph{
+ nodes: nodes,
+ vars: vars,
+ readMks: readMks,
+ exports: er.exports,
+ }, nil
+}
diff --git a/doc.go b/doc.go
new file mode 100644
index 0000000..0cea5f9
--- /dev/null
+++ b/doc.go
@@ -0,0 +1,8 @@
+/*
+Package kati provides GNU make compatible functions, especially
+to speed up the continuous build of Android.
+
+*/
+package kati
+
+// TODO(ukai): cleanup API. make more symbol unexported.
diff --git a/eval.cc b/eval.cc
index 94334ed..ab99a01 100644
--- a/eval.cc
+++ b/eval.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "eval.h"
#include <errno.h>
diff --git a/eval.go b/eval.go
index 4d6a980..e168662 100644
--- a/eval.go
+++ b/eval.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -53,6 +53,7 @@ type Evaluator struct {
vars Vars
lastRule *Rule
currentScope Vars
+ useCache bool
avoidIO bool
hasIO bool
readMks map[string]*ReadMakefile
@@ -62,7 +63,7 @@ type Evaluator struct {
lineno int
}
-func newEvaluator(vars map[string]Var) *Evaluator {
+func NewEvaluator(vars map[string]Var) *Evaluator {
return &Evaluator{
outVars: make(Vars),
vars: vars,
@@ -91,7 +92,7 @@ func (ev *Evaluator) args(buf *buffer, args ...Value) [][]byte {
func (ev *Evaluator) evalAssign(ast *AssignAST) {
ev.lastRule = nil
lhs, rhs := ev.evalAssignAST(ast)
- if katiLogFlag {
+ if LogFlag {
Logf("ASSIGN: %s=%q (flavor:%q)", lhs, rhs, rhs.Flavor())
}
if lhs == "" {
@@ -128,7 +129,7 @@ func (ev *Evaluator) setTargetSpecificVar(assign *AssignAST, output string) {
}
ev.currentScope = vars
lhs, rhs := ev.evalAssignAST(assign)
- if katiLogFlag {
+ if LogFlag {
Logf("rule outputs:%q assign:%q=%q (flavor:%q)", output, lhs, rhs, rhs.Flavor())
}
vars.Assign(lhs, &TargetSpecificVar{v: rhs, op: assign.op})
@@ -147,7 +148,7 @@ func (ev *Evaluator) evalMaybeRule(ast *MaybeRuleAST) {
if ast.term == '=' {
line = append(line, ast.afterTerm...)
}
- if katiLogFlag {
+ if LogFlag {
Logf("rule? %q=>%q", ast.expr, line)
}
@@ -166,7 +167,7 @@ func (ev *Evaluator) evalMaybeRule(ast *MaybeRuleAST) {
Error(ast.filename, ast.lineno, "%v", err.Error())
}
freeBuf(buf)
- if katiLogFlag {
+ if LogFlag {
Logf("rule %q => outputs:%q, inputs:%q", line, rule.outputs, rule.inputs)
}
@@ -201,7 +202,7 @@ func (ev *Evaluator) evalMaybeRule(ast *MaybeRuleAST) {
if ast.term == ';' {
rule.cmds = append(rule.cmds, string(ast.afterTerm[1:]))
}
- if katiLogFlag {
+ if LogFlag {
Logf("rule outputs:%q cmds:%q", rule.outputs, rule.cmds)
}
ev.lastRule = rule
@@ -288,7 +289,7 @@ func (ev *Evaluator) evalIncludeFile(fname string, mk Makefile) error {
}
func (ev *Evaluator) updateReadMakefile(fn string, hash [sha1.Size]byte, st FileState) {
- if !useCache {
+ if !ev.useCache {
return
}
@@ -349,7 +350,7 @@ func (ev *Evaluator) evalInclude(ast *IncludeAST) {
}
for _, fn := range files {
- if ignoreOptionalInclude != "" && ast.op == "-include" && matchPattern(fn, ignoreOptionalInclude) {
+ if IgnoreOptionalInclude != "" && ast.op == "-include" && matchPattern(fn, IgnoreOptionalInclude) {
continue
}
mk, hash, err := makefileCache.parse(fn)
@@ -383,7 +384,7 @@ func (ev *Evaluator) evalIf(ast *IfAST) {
val := buf.Len()
freeBuf(buf)
isTrue = (val > 0) == (ast.op == "ifdef")
- if katiLogFlag {
+ if LogFlag {
Logf("%s lhs=%q value=%q => %t", ast.op, ast.lhs, value, isTrue)
}
case "ifeq", "ifneq":
@@ -395,7 +396,7 @@ func (ev *Evaluator) evalIf(ast *IfAST) {
rhs := string(params[1])
freeBuf(buf)
isTrue = (lhs == rhs) == (ast.op == "ifeq")
- if katiLogFlag {
+ if LogFlag {
Logf("%s lhs=%q %q rhs=%q %q => %t", ast.op, ast.lhs, lhs, ast.rhs, rhs, isTrue)
}
default:
@@ -441,8 +442,9 @@ func createReadMakefileArray(mp map[string]*ReadMakefile) []*ReadMakefile {
return r
}
-func Eval(mk Makefile, vars Vars) (er *EvalResult, err error) {
- ev := newEvaluator(vars)
+func Eval(mk Makefile, vars Vars, useCache bool) (er *EvalResult, err error) {
+ ev := NewEvaluator(vars)
+ ev.useCache = useCache
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("panic in eval %s: %v", mk.filename, r)
@@ -450,6 +452,9 @@ func Eval(mk Makefile, vars Vars) (er *EvalResult, err error) {
}()
makefileList := vars.Lookup("MAKEFILE_LIST")
+ if !makefileList.IsDefined() {
+ makefileList = &SimpleVar{value: "", origin: "file"}
+ }
makefileList = makefileList.Append(ev, mk.filename)
ev.outVars.Assign("MAKEFILE_LIST", makefileList)
diff --git a/exec.cc b/exec.cc
index bdfa2fd..44ef68b 100644
--- a/exec.cc
+++ b/exec.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "exec.h"
#include <stdio.h>
diff --git a/exec.go b/exec.go
index 2cacc93..8c1ac1e 100644
--- a/exec.go
+++ b/exec.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -207,7 +207,7 @@ func (ex *Executor) makeJobs(n *DepNode, neededBy *Job) error {
}
func (ex *Executor) reportStats() {
- if !katiLogFlag && !katiPeriodicStatsFlag {
+ if !LogFlag && !PeriodicStatsFlag {
return
}
@@ -218,17 +218,28 @@ func (ex *Executor) reportStats() {
}
}
-func NewExecutor(vars Vars) *Executor {
+type ExecutorOpt struct {
+ NumJobs int
+ ParaPath string
+}
+
+func NewExecutor(vars Vars, opt *ExecutorOpt) *Executor {
+ if opt == nil {
+ opt = &ExecutorOpt{NumJobs: 1}
+ }
+ if opt.NumJobs < 1 {
+ opt.NumJobs = 1
+ }
ex := &Executor{
rules: make(map[string]*Rule),
suffixRules: make(map[string][]*Rule),
done: make(map[string]*Job),
vars: vars,
- wm: NewWorkerManager(),
+ wm: NewWorkerManager(opt.NumJobs, opt.ParaPath),
}
// TODO: We should move this to somewhere around evalCmd so that
// we can handle SHELL in target specific variables.
- ev := newEvaluator(ex.vars)
+ ev := NewEvaluator(ex.vars)
ex.shell = ev.EvaluateVar("SHELL")
for k, v := range map[string]Var{
"@": AutoAtVar{AutoVar: AutoVar{ex: ex}},
@@ -275,7 +286,7 @@ func (ex *Executor) createRunners(n *DepNode, avoidIO bool) ([]runner, bool) {
ex.vars[k] = v
}
- ev := newEvaluator(ex.vars)
+ ev := NewEvaluator(ex.vars)
ev.avoidIO = avoidIO
ev.filename = n.Filename
ev.lineno = n.Lineno
@@ -297,7 +308,7 @@ func (ex *Executor) createRunners(n *DepNode, avoidIO bool) ([]runner, bool) {
func EvalCommands(nodes []*DepNode, vars Vars) {
ioCnt := 0
- ex := NewExecutor(vars)
+ ex := NewExecutor(vars, nil)
for i, n := range nodes {
runners, hasIO := ex.createRunners(n, true)
if hasIO {
diff --git a/expr.go b/expr.go
index 91c861b..f778901 100644
--- a/expr.go
+++ b/expr.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -591,7 +591,7 @@ func parseFunc(f Func, in []byte, s int, term []byte, funcName string, alloc boo
if compactor, ok := f.(Compactor); ok {
fv = compactor.Compact()
}
- if katiEvalStatsFlag || traceEvent.enabled() {
+ if EvalStatsFlag || traceEvent.enabled() {
fv = funcstats{
Value: fv,
str: fv.String(),
diff --git a/expr_test.go b/expr_test.go
index 9b776e0..a7f2fe3 100644
--- a/expr_test.go
+++ b/expr_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"reflect"
diff --git a/file.cc b/file.cc
index fc7969f..7217a37 100644
--- a/file.cc
+++ b/file.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "file.h"
#include <fcntl.h>
diff --git a/file_cache.cc b/file_cache.cc
index 0cd6ea5..b26d054 100644
--- a/file_cache.cc
+++ b/file_cache.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "file_cache.h"
#include <unordered_map>
diff --git a/fileutil.cc b/fileutil.cc
index 92726fa..ebf6fd4 100644
--- a/fileutil.cc
+++ b/fileutil.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "fileutil.h"
#include <errno.h>
diff --git a/fileutil.go b/fileutil.go
index a288b6d..cde353b 100644
--- a/fileutil.go
+++ b/fileutil.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import "os"
diff --git a/flags.go b/flags.go
new file mode 100644
index 0000000..105df2d
--- /dev/null
+++ b/flags.go
@@ -0,0 +1,30 @@
+// Copyright 2015 Google Inc. All rights reserved
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kati
+
+var (
+ LogFlag bool
+ StatsFlag bool
+ PeriodicStatsFlag bool
+ EvalStatsFlag bool
+
+ DryRunFlag bool
+
+ UseFindCache bool
+ UseWildcardCache bool
+ UseShellBuiltins bool
+
+ IgnoreOptionalInclude string
+)
diff --git a/func.cc b/func.cc
index c8127f7..b46e50c 100644
--- a/func.cc
+++ b/func.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "func.h"
#include <glob.h>
diff --git a/func.go b/func.go
index 364545b..b9f3fd9 100644
--- a/func.go
+++ b/func.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -474,7 +474,7 @@ func (f *funcWildcard) Eval(w io.Writer, ev *Evaluator) {
abuf := newBuf()
f.args[1].Eval(abuf, ev)
te := traceEvent.begin("wildcard", tmpval(abuf.Bytes()), traceEventMain)
- if ev.avoidIO && !useWildcardCache {
+ if ev.avoidIO && !UseWildcardCache {
ev.hasIO = true
io.WriteString(w, "$(/bin/ls -d ")
w.Write(abuf.Bytes())
@@ -774,7 +774,7 @@ func (f *funcShell) Eval(w io.Writer, ev *Evaluator) {
shellVar := ev.LookupVar("SHELL")
// TODO: Should be Eval, not String.
cmdline := []string{shellVar.String(), "-c", arg}
- if katiLogFlag {
+ if LogFlag {
Logf("shell %q", cmdline)
}
cmd := exec.Cmd{
@@ -796,7 +796,7 @@ func (f *funcShell) Compact() Value {
if len(f.args)-1 < 1 {
return f
}
- if !useFindCache && !useShellBuiltins {
+ if !UseFindCache && !UseShellBuiltins {
return f
}
@@ -807,7 +807,7 @@ func (f *funcShell) Compact() Value {
default:
expr = Expr{v}
}
- if useShellBuiltins {
+ if UseShellBuiltins {
// hack for android
for _, sb := range shBuiltins {
if v, ok := matchExpr(expr, sb.pattern); ok {
@@ -831,7 +831,7 @@ func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
varname := fargs[0]
variable := string(varname)
te := traceEvent.begin("call", literal(variable), traceEventMain)
- if katiLogFlag {
+ if LogFlag {
Logf("call %q variable %q", f.args[1], variable)
}
v := ev.LookupVar(variable)
@@ -846,7 +846,7 @@ func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
for i, arg := range fargs[1:] {
// f.args[2]=>args[1] will be $1.
args = append(args, tmpval(arg))
- if katiLogFlag {
+ if LogFlag {
Logf("call $%d: %q=>%q", i+1, arg, fargs[i+1])
}
}
@@ -854,13 +854,13 @@ func (f *funcCall) Eval(w io.Writer, ev *Evaluator) {
ev.paramVars = args
var buf bytes.Buffer
- if katiLogFlag {
+ if LogFlag {
w = io.MultiWriter(w, &buf)
}
v.Eval(w, ev)
ev.paramVars = oldParams
traceEvent.end(te)
- if katiLogFlag {
+ if LogFlag {
Logf("call %q variable %q return %q", f.args[1], variable, buf.Bytes())
}
freeBuf(abuf)
@@ -1040,7 +1040,7 @@ func (f *funcEvalAssign) Eval(w io.Writer, ev *Evaluator) {
}
rvalue = &RecursiveVar{expr: tmpval(rhs), origin: "file"}
}
- if katiLogFlag {
+ if LogFlag {
Logf("Eval ASSIGN: %s=%q (flavor:%q)", f.lhs, rvalue, rvalue.Flavor())
}
ev.outVars.Assign(f.lhs, rvalue)
diff --git a/func_test.go b/func_test.go
index 6758a9b..58d7570 100644
--- a/func_test.go
+++ b/func_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -28,7 +28,7 @@ func BenchmarkFuncStrip(b *testing.B) {
},
},
}
- ev := newEvaluator(make(map[string]Var))
+ ev := NewEvaluator(make(map[string]Var))
var buf bytes.Buffer
b.ReportAllocs()
b.ResetTimer()
@@ -47,7 +47,7 @@ func BenchmarkFuncSort(b *testing.B) {
},
},
}
- ev := newEvaluator(make(map[string]Var))
+ ev := NewEvaluator(make(map[string]Var))
var buf bytes.Buffer
b.ReportAllocs()
b.ResetTimer()
@@ -68,7 +68,7 @@ func BenchmarkFuncPatsubst(b *testing.B) {
},
},
}
- ev := newEvaluator(make(map[string]Var))
+ ev := NewEvaluator(make(map[string]Var))
var buf bytes.Buffer
b.ReportAllocs()
b.ResetTimer()
diff --git a/ioutil.go b/ioutil.go
index ef27e01..de8f88f 100644
--- a/ioutil.go
+++ b/ioutil.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import "io"
diff --git a/log.go b/log.go
index b00e2bb..514ff9b 100644
--- a/log.go
+++ b/log.go
@@ -12,13 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
"fmt"
"os"
- "runtime/pprof"
"sync"
)
@@ -35,14 +34,14 @@ func LogAlways(f string, a ...interface{}) {
}
func LogStats(f string, a ...interface{}) {
- if !katiLogFlag && !katiStatsFlag {
+ if !LogFlag && !StatsFlag {
return
}
LogAlways(f, a...)
}
func Logf(f string, a ...interface{}) {
- if !katiLogFlag {
+ if !LogFlag {
return
}
LogAlways(f, a...)
@@ -58,19 +57,22 @@ func WarnNoPrefix(filename string, lineno int, f string, a ...interface{}) {
fmt.Printf(f, a...)
}
+var atErrors []func()
+
+func AtError(f func()) {
+ atErrors = append(atErrors, f)
+}
+
func Error(filename string, lineno int, f string, a ...interface{}) {
f = fmt.Sprintf("%s:%d: %s", filename, lineno, f)
- maybeWriteHeapProfile()
ErrorNoLocation(f, a...)
}
func ErrorNoLocation(f string, a ...interface{}) {
f = fmt.Sprintf("%s\n", f)
fmt.Printf(f, a...)
- if cpuprofile != "" {
- pprof.StopCPUProfile()
+ for i := len(atErrors) - 1; i >= 0; i-- {
+ atErrors[i]()
}
- maybeWriteHeapProfile()
- dumpStats()
os.Exit(2)
}
diff --git a/main.cc b/main.cc
index f8c05c7..2650675 100644
--- a/main.cc
+++ b/main.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include <limits.h>
#include <stdio.h>
#include <string.h>
diff --git a/main.go b/main.go
deleted file mode 100644
index 15ad142..0000000
--- a/main.go
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package main
-
-import (
- "bytes"
- "crypto/sha1"
- "flag"
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "runtime"
- "runtime/pprof"
- "strings"
- "text/template"
- "time"
-)
-
-const shellDateTimeformat = time.RFC3339
-
-var (
- katiLogFlag bool
- makefileFlag string
- dryRunFlag bool
- jobsFlag int
- cpuprofile string
- heapprofile string
- memstats string
- traceEventFile string
- katiStatsFlag bool
- katiPeriodicStatsFlag bool
- katiEvalStatsFlag bool
- loadJSON string
- saveJSON string
- loadGOB string
- saveGOB string
- syntaxCheckOnlyFlag bool
- queryFlag string
- eagerCmdEvalFlag bool
- useParaFlag bool
- useCache bool
- useFindCache bool
- findCachePrunes string
- findCacheLeafNames string
- useWildcardCache bool
- useShellBuiltins bool
- shellDate string
- generateNinja bool
- ignoreOptionalInclude string
- gomaDir string
-
- katiDir string
-)
-
-type DepGraph struct {
- nodes []*DepNode
- vars Vars
- readMks []*ReadMakefile
- exports map[string]bool
- isCached bool
-}
-
-func parseFlags() {
- // TODO: Make this default and replace this by -d flag.
- flag.BoolVar(&katiLogFlag, "kati_log", false, "Verbose kati specific log")
- flag.StringVar(&makefileFlag, "f", "", "Use it as a makefile")
-
- flag.BoolVar(&dryRunFlag, "n", false, "Only print the commands that would be executed")
-
- flag.IntVar(&jobsFlag, "j", 1, "Allow N jobs at once.")
-
- flag.StringVar(&loadGOB, "load", "", "")
- flag.StringVar(&saveGOB, "save", "", "")
- flag.StringVar(&loadJSON, "load_json", "", "")
- flag.StringVar(&saveJSON, "save_json", "", "")
-
- flag.StringVar(&cpuprofile, "kati_cpuprofile", "", "write cpu profile to `file`")
- flag.StringVar(&heapprofile, "kati_heapprofile", "", "write heap profile to `file`")
- flag.StringVar(&memstats, "kati_memstats", "", "Show memstats with given templates")
- flag.StringVar(&traceEventFile, "kati_trace_event", "", "write trace event to `file`")
- flag.BoolVar(&katiStatsFlag, "kati_stats", false, "Show a bunch of statistics")
- flag.BoolVar(&katiPeriodicStatsFlag, "kati_periodic_stats", false, "Show a bunch of periodic statistics")
- flag.BoolVar(&katiEvalStatsFlag, "kati_eval_stats", false, "Show eval statistics")
- flag.BoolVar(&eagerCmdEvalFlag, "eager_cmd_eval", false, "Eval commands first.")
- flag.BoolVar(&useParaFlag, "use_para", false, "Use para.")
- flag.BoolVar(&syntaxCheckOnlyFlag, "c", false, "Syntax check only.")
- flag.StringVar(&queryFlag, "query", "", "Show the target info")
- // TODO: Make this default.
- flag.BoolVar(&useCache, "use_cache", false, "Use cache.")
- flag.BoolVar(&useFindCache, "use_find_cache", false, "Use find cache.")
- flag.StringVar(&findCachePrunes, "find_cache_prunes", "",
- "space separated prune directories for find cache.")
- flag.StringVar(&findCacheLeafNames, "find_cache_leaf_names", "",
- "space separated leaf names for find cache.")
- flag.BoolVar(&useWildcardCache, "use_wildcard_cache", true, "Use wildcard cache.")
- flag.BoolVar(&useShellBuiltins, "use_shell_builtins", true, "Use shell builtins")
- flag.StringVar(&shellDate, "shell_date", "", "specify $(shell date) time as "+shellDateTimeformat)
- flag.BoolVar(&generateNinja, "ninja", false, "Generate build.ninja.")
- flag.StringVar(&ignoreOptionalInclude, "ignore_optional_include", "", "If specified, skip reading -include directives start with the specified path.")
- flag.StringVar(&gomaDir, "goma_dir", "", "If specified, use goma to build C/C++ files.")
- flag.Parse()
-}
-
-func parseCommandLine() ([]string, []string) {
- var vars []string
- var targets []string
- for _, arg := range flag.Args() {
- if strings.IndexByte(arg, '=') >= 0 {
- vars = append(vars, arg)
- continue
- }
- targets = append(targets, arg)
- }
- return vars, targets
-}
-
-func getBootstrapMakefile(targets []string) Makefile {
- bootstrap := `
-CC:=cc
-CXX:=g++
-AR:=ar
-MAKE:=kati
-# Pretend to be GNU make 3.81, for compatibility.
-MAKE_VERSION:=3.81
-SHELL:=/bin/sh
-# TODO: Add more builtin vars.
-
-# http://www.gnu.org/software/make/manual/make.html#Catalogue-of-Rules
-# The document above is actually not correct. See default.c:
-# http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=4.1
-.c.o:
- $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<
-.cc.o:
- $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<
-# TODO: Add more builtin rules.
-`
- bootstrap += fmt.Sprintf("MAKECMDGOALS:=%s\n", strings.Join(targets, " "))
- cwd, err := filepath.Abs(".")
- if err != nil {
- panic(err)
- }
- bootstrap += fmt.Sprintf("CURDIR:=%s\n", cwd)
- mk, err := ParseMakefileString(bootstrap, BootstrapMakefile, 0)
- if err != nil {
- panic(err)
- }
- return mk
-}
-
-func maybeWriteHeapProfile() {
- if heapprofile != "" {
- f, err := os.Create(heapprofile)
- if err != nil {
- panic(err)
- }
- pprof.WriteHeapProfile(f)
- }
-}
-
-func getDepGraph(clvars []string, targets []string) *DepGraph {
- startTime := time.Now()
-
- if loadGOB != "" {
- g := LoadDepGraph(loadGOB)
- LogStats("deserialize time: %q", time.Since(startTime))
- return g
- }
- if loadJSON != "" {
- g := LoadDepGraphFromJSON(loadJSON)
- LogStats("deserialize time: %q", time.Since(startTime))
- return g
- }
-
- makefile := makefileFlag
- if makefile == "" {
- makefile = GetDefaultMakefile()
- }
-
- if useCache {
- g := LoadDepGraphCache(makefile, targets)
- if g != nil {
- return g
- }
- }
-
- bmk := getBootstrapMakefile(targets)
-
- content, err := ioutil.ReadFile(makefile)
- if err != nil {
- panic(err)
- }
- mk, err := ParseMakefile(content, makefile)
- if err != nil {
- panic(err)
- }
-
- for _, stmt := range mk.stmts {
- stmt.show()
- }
-
- mk.stmts = append(bmk.stmts, mk.stmts...)
-
- vars := make(Vars)
- for _, env := range os.Environ() {
- kv := strings.SplitN(env, "=", 2)
- Logf("envvar %q", kv)
- if len(kv) < 2 {
- panic(fmt.Sprintf("A weird environ variable %q", kv))
- }
- vars.Assign(kv[0], &RecursiveVar{
- expr: literal(kv[1]),
- origin: "environment",
- })
- }
- vars.Assign("MAKEFILE_LIST", &SimpleVar{value: "", origin: "file"})
- for _, v := range clvars {
- kv := strings.SplitN(v, "=", 2)
- Logf("cmdlinevar %q", kv)
- if len(kv) < 2 {
- panic(fmt.Sprintf("unexpected command line var %q", kv))
- }
- vars.Assign(kv[0], &RecursiveVar{
- expr: literal(kv[1]),
- origin: "command line",
- })
- }
-
- er, err := Eval(mk, vars)
- if err != nil {
- panic(err)
- }
-
- vars.Merge(er.vars)
-
- LogStats("eval time: %q", time.Since(startTime))
- LogStats("shell func time: %q %d", shellStats.duration, shellStats.count)
-
- startTime = time.Now()
- db := NewDepBuilder(er, vars)
- LogStats("dep build prepare time: %q", time.Since(startTime))
-
- startTime = time.Now()
- nodes, err2 := db.Eval(targets)
- if err2 != nil {
- panic(err2)
- }
- LogStats("dep build time: %q", time.Since(startTime))
- var readMks []*ReadMakefile
- // Always put the root Makefile as the first element.
- readMks = append(readMks, &ReadMakefile{
- Filename: makefile,
- Hash: sha1.Sum(content),
- State: FileExists,
- })
- readMks = append(readMks, er.readMks...)
- return &DepGraph{
- nodes: nodes,
- vars: vars,
- readMks: readMks,
- exports: er.exports,
- }
-}
-
-func findKatiDir() {
- switch runtime.GOOS {
- case "linux":
- kati, err := os.Readlink("/proc/self/exe")
- if err != nil {
- panic(err)
- }
- katiDir = filepath.Dir(kati)
- default:
- panic(fmt.Sprintf("unknown OS: %s", runtime.GOOS))
- }
-}
-
-func main() {
- runtime.GOMAXPROCS(runtime.NumCPU())
- findKatiDir()
- parseFlags()
- if cpuprofile != "" {
- f, err := os.Create(cpuprofile)
- if err != nil {
- panic(err)
- }
- pprof.StartCPUProfile(f)
- defer pprof.StopCPUProfile()
- }
- defer maybeWriteHeapProfile()
- defer dumpStats()
- if memstats != "" {
- t := template.Must(template.New("memstats").Parse(memstats))
- var ms runtime.MemStats
- runtime.ReadMemStats(&ms)
- var buf bytes.Buffer
- err := t.Execute(&buf, ms)
- fmt.Println(buf.String())
- if err != nil {
- panic(err)
- }
- defer func() {
- var ms runtime.MemStats
- runtime.ReadMemStats(&ms)
- var buf bytes.Buffer
- t.Execute(&buf, ms)
- fmt.Println(buf.String())
- }()
- }
- if traceEventFile != "" {
- f, err := os.Create(traceEventFile)
- if err != nil {
- panic(err)
- }
- traceEvent.start(f)
- defer traceEvent.stop()
- }
-
- if shellDate != "" {
- if shellDate == "ref" {
- shellDate = shellDateTimeformat[:20] // until Z, drop 07:00
- }
- t, err := time.Parse(shellDateTimeformat, shellDate)
- if err != nil {
- panic(err)
- }
- shellDateTimestamp = t
- }
-
- if findCacheLeafNames != "" {
- androidDefaultLeafNames = strings.Fields(findCacheLeafNames)
- }
- if findCachePrunes != "" {
- useFindCache = true
- androidFindCache.init(strings.Fields(findCachePrunes), androidDefaultLeafNames)
- }
-
- clvars, targets := parseCommandLine()
-
- g := getDepGraph(clvars, targets)
- nodes := g.nodes
- vars := g.vars
-
- if eagerCmdEvalFlag {
- startTime := time.Now()
- EvalCommands(nodes, vars)
- LogStats("eager eval command time: %q", time.Since(startTime))
- }
-
- if saveGOB != "" {
- startTime := time.Now()
- DumpDepGraph(g, saveGOB, targets)
- LogStats("serialize time: %q", time.Since(startTime))
- }
- if saveJSON != "" {
- startTime := time.Now()
- DumpDepGraphAsJSON(g, saveJSON, targets)
- LogStats("serialize time: %q", time.Since(startTime))
- }
-
- if useCache && !g.isCached {
- startTime := time.Now()
- DumpDepGraphCache(g, targets)
- LogStats("serialize time: %q", time.Since(startTime))
- }
-
- if generateNinja {
- startTime := time.Now()
- GenerateNinja(g)
- LogStats("generate ninja time: %q", time.Since(startTime))
- return
- }
-
- if syntaxCheckOnlyFlag {
- return
- }
-
- if queryFlag != "" {
- HandleQuery(queryFlag, g)
- return
- }
-
- // TODO: Handle target specific variables.
- ev := newEvaluator(vars)
- for name, export := range g.exports {
- if export {
- os.Setenv(name, ev.EvaluateVar(name))
- } else {
- os.Unsetenv(name)
- }
- }
-
- startTime := time.Now()
- ex := NewExecutor(vars)
- err := ex.Exec(nodes)
- if err != nil {
- panic(err)
- }
- LogStats("exec time: %q", time.Since(startTime))
-}
diff --git a/ninja.go b/ninja.go
index ac9748f..174e54a 100644
--- a/ninja.go
+++ b/ninja.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -33,9 +33,10 @@ type NinjaGenerator struct {
ruleID int
done map[string]bool
ccRe *regexp.Regexp
+ gomaDir string
}
-func NewNinjaGenerator(g *DepGraph) *NinjaGenerator {
+func NewNinjaGenerator(g *DepGraph, gomaDir string) *NinjaGenerator {
ccRe, err := regexp.Compile(`^prebuilts/(gcc|clang)/.*(gcc|g\+\+|clang|clang\+\+) .* -c `)
if err != nil {
panic(err)
@@ -46,6 +47,7 @@ func NewNinjaGenerator(g *DepGraph) *NinjaGenerator {
exports: g.exports,
done: make(map[string]bool),
ccRe: ccRe,
+ gomaDir: gomaDir,
}
}
@@ -172,8 +174,8 @@ func (n *NinjaGenerator) genShellScript(runners []runner) (string, bool) {
if cmd == "" {
cmd = "true"
}
- if gomaDir != "" && n.ccRe.MatchString(cmd) {
- cmd = fmt.Sprintf("%s/gomacc %s", gomaDir, cmd)
+ if n.gomaDir != "" && n.ccRe.MatchString(cmd) {
+ cmd = fmt.Sprintf("%s/gomacc %s", n.gomaDir, cmd)
useGomacc = true
}
@@ -193,7 +195,7 @@ func (n *NinjaGenerator) genShellScript(runners []runner) (string, bool) {
buf.WriteByte(')')
}
}
- return buf.String(), gomaDir != "" && !useGomacc
+ return buf.String(), n.gomaDir != "" && !useGomacc
}
func (n *NinjaGenerator) genRuleName() string {
@@ -283,7 +285,7 @@ func (n *NinjaGenerator) generateShell() {
}
defer f.Close()
- ev := newEvaluator(n.vars)
+ ev := NewEvaluator(n.vars)
shell := ev.EvaluateVar("SHELL")
if shell == "" {
shell = "/bin/sh"
@@ -296,7 +298,7 @@ func (n *NinjaGenerator) generateShell() {
fmt.Fprintf(f, "unset %s\n", name)
}
}
- if gomaDir == "" {
+ if n.gomaDir == "" {
fmt.Fprintln(f, `exec ninja "$@"`)
} else {
fmt.Fprintln(f, `exec ninja -j300 "$@"`)
@@ -319,19 +321,19 @@ func (n *NinjaGenerator) generateNinja() {
fmt.Fprintf(n.f, "# Generated by kati\n")
fmt.Fprintf(n.f, "\n")
- if gomaDir != "" {
+ if n.gomaDir != "" {
fmt.Fprintf(n.f, "pool local_pool\n")
fmt.Fprintf(n.f, " depth = %d\n", runtime.NumCPU())
}
- n.ex = NewExecutor(n.vars)
+ n.ex = NewExecutor(n.vars, nil)
for _, node := range n.nodes {
n.emitNode(node)
}
}
-func GenerateNinja(g *DepGraph) {
- n := NewNinjaGenerator(g)
+func GenerateNinja(g *DepGraph, gomaDir string) {
+ n := NewNinjaGenerator(g, gomaDir)
n.generateShell()
n.generateNinja()
}
diff --git a/ninja_test.go b/ninja_test.go
index c757409..8b35206 100644
--- a/ninja_test.go
+++ b/ninja_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import "testing"
diff --git a/para.cc b/para.cc
index e764324..18cc4b8 100644
--- a/para.cc
+++ b/para.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/para.go b/para.go
index 9ef4a11..9948866 100644
--- a/para.go
+++ b/para.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bufio"
@@ -20,7 +20,6 @@ import (
"fmt"
"io"
"os/exec"
- "path/filepath"
)
func btoi(b bool) int {
@@ -133,9 +132,8 @@ type ParaWorker struct {
doneChan chan bool
}
-func NewParaWorker(paraChan chan *ParaResult) *ParaWorker {
- bin := filepath.Join(katiDir, "para")
- para := exec.Command(bin, fmt.Sprintf("-j%d", jobsFlag), "--kati")
+func newParaWorker(paraChan chan *ParaResult, numJobs int, paraPath string) *ParaWorker {
+ para := exec.Command(paraPath, fmt.Sprintf("-j%d", numJobs), "--kati")
stdin, err := para.StdinPipe()
if err != nil {
panic(err)
diff --git a/para_test.go b/para_test.go
index 0cae106..26f2669 100644
--- a/para_test.go
+++ b/para_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"fmt"
@@ -25,8 +25,8 @@ func TestPara(t *testing.T) {
if err != nil {
panic(err)
}
- katiDir = cwd
- jobsFlag = 4
+ ParaPath = filepath.Join(cwd, "para")
+ JobsFlag = 4
paraChan := make(chan *ParaResult)
para := NewParaWorker(paraChan)
diff --git a/parser.cc b/parser.cc
index aca28b6..3bec5be 100644
--- a/parser.cc
+++ b/parser.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "parser.h"
#include <stack>
diff --git a/parser.go b/parser.go
index 9c61207..4e7574d 100644
--- a/parser.go
+++ b/parser.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
//go:generate go run testcase/gen_testcase_parse_benchmark.go
//
@@ -684,7 +684,7 @@ func ParseMakefileFd(filename string, f *os.File) (Makefile, error) {
return parser.parse()
}
-func GetDefaultMakefile() string {
+func DefaultMakefile() string {
candidates := []string{"GNUmakefile", "makefile", "Makefile"}
for _, filename := range candidates {
if exists(filename) {
@@ -746,12 +746,12 @@ func (mc *makefileCacheT) parse(filename string) (Makefile, [sha1.Size]byte, err
Logf("parse Makefile %q", filename)
mk, hash, ok, err := makefileCache.lookup(filename)
if ok {
- if katiLogFlag {
+ if LogFlag {
Logf("makefile cache hit for %q", filename)
}
return mk, hash, err
}
- if katiLogFlag {
+ if LogFlag {
Logf("reading makefile %q", filename)
}
c, err := ioutil.ReadFile(filename)
diff --git a/pathutil.go b/pathutil.go
index 38e613f..5c5649e 100644
--- a/pathutil.go
+++ b/pathutil.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"errors"
@@ -98,7 +98,7 @@ func wildcardGlob(pat string) []string {
}
func wildcard(sw *ssvWriter, pat string) {
- if useWildcardCache {
+ if UseWildcardCache {
// TODO(ukai): make sure it didn't chdir?
wildcardCache.mu.Lock()
files, ok := wildcardCache.m[pat]
@@ -114,7 +114,7 @@ func wildcard(sw *ssvWriter, pat string) {
for _, file := range files {
sw.WriteString(file)
}
- if useWildcardCache {
+ if UseWildcardCache {
wildcardCache.mu.Lock()
wildcardCache.m[pat] = files
wildcardCache.mu.Unlock()
@@ -136,9 +136,17 @@ type androidFindCacheT struct {
}
var (
- androidFindCache androidFindCacheT
+ androidFindCache androidFindCacheT
+ androidDefaultLeafNames = []string{"CleanSpec.mk", "Android.mk"}
)
+func AndroidFindCacheInit(prunes, leafNames []string) {
+ if leafNames != nil {
+ androidDefaultLeafNames = leafNames
+ }
+ androidFindCache.init(prunes)
+}
+
func (c *androidFindCacheT) ready() bool {
if c.files != nil {
return true
@@ -159,11 +167,11 @@ func (c *androidFindCacheT) leavesReady() bool {
return c.leaves != nil
}
-func (c *androidFindCacheT) init(prunes, leaves []string) {
+func (c *androidFindCacheT) init(prunes []string) {
c.once.Do(func() {
c.filesch = make(chan []fileInfo, 1)
c.leavesch = make(chan []fileInfo, 1)
- go c.start(prunes, leaves)
+ go c.start(prunes, androidDefaultLeafNames)
})
}
diff --git a/query.go b/query.go
index 7a09ff9..e77627a 100644
--- a/query.go
+++ b/query.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import "fmt"
diff --git a/rule.cc b/rule.cc
index 0bf87bc..38a0da7 100644
--- a/rule.cc
+++ b/rule.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "rule.h"
#include "log.h"
diff --git a/rule_parser.go b/rule_parser.go
index 2f575e7..ccc207d 100644
--- a/rule_parser.go
+++ b/rule_parser.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
diff --git a/rule_parser_test.go b/rule_parser_test.go
index 5dc8f24..b1db3ec 100644
--- a/rule_parser_test.go
+++ b/rule_parser_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"reflect"
diff --git a/serialize.go b/serialize.go
index 8ed60d2..2b8c45c 100644
--- a/serialize.go
+++ b/serialize.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
@@ -290,7 +290,7 @@ func DumpDepGraphCache(g *DepGraph, roots []string) {
cacheFile := GetCacheFilename(g.readMks[0].Filename, roots)
for _, mk := range g.readMks {
// Inconsistent, do not dump this result.
- if mk.State == 2 {
+ if mk.State == FileInconsistent {
if exists(cacheFile) {
os.Remove(cacheFile)
}
@@ -551,7 +551,7 @@ func showSerializedGraphStats(g SerializableGraph) {
}
func DeserializeGraph(g SerializableGraph) *DepGraph {
- if katiLogFlag || katiStatsFlag {
+ if LogFlag || StatsFlag {
showSerializedGraphStats(g)
}
nodes := DeserializeNodes(g)
diff --git a/shellutil.go b/shellutil.go
index c73711d..93a53df 100644
--- a/shellutil.go
+++ b/shellutil.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"fmt"
@@ -21,8 +21,6 @@ import (
"time"
)
-var androidDefaultLeafNames = []string{"CleanSpec.mk", "Android.mk"}
-
var shBuiltins = []struct {
name string
pattern Expr
@@ -59,7 +57,7 @@ var shBuiltins = []struct {
if v[0] != v[1] {
return sh
}
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindFileInDir{
funcShell: sh,
dir: v[0],
@@ -78,7 +76,7 @@ var shBuiltins = []struct {
literal(` -name "*.java" -and -not -name ".*"`),
},
compact: func(sh *funcShell, v []Value) Value {
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindExtFilesUnder{
funcShell: sh,
chdir: v[0],
@@ -100,7 +98,7 @@ var shBuiltins = []struct {
literal(" -name \"*.proto\" -and -not -name \".*\""),
},
compact: func(sh *funcShell, v []Value) Value {
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindExtFilesUnder{
funcShell: sh,
chdir: v[0],
@@ -126,7 +124,7 @@ var shBuiltins = []struct {
literal(` && find . -type d -a -name ".svn" -prune -o -type f -a \! -name "*.java" -a \! -name "package.html" -a \! -name "overview.html" -a \! -name ".*.swp" -a \! -name ".DS_Store" -a \! -name "*~" -print `),
},
compact: func(sh *funcShell, v []Value) Value {
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindJavaResourceFileGroup{
funcShell: sh,
dir: Expr(v),
@@ -146,7 +144,7 @@ var shBuiltins = []struct {
if !contains(androidDefaultLeafNames, "CleanSpec.mk") {
return sh
}
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindleaves{
funcShell: sh,
prunes: []Value{
@@ -175,7 +173,7 @@ var shBuiltins = []struct {
if !contains(androidDefaultLeafNames, "Android.mk") {
return sh
}
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindleaves{
funcShell: sh,
prunes: []Value{
@@ -205,7 +203,7 @@ var shBuiltins = []struct {
if !contains(androidDefaultLeafNames, "Android.mk") {
return sh
}
- androidFindCache.init(nil, androidDefaultLeafNames)
+ androidFindCache.init(nil)
return &funcShellAndroidFindleaves{
funcShell: sh,
prunes: []Value{
@@ -408,7 +406,7 @@ func (f *funcShellAndroidFindleaves) Eval(w io.Writer, ev *Evaluator) {
}
var (
- shellDateTimestamp time.Time
+ ShellDateTimestamp time.Time
shellDateFormatRef = map[string]string{
"%Y": "2006",
"%m": "01",
@@ -427,7 +425,7 @@ type funcShellDate struct {
}
func compactShellDate(sh *funcShell, v []Value) Value {
- if shellDateTimestamp.IsZero() {
+ if ShellDateTimestamp.IsZero() {
return sh
}
tf, ok := v[0].(literal)
@@ -445,5 +443,5 @@ func compactShellDate(sh *funcShell, v []Value) Value {
}
func (f *funcShellDate) Eval(w io.Writer, ev *Evaluator) {
- fmt.Fprint(w, shellDateTimestamp.Format(f.format))
+ fmt.Fprint(w, ShellDateTimestamp.Format(f.format))
}
diff --git a/shellutil_test.go b/shellutil_test.go
index c54e761..e4c200d 100644
--- a/shellutil_test.go
+++ b/shellutil_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"testing"
@@ -42,10 +42,10 @@ func TestRot13(t *testing.T) {
}
func TestShellDate(t *testing.T) {
- ts := shellDateTimestamp
- shellDateTimestamp = time.Now()
+ ts := ShellDateTimestamp
+ ShellDateTimestamp = time.Now()
defer func() {
- shellDateTimestamp = ts
+ ShellDateTimestamp = ts
}()
for _, tc := range []struct {
sharg literal
diff --git a/stats.go b/stats.go
index efb775c..6535869 100644
--- a/stats.go
+++ b/stats.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"fmt"
@@ -39,6 +39,14 @@ const (
var traceEvent traceEventT
+func TraceEventStart(f io.WriteCloser) {
+ traceEvent.start(f)
+}
+
+func TraceEventStop() {
+ traceEvent.stop()
+}
+
func (t *traceEventT) start(f io.WriteCloser) {
t.f = f
t.t0 = time.Now()
@@ -65,7 +73,7 @@ func (t *traceEventT) begin(name string, v Value, tid int) event {
var e event
e.tid = tid
e.t = time.Now()
- if t.f != nil || katiEvalStatsFlag {
+ if t.f != nil || EvalStatsFlag {
e.name = name
e.v = v.String()
}
@@ -123,7 +131,7 @@ var stats = &statsT{
}
func (s *statsT) add(name, v string, t time.Time) {
- if !katiEvalStatsFlag {
+ if !EvalStatsFlag {
return
}
d := time.Since(t)
@@ -139,8 +147,8 @@ func (s *statsT) add(name, v string, t time.Time) {
s.mu.Unlock()
}
-func dumpStats() {
- if !katiEvalStatsFlag {
+func DumpStats() {
+ if !EvalStatsFlag {
return
}
var sv byTotalTime
@@ -177,3 +185,15 @@ func (s *shellStatsT) add(d time.Duration) {
s.count++
s.mu.Unlock()
}
+
+func (s *shellStatsT) Duration() time.Duration {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.duration
+}
+
+func (s *shellStatsT) Count() int {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.count
+}
diff --git a/string_piece.cc b/string_piece.cc
index e5679b0..78de4ed 100644
--- a/string_piece.cc
+++ b/string_piece.cc
@@ -17,6 +17,8 @@
// found in the LICENSE file.
// Copied from strings/stringpiece.cc with modifications
+// +build ignore
+
#include <ctype.h>
#include <limits.h>
diff --git a/string_piece_test.cc b/string_piece_test.cc
index 544c0e4..85675d8 100644
--- a/string_piece_test.cc
+++ b/string_piece_test.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "string_piece.h"
#include <assert.h>
diff --git a/string_pool.cc b/string_pool.cc
index 596b024..bd6a709 100644
--- a/string_pool.cc
+++ b/string_pool.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "string_pool.h"
#include <stdlib.h>
diff --git a/stringprintf.cc b/stringprintf.cc
index 63fd00b..4ca40d2 100644
--- a/stringprintf.cc
+++ b/stringprintf.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "stringprintf.h"
#include <assert.h>
diff --git a/strutil.cc b/strutil.cc
index 21dbe3b..3c84304 100644
--- a/strutil.cc
+++ b/strutil.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "strutil.h"
#include <ctype.h>
diff --git a/strutil.go b/strutil.go
index 689537f..d3b3792 100644
--- a/strutil.go
+++ b/strutil.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
diff --git a/strutil_test.cc b/strutil_test.cc
index e8e773a..bcff29f 100644
--- a/strutil_test.cc
+++ b/strutil_test.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "strutil.h"
#include <assert.h>
diff --git a/strutil_test.go b/strutil_test.go
index 0cd77ed..362a09d 100644
--- a/strutil_test.go
+++ b/strutil_test.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"fmt"
diff --git a/symtab.go b/symtab.go
index f9f22de..f8fc1f8 100644
--- a/symtab.go
+++ b/symtab.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import "sync"
diff --git a/value.cc b/value.cc
index 79acc71..87cc736 100644
--- a/value.cc
+++ b/value.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "value.h"
#include <vector>
diff --git a/var.cc b/var.cc
index 80f47bb..9ff8bb9 100644
--- a/var.cc
+++ b/var.cc
@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build ignore
+
#include "var.h"
#include "log.h"
diff --git a/var.go b/var.go
index 7e4144e..568316d 100644
--- a/var.go
+++ b/var.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"bytes"
diff --git a/worker.go b/worker.go
index 3e61db7..fdd095a 100644
--- a/worker.go
+++ b/worker.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package main
+package kati
import (
"container/heap"
@@ -87,7 +87,7 @@ func (jq *JobQueue) Pop() interface{} {
return item
}
-func NewWorker(wm *WorkerManager) *Worker {
+func newWorker(wm *WorkerManager) *Worker {
w := &Worker{
wm: wm,
jobChan: make(chan *Job),
@@ -154,7 +154,7 @@ func newRunner(r runner, s string) runner {
}
switch s[0] {
case '@':
- if !dryRunFlag {
+ if !DryRunFlag {
r.echo = false
}
s = s[1:]
@@ -171,10 +171,10 @@ func newRunner(r runner, s string) runner {
}
func (r runner) run(output string) error {
- if r.echo || dryRunFlag {
+ if r.echo || DryRunFlag {
fmt.Printf("%s\n", r.cmd)
}
- if dryRunFlag {
+ if DryRunFlag {
return nil
}
args := []string{r.shell, "-c", r.cmd}
@@ -250,7 +250,7 @@ func (j *Job) build() {
func (wm *WorkerManager) handleJobs() {
for {
- if !useParaFlag && len(wm.freeWorkers) == 0 {
+ if wm.para == nil && len(wm.freeWorkers) == 0 {
return
}
if wm.readyQueue.Len() == 0 {
@@ -259,7 +259,7 @@ func (wm *WorkerManager) handleJobs() {
j := heap.Pop(&wm.readyQueue).(*Job)
Logf("run: %s", j.n.Output)
- if useParaFlag {
+ if wm.para != nil {
j.runners = j.createRunners()
if len(j.runners) == 0 {
wm.updateParents(j)
@@ -290,6 +290,7 @@ func (wm *WorkerManager) updateParents(j *Job) {
}
type WorkerManager struct {
+ maxJobs int
jobs []*Job
readyQueue JobQueue
jobChan chan *Job
@@ -307,8 +308,9 @@ type WorkerManager struct {
finishCnt int
}
-func NewWorkerManager() *WorkerManager {
+func NewWorkerManager(numJobs int, paraPath string) *WorkerManager {
wm := &WorkerManager{
+ maxJobs: numJobs,
jobChan: make(chan *Job),
resultChan: make(chan JobResult),
newDepChan: make(chan NewDep),
@@ -317,15 +319,15 @@ func NewWorkerManager() *WorkerManager {
busyWorkers: make(map[*Worker]bool),
}
- if useParaFlag {
+ if paraPath != "" {
wm.runnings = make(map[string]*Job)
wm.paraChan = make(chan *ParaResult)
- wm.para = NewParaWorker(wm.paraChan)
+ wm.para = newParaWorker(wm.paraChan, numJobs, paraPath)
go wm.para.Run()
} else {
wm.busyWorkers = make(map[*Worker]bool)
- for i := 0; i < jobsFlag; i++ {
- w := NewWorker(wm)
+ for i := 0; i < numJobs; i++ {
+ w := newWorker(wm)
wm.freeWorkers = append(wm.freeWorkers, w)
go w.Run()
}
@@ -393,7 +395,7 @@ func (wm *WorkerManager) Run() {
if pr.status < 0 && pr.signal < 0 {
j := wm.runnings[pr.output]
for _, r := range j.runners {
- if r.echo || dryRunFlag {
+ if r.echo || DryRunFlag {
fmt.Printf("%s\n", r.cmd)
}
}
@@ -409,18 +411,18 @@ func (wm *WorkerManager) Run() {
}
wm.handleJobs()
- if useParaFlag {
+ if wm.para != nil {
numBusy := len(wm.runnings)
- if numBusy > jobsFlag {
- numBusy = jobsFlag
+ if numBusy > wm.maxJobs {
+ numBusy = wm.maxJobs
}
- Logf("job=%d ready=%d free=%d busy=%d", len(wm.jobs)-wm.finishCnt, wm.readyQueue.Len(), jobsFlag-numBusy, numBusy)
+ Logf("job=%d ready=%d free=%d busy=%d", len(wm.jobs)-wm.finishCnt, wm.readyQueue.Len(), wm.maxJobs-numBusy, numBusy)
} else {
Logf("job=%d ready=%d free=%d busy=%d", len(wm.jobs)-wm.finishCnt, wm.readyQueue.Len(), len(wm.freeWorkers), len(wm.busyWorkers))
}
}
- if useParaFlag {
+ if wm.para != nil {
Logf("Wait for para to finish")
wm.para.Wait()
} else {