blob: 20db65a5017b6d8b68f1fbb818075ea65cf2dfe9 [file] [log] [blame]
Dan Willemsen4b7d5de2016-01-12 23:20:28 -08001// Copyright 2016 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
Colin Cross635c3b02016-05-18 15:37:25 -070015package android
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080016
17import (
18 "bytes"
19 "fmt"
Colin Cross6301c3c2021-09-28 17:40:21 -070020 "path/filepath"
21 "runtime"
Dan Willemsen6a6478d2020-07-17 19:28:53 -070022 "sort"
Colin Cross31656952018-05-24 16:11:20 -070023 "strings"
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080024
Colin Cross65494b92019-02-07 14:25:51 -080025 "github.com/google/blueprint"
Colin Crossc3d87d32020-06-04 13:25:17 -070026 "github.com/google/blueprint/pathtools"
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080027 "github.com/google/blueprint/proptools"
28)
29
Dan Albertf5415d72017-08-17 16:19:59 -070030func init() {
31 RegisterMakeVarsProvider(pctx, androidMakeVarsProvider)
32}
33
34func androidMakeVarsProvider(ctx MakeVarsContext) {
Dan Albert1a246272020-07-06 14:49:35 -070035 ctx.Strict("MIN_SUPPORTED_SDK_VERSION", ctx.Config().MinSupportedSdkVersion().String())
Dan Albertf5415d72017-08-17 16:19:59 -070036}
37
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080038///////////////////////////////////////////////////////////////////////////////
Dan Willemsen6a6478d2020-07-17 19:28:53 -070039
40// BaseMakeVarsContext contains the common functions for other packages to use
41// to declare make variables
42type BaseMakeVarsContext interface {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080043 Config() Config
Dan Willemsen3fb1fae2018-03-12 15:30:26 -070044 DeviceConfig() DeviceConfig
Colin Cross65494b92019-02-07 14:25:51 -080045 AddNinjaFileDeps(deps ...string)
Colin Cross65494b92019-02-07 14:25:51 -080046
Colin Cross65494b92019-02-07 14:25:51 -080047 Failed() bool
48
Dan Willemsen558e5172016-05-19 16:58:46 -070049 // These are equivalent to Strict and Check, but do not attempt to
50 // evaluate the values before writing them to the Makefile. They can
51 // be used when all ninja variables have already been evaluated through
52 // Eval().
53 StrictRaw(name, value string)
54 CheckRaw(name, value string)
Colin Cross8177ad22019-11-04 10:27:48 -080055
56 // GlobWithDeps returns a list of files that match the specified pattern but do not match any
57 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
58 // builder whenever a file matching the pattern as added or removed, without rerunning if a
59 // file that does not match the pattern is added to a searched directory.
60 GlobWithDeps(pattern string, excludes []string) ([]string, error)
Colin Crossc3d87d32020-06-04 13:25:17 -070061
62 // Phony creates a phony rule in Make, which will allow additional DistForGoal
63 // dependencies to be added to it. Phony can be called on the same name multiple
64 // times to add additional dependencies.
65 Phony(names string, deps ...Path)
Colin Cross3cda0d82019-09-24 13:40:07 -070066
67 // DistForGoal creates a rule to copy one or more Paths to the artifacts
68 // directory on the build server when the specified goal is built.
69 DistForGoal(goal string, paths ...Path)
70
71 // DistForGoalWithFilename creates a rule to copy a Path to the artifacts
72 // directory on the build server with the given filename when the specified
73 // goal is built.
74 DistForGoalWithFilename(goal string, path Path, filename string)
75
76 // DistForGoals creates a rule to copy one or more Paths to the artifacts
77 // directory on the build server when any of the specified goals are built.
78 DistForGoals(goals []string, paths ...Path)
79
80 // DistForGoalsWithFilename creates a rule to copy a Path to the artifacts
81 // directory on the build server with the given filename when any of the
82 // specified goals are built.
83 DistForGoalsWithFilename(goals []string, path Path, filename string)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080084}
85
Dan Willemsen6a6478d2020-07-17 19:28:53 -070086// MakeVarsContext contains the set of functions available for MakeVarsProvider
87// and SingletonMakeVarsProvider implementations.
88type MakeVarsContext interface {
89 BaseMakeVarsContext
90
91 ModuleName(module blueprint.Module) string
92 ModuleDir(module blueprint.Module) string
93 ModuleSubDir(module blueprint.Module) string
94 ModuleType(module blueprint.Module) string
Colin Cross127bb8b2020-12-16 16:46:01 -080095 ModuleProvider(module blueprint.Module, key blueprint.ProviderKey) interface{}
Dan Willemsen6a6478d2020-07-17 19:28:53 -070096 BlueprintFile(module blueprint.Module) string
97
98 ModuleErrorf(module blueprint.Module, format string, args ...interface{})
99 Errorf(format string, args ...interface{})
100
101 VisitAllModules(visit func(Module))
102 VisitAllModulesIf(pred func(Module) bool, visit func(Module))
103
104 // Verify the make variable matches the Soong version, fail the build
105 // if it does not. If the make variable is empty, just set it.
106 Strict(name, ninjaStr string)
107 // Check to see if the make variable matches the Soong version, warn if
108 // it does not. If the make variable is empty, just set it.
109 Check(name, ninjaStr string)
110
111 // These are equivalent to the above, but sort the make and soong
112 // variables before comparing them. They also show the unique entries
113 // in each list when displaying the difference, instead of the entire
114 // string.
115 StrictSorted(name, ninjaStr string)
116 CheckSorted(name, ninjaStr string)
117
118 // Evaluates a ninja string and returns the result. Used if more
119 // complicated modification needs to happen before giving it to Make.
120 Eval(ninjaStr string) (string, error)
121}
122
123// MakeVarsModuleContext contains the set of functions available for modules
124// implementing the ModuleMakeVarsProvider interface.
125type MakeVarsModuleContext interface {
126 BaseMakeVarsContext
127}
128
Colin Cross65494b92019-02-07 14:25:51 -0800129var _ PathContext = MakeVarsContext(nil)
130
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800131type MakeVarsProvider func(ctx MakeVarsContext)
132
Colin Cross0875c522017-11-28 17:34:01 -0800133func RegisterMakeVarsProvider(pctx PackageContext, provider MakeVarsProvider) {
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400134 makeVarsInitProviders = append(makeVarsInitProviders, makeVarsProvider{pctx, provider})
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800135}
136
Colin Crossed023ec2019-02-19 12:38:45 -0800137// SingletonMakeVarsProvider is a Singleton with an extra method to provide extra values to be exported to Make.
138type SingletonMakeVarsProvider interface {
Colin Crossed023ec2019-02-19 12:38:45 -0800139 // MakeVars uses a MakeVarsContext to provide extra values to be exported to Make.
140 MakeVars(ctx MakeVarsContext)
141}
142
Colin Cross06fa5882020-10-29 18:21:38 -0700143var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
144
145// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
146// the list of MakeVarsProviders to run.
147func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
148 // Singletons are registered on the Context and may be different between different Contexts,
149 // for example when running multiple tests. Store the SingletonMakeVarsProviders in the
150 // Config so they are attached to the Context.
151 singletonMakeVarsProviders := config.Once(singletonMakeVarsProvidersKey, func() interface{} {
152 return &[]makeVarsProvider{}
153 }).(*[]makeVarsProvider)
154
155 *singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
156 makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
Colin Crossed023ec2019-02-19 12:38:45 -0800157}
158
Colin Cross06fa5882020-10-29 18:21:38 -0700159// singletonMakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
160func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
Colin Crossed023ec2019-02-19 12:38:45 -0800161 return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
162}
163
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700164// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make.
165type ModuleMakeVarsProvider interface {
166 Module
167
168 // MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make.
169 MakeVars(ctx MakeVarsModuleContext)
170}
171
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800172///////////////////////////////////////////////////////////////////////////////
173
Colin Cross0875c522017-11-28 17:34:01 -0800174func makeVarsSingletonFunc() Singleton {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800175 return &makeVarsSingleton{}
176}
177
178type makeVarsSingleton struct{}
179
180type makeVarsProvider struct {
Colin Cross0875c522017-11-28 17:34:01 -0800181 pctx PackageContext
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800182 call MakeVarsProvider
183}
184
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400185// Collection of makevars providers that are registered in init() methods.
186var makeVarsInitProviders []makeVarsProvider
187
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800188type makeVarsContext struct {
Colin Cross65494b92019-02-07 14:25:51 -0800189 SingletonContext
Colin Crossc3d87d32020-06-04 13:25:17 -0700190 config Config
191 pctx PackageContext
192 vars []makeVarsVariable
193 phonies []phony
Colin Cross3cda0d82019-09-24 13:40:07 -0700194 dists []dist
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800195}
196
197var _ MakeVarsContext = &makeVarsContext{}
198
199type makeVarsVariable struct {
200 name string
201 value string
202 sort bool
203 strict bool
204}
205
Colin Crossc3d87d32020-06-04 13:25:17 -0700206type phony struct {
207 name string
208 deps []string
209}
210
Colin Cross3cda0d82019-09-24 13:40:07 -0700211type dist struct {
212 goals []string
213 paths []string
214}
215
Colin Cross0875c522017-11-28 17:34:01 -0800216func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
Jingwen Chencda22c92020-11-23 00:22:30 -0500217 if !ctx.Config().KatiEnabled() {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800218 return
219 }
220
Colin Cross988414c2020-01-11 01:11:46 +0000221 outFile := absolutePath(PathForOutput(ctx,
222 "make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800223
Colin Crossc3d87d32020-06-04 13:25:17 -0700224 lateOutFile := absolutePath(PathForOutput(ctx,
225 "late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
226
Colin Cross6301c3c2021-09-28 17:40:21 -0700227 installsFile := absolutePath(PathForOutput(ctx,
228 "installs"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
229
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800230 if ctx.Failed() {
231 return
232 }
233
Colin Cross3cda0d82019-09-24 13:40:07 -0700234 var vars []makeVarsVariable
235 var dists []dist
Colin Crossc3d87d32020-06-04 13:25:17 -0700236 var phonies []phony
Colin Cross6301c3c2021-09-28 17:40:21 -0700237 var katiInstalls []katiInstall
238 var katiSymlinks []katiInstall
Colin Cross06fa5882020-10-29 18:21:38 -0700239
240 providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
241 providers = append(providers, *ctx.Config().Get(singletonMakeVarsProvidersKey).(*[]makeVarsProvider)...)
242
243 for _, provider := range providers {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800244 mctx := &makeVarsContext{
Colin Cross65494b92019-02-07 14:25:51 -0800245 SingletonContext: ctx,
246 pctx: provider.pctx,
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800247 }
248
249 provider.call(mctx)
250
251 vars = append(vars, mctx.vars...)
Colin Crossc3d87d32020-06-04 13:25:17 -0700252 phonies = append(phonies, mctx.phonies...)
Colin Cross3cda0d82019-09-24 13:40:07 -0700253 dists = append(dists, mctx.dists...)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800254 }
255
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700256 ctx.VisitAllModules(func(m Module) {
Jiyong Parkf78531b2020-09-09 17:14:28 +0900257 if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled() {
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700258 mctx := &makeVarsContext{
259 SingletonContext: ctx,
260 }
261
262 provider.MakeVars(mctx)
263
264 vars = append(vars, mctx.vars...)
265 phonies = append(phonies, mctx.phonies...)
266 dists = append(dists, mctx.dists...)
267 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700268
269 if m.ExportedToMake() {
270 katiInstalls = append(katiInstalls, m.base().katiInstalls...)
271 katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...)
272 }
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700273 })
274
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800275 if ctx.Failed() {
276 return
277 }
278
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700279 sort.Slice(vars, func(i, j int) bool {
280 return vars[i].name < vars[j].name
281 })
282 sort.Slice(phonies, func(i, j int) bool {
283 return phonies[i].name < phonies[j].name
284 })
285 lessArr := func(a, b []string) bool {
286 if len(a) == len(b) {
287 for i := range a {
288 if a[i] < b[i] {
289 return true
290 }
291 }
292 return false
293 }
294 return len(a) < len(b)
295 }
296 sort.Slice(dists, func(i, j int) bool {
297 return lessArr(dists[i].goals, dists[j].goals) || lessArr(dists[i].paths, dists[j].paths)
298 })
299
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800300 outBytes := s.writeVars(vars)
301
Colin Crossc3d87d32020-06-04 13:25:17 -0700302 if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800303 ctx.Errorf(err.Error())
304 }
Colin Crossc3d87d32020-06-04 13:25:17 -0700305
Colin Cross3cda0d82019-09-24 13:40:07 -0700306 lateOutBytes := s.writeLate(phonies, dists)
Colin Crossc3d87d32020-06-04 13:25:17 -0700307
308 if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
309 ctx.Errorf(err.Error())
310 }
311
Colin Cross6301c3c2021-09-28 17:40:21 -0700312 installsBytes := s.writeInstalls(katiInstalls, katiSymlinks)
313 if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
314 ctx.Errorf(err.Error())
315 }
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800316}
317
318func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
319 buf := &bytes.Buffer{}
320
Dan Willemsen59339a22018-07-22 21:18:45 -0700321 fmt.Fprint(buf, `# Autogenerated file
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800322
323# Compares SOONG_$(1) against $(1), and warns if they are not equal.
324#
325# If the original variable is empty, then just set it to the SOONG_ version.
326#
327# $(1): Name of the variable to check
328# $(2): If not-empty, sort the values before comparing
329# $(3): Extra snippet to run if it does not match
330define soong-compare-var
331ifneq ($$($(1)),)
Dan Willemsen558e5172016-05-19 16:58:46 -0700332 my_val_make := $$(strip $(if $(2),$$(sort $$($(1))),$$($(1))))
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800333 my_val_soong := $(if $(2),$$(sort $$(SOONG_$(1))),$$(SOONG_$(1)))
334 ifneq ($$(my_val_make),$$(my_val_soong))
335 $$(warning $(1) does not match between Make and Soong:)
336 $(if $(2),$$(warning Make adds: $$(filter-out $$(my_val_soong),$$(my_val_make))),$$(warning Make : $$(my_val_make)))
337 $(if $(2),$$(warning Soong adds: $$(filter-out $$(my_val_make),$$(my_val_soong))),$$(warning Soong: $$(my_val_soong)))
338 $(3)
339 endif
340 my_val_make :=
341 my_val_soong :=
342else
343 $(1) := $$(SOONG_$(1))
344endif
Dan Willemsende18f472016-09-30 10:16:38 -0700345.KATI_READONLY := $(1) SOONG_$(1)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800346endef
347
348my_check_failed := false
349
350`)
351
352 // Write all the strict checks out first so that if one of them errors,
353 // we get all of the strict errors printed, but not the non-strict
354 // warnings.
355 for _, v := range vars {
356 if !v.strict {
357 continue
358 }
359
360 sort := ""
361 if v.sort {
362 sort = "true"
363 }
364
365 fmt.Fprintf(buf, "SOONG_%s := %s\n", v.name, v.value)
366 fmt.Fprintf(buf, "$(eval $(call soong-compare-var,%s,%s,my_check_failed := true))\n\n", v.name, sort)
367 }
368
Dan Willemsen59339a22018-07-22 21:18:45 -0700369 fmt.Fprint(buf, `
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800370ifneq ($(my_check_failed),false)
371 $(error Soong variable check failed)
372endif
373my_check_failed :=
374
375
376`)
377
378 for _, v := range vars {
379 if v.strict {
380 continue
381 }
382
383 sort := ""
384 if v.sort {
385 sort = "true"
386 }
387
388 fmt.Fprintf(buf, "SOONG_%s := %s\n", v.name, v.value)
389 fmt.Fprintf(buf, "$(eval $(call soong-compare-var,%s,%s))\n\n", v.name, sort)
390 }
391
392 fmt.Fprintln(buf, "\nsoong-compare-var :=")
393
Colin Crossc3d87d32020-06-04 13:25:17 -0700394 fmt.Fprintln(buf)
395
396 return buf.Bytes()
397}
398
Colin Cross3cda0d82019-09-24 13:40:07 -0700399func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
Colin Crossc3d87d32020-06-04 13:25:17 -0700400 buf := &bytes.Buffer{}
401
402 fmt.Fprint(buf, `# Autogenerated file
403
404# Values written by Soong read after parsing all Android.mk files.
405
406
407`)
408
409 for _, phony := range phonies {
410 fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
411 fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n "))
412 }
413
Colin Cross3cda0d82019-09-24 13:40:07 -0700414 fmt.Fprintln(buf)
415
416 for _, dist := range dists {
417 fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
418 strings.Join(dist.goals, " "), strings.Join(dist.paths, " "))
419 }
420
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800421 return buf.Bytes()
422}
423
Colin Cross6301c3c2021-09-28 17:40:21 -0700424// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules
425// are exported to Make instead of written directly to the ninja file so that main.mk can add
426// the dependencies from the `required` property that are hard to resolve in Soong.
427func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []byte {
428 buf := &bytes.Buffer{}
429
430 fmt.Fprint(buf, `# Autogenerated file
431
432# Values written by Soong to generate install rules that can be amended by Kati.
433
434
435`)
436
437 preserveSymlinksFlag := "-d"
438 if runtime.GOOS == "darwin" {
439 preserveSymlinksFlag = "-R"
440 }
441
442 for _, install := range installs {
443 // Write a rule for each install request in the form:
444 // to: from [ deps ] [ | order only deps ]
445 // cp -f -d $< $@ [ && chmod +x $@ ]
446 fmt.Fprintf(buf, "%s: %s", install.to.String(), install.from.String())
447 for _, dep := range install.implicitDeps {
448 fmt.Fprintf(buf, " %s", dep.String())
449 }
450 if len(install.orderOnlyDeps) > 0 {
451 fmt.Fprintf(buf, " |")
452 }
453 for _, dep := range install.orderOnlyDeps {
454 fmt.Fprintf(buf, " %s", dep.String())
455 }
456 fmt.Fprintln(buf)
457
458 fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@", preserveSymlinksFlag)
459 if install.executable {
460 fmt.Fprintf(buf, " && chmod +x $@")
461 }
462 fmt.Fprintln(buf)
463 fmt.Fprintln(buf)
464 }
465
466 for _, symlink := range symlinks {
467 fmt.Fprintf(buf, "%s:", symlink.to.String())
468 for _, dep := range symlink.implicitDeps {
469 fmt.Fprintf(buf, " %s", dep.String())
470 }
471 if symlink.from != nil || len(symlink.orderOnlyDeps) > 0 {
472 fmt.Fprintf(buf, " |")
473 }
474 if symlink.from != nil {
475 fmt.Fprintf(buf, " %s", symlink.from.String())
476 }
477 for _, dep := range symlink.orderOnlyDeps {
478 fmt.Fprintf(buf, " %s", dep.String())
479 }
480 fmt.Fprintln(buf)
481
482 fromStr := ""
483 if symlink.from != nil {
484 rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String())
485 if err != nil {
486 panic(fmt.Errorf("failed to find relative path for symlink from %q to %q: %w",
487 symlink.from.String(), symlink.to.String(), err))
488 }
489 fromStr = rel
490 } else {
491 fromStr = symlink.absFrom
492 }
493
494 fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
495 fmt.Fprintln(buf)
496 fmt.Fprintln(buf)
497 }
498
499 return buf.Bytes()
500}
501
Dan Willemsen3fb1fae2018-03-12 15:30:26 -0700502func (c *makeVarsContext) DeviceConfig() DeviceConfig {
Colin Cross65494b92019-02-07 14:25:51 -0800503 return DeviceConfig{c.Config().deviceConfig}
Jiyong Park374510b2018-03-19 18:23:01 +0900504}
505
Colin Cross31656952018-05-24 16:11:20 -0700506var ninjaDescaper = strings.NewReplacer("$$", "$")
507
Dan Willemsen558e5172016-05-19 16:58:46 -0700508func (c *makeVarsContext) Eval(ninjaStr string) (string, error) {
Colin Cross65494b92019-02-07 14:25:51 -0800509 s, err := c.SingletonContext.Eval(c.pctx, ninjaStr)
Colin Cross31656952018-05-24 16:11:20 -0700510 if err != nil {
511 return "", err
512 }
513 // SingletonContext.Eval returns an exapnded string that is valid for a ninja file, de-escape $$ to $ for use
514 // in a Makefile
515 return ninjaDescaper.Replace(s), nil
Dan Willemsen558e5172016-05-19 16:58:46 -0700516}
517
518func (c *makeVarsContext) addVariableRaw(name, value string, strict, sort bool) {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800519 c.vars = append(c.vars, makeVarsVariable{
520 name: name,
521 value: value,
522 strict: strict,
523 sort: sort,
524 })
525}
526
Dan Willemsen558e5172016-05-19 16:58:46 -0700527func (c *makeVarsContext) addVariable(name, ninjaStr string, strict, sort bool) {
528 value, err := c.Eval(ninjaStr)
529 if err != nil {
Colin Cross65494b92019-02-07 14:25:51 -0800530 c.SingletonContext.Errorf(err.Error())
Dan Willemsen558e5172016-05-19 16:58:46 -0700531 }
532 c.addVariableRaw(name, value, strict, sort)
533}
534
Colin Crossc3d87d32020-06-04 13:25:17 -0700535func (c *makeVarsContext) addPhony(name string, deps []string) {
536 c.phonies = append(c.phonies, phony{name, deps})
537}
538
Colin Cross3cda0d82019-09-24 13:40:07 -0700539func (c *makeVarsContext) addDist(goals []string, paths []string) {
540 c.dists = append(c.dists, dist{
541 goals: goals,
542 paths: paths,
543 })
544}
545
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800546func (c *makeVarsContext) Strict(name, ninjaStr string) {
547 c.addVariable(name, ninjaStr, true, false)
548}
549func (c *makeVarsContext) StrictSorted(name, ninjaStr string) {
550 c.addVariable(name, ninjaStr, true, true)
551}
Dan Willemsen558e5172016-05-19 16:58:46 -0700552func (c *makeVarsContext) StrictRaw(name, value string) {
553 c.addVariableRaw(name, value, true, false)
554}
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800555
556func (c *makeVarsContext) Check(name, ninjaStr string) {
557 c.addVariable(name, ninjaStr, false, false)
558}
559func (c *makeVarsContext) CheckSorted(name, ninjaStr string) {
560 c.addVariable(name, ninjaStr, false, true)
561}
Dan Willemsen558e5172016-05-19 16:58:46 -0700562func (c *makeVarsContext) CheckRaw(name, value string) {
563 c.addVariableRaw(name, value, false, false)
564}
Colin Crossc3d87d32020-06-04 13:25:17 -0700565
566func (c *makeVarsContext) Phony(name string, deps ...Path) {
567 c.addPhony(name, Paths(deps).Strings())
568}
Colin Cross3cda0d82019-09-24 13:40:07 -0700569
570func (c *makeVarsContext) DistForGoal(goal string, paths ...Path) {
571 c.DistForGoals([]string{goal}, paths...)
572}
573
574func (c *makeVarsContext) DistForGoalWithFilename(goal string, path Path, filename string) {
575 c.DistForGoalsWithFilename([]string{goal}, path, filename)
576}
577
578func (c *makeVarsContext) DistForGoals(goals []string, paths ...Path) {
579 c.addDist(goals, Paths(paths).Strings())
580}
581
582func (c *makeVarsContext) DistForGoalsWithFilename(goals []string, path Path, filename string) {
583 c.addDist(goals, []string{path.String() + ":" + filename})
584}