1// Copyright 2014 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package bootstrap
16
17import (
18	"fmt"
19	"os"
20	"path/filepath"
21	"runtime"
22	"strings"
23
24	"github.com/google/blueprint"
25)
26
27func bootstrapVariable(name string, value func(BootstrapConfig) string) blueprint.Variable {
28	return pctx.VariableFunc(name, func(config interface{}) (string, error) {
29		c, ok := config.(BootstrapConfig)
30		if !ok {
31			panic(fmt.Sprintf("Bootstrap rules were passed a configuration that does not include theirs, config=%q",
32				config))
33		}
34		return value(c), nil
35	})
36}
37
38var (
39	// These variables are the only configuration needed by the bootstrap
40	// modules.
41	srcDirVariable = bootstrapVariable("srcDir", func(c BootstrapConfig) string {
42		return c.SrcDir()
43	})
44	buildDirVariable = bootstrapVariable("buildDir", func(c BootstrapConfig) string {
45		return c.BuildDir()
46	})
47	ninjaBuildDirVariable = bootstrapVariable("ninjaBuildDir", func(c BootstrapConfig) string {
48		return c.NinjaBuildDir()
49	})
50	goRootVariable = bootstrapVariable("goRoot", func(c BootstrapConfig) string {
51		goroot := runtime.GOROOT()
52		// Prefer to omit absolute paths from the ninja file
53		if cwd, err := os.Getwd(); err == nil {
54			if relpath, err := filepath.Rel(cwd, goroot); err == nil {
55				if !strings.HasPrefix(relpath, "../") {
56					goroot = relpath
57				}
58			}
59		}
60		return goroot
61	})
62	compileCmdVariable = bootstrapVariable("compileCmd", func(c BootstrapConfig) string {
63		return "$goRoot/pkg/tool/" + runtime.GOOS + "_" + runtime.GOARCH + "/compile"
64	})
65	linkCmdVariable = bootstrapVariable("linkCmd", func(c BootstrapConfig) string {
66		return "$goRoot/pkg/tool/" + runtime.GOOS + "_" + runtime.GOARCH + "/link"
67	})
68	debugFlagsVariable = bootstrapVariable("debugFlags", func(c BootstrapConfig) string {
69		if c.DebugCompilation() {
70			// -N: disable optimizations, -l: disable inlining
71			return "-N -l"
72		} else {
73			return ""
74		}
75	})
76)
77
78type BootstrapConfig interface {
79	// The top-level directory of the source tree
80	SrcDir() string
81
82	// The directory where files emitted during bootstrapping are located.
83	// Usually NinjaBuildDir() + "/soong".
84	BuildDir() string
85
86	// The output directory for the build.
87	NinjaBuildDir() string
88
89	// Whether to compile Go code in such a way that it can be debugged
90	DebugCompilation() bool
91}
92
93type ConfigRemoveAbandonedFilesUnder interface {
94	// RemoveAbandonedFilesUnder should return two slices:
95	// - a slice of path prefixes that will be cleaned of files that are no
96	//   longer active targets, but are listed in the .ninja_log.
97	// - a slice of paths that are exempt from cleaning
98	RemoveAbandonedFilesUnder(buildDir string) (under, except []string)
99}
100
101type ConfigBlueprintToolLocation interface {
102	// BlueprintToolLocation can return a path name to install blueprint tools
103	// designed for end users (bpfmt, bpmodify, and anything else using
104	// blueprint_go_binary).
105	BlueprintToolLocation() string
106}
107
108type StopBefore int
109
110const (
111	StopBeforePrepareBuildActions StopBefore = 1
112	StopBeforeWriteNinja          StopBefore = 2
113)
114
115type ConfigStopBefore interface {
116	StopBefore() StopBefore
117}
118
119type Stage int
120
121const (
122	StagePrimary Stage = iota
123	StageMain
124)
125
126type PrimaryBuilderInvocation struct {
127	Inputs  []string
128	Outputs []string
129	Args    []string
130}
131
132type Config struct {
133	stage Stage
134
135	topLevelBlueprintsFile string
136	globFile               string
137
138	runGoTests     bool
139	useValidations bool
140
141	primaryBuilderInvocations []PrimaryBuilderInvocation
142}
143