aboutsummaryrefslogtreecommitdiffstats
path: root/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'main.go')
-rw-r--r--main.go412
1 files changed, 0 insertions, 412 deletions
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))
-}