blob: 692b27ec6f51e762d19116c421204a5a12459677 [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"
Colin Crossd9bbf4b2023-11-17 16:23:48 -080019 "cmp"
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080020 "fmt"
Colin Cross6301c3c2021-09-28 17:40:21 -070021 "path/filepath"
22 "runtime"
Colin Crossd9bbf4b2023-11-17 16:23:48 -080023 "slices"
Dan Willemsen6a6478d2020-07-17 19:28:53 -070024 "sort"
Colin Cross31656952018-05-24 16:11:20 -070025 "strings"
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080026
Colin Cross65494b92019-02-07 14:25:51 -080027 "github.com/google/blueprint"
Colin Crossc3d87d32020-06-04 13:25:17 -070028 "github.com/google/blueprint/pathtools"
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080029 "github.com/google/blueprint/proptools"
30)
31
Dan Albertf5415d72017-08-17 16:19:59 -070032func init() {
33 RegisterMakeVarsProvider(pctx, androidMakeVarsProvider)
34}
35
36func androidMakeVarsProvider(ctx MakeVarsContext) {
Dan Albert1a246272020-07-06 14:49:35 -070037 ctx.Strict("MIN_SUPPORTED_SDK_VERSION", ctx.Config().MinSupportedSdkVersion().String())
Dan Albertf5415d72017-08-17 16:19:59 -070038}
39
Paul Duffin8eb45732022-10-04 19:03:31 +010040// /////////////////////////////////////////////////////////////////////////////
Dan Willemsen6a6478d2020-07-17 19:28:53 -070041
42// BaseMakeVarsContext contains the common functions for other packages to use
43// to declare make variables
44type BaseMakeVarsContext interface {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080045 Config() Config
Dan Willemsen3fb1fae2018-03-12 15:30:26 -070046 DeviceConfig() DeviceConfig
Colin Cross65494b92019-02-07 14:25:51 -080047 AddNinjaFileDeps(deps ...string)
Colin Cross65494b92019-02-07 14:25:51 -080048
Colin Cross65494b92019-02-07 14:25:51 -080049 Failed() bool
50
Dan Willemsen558e5172016-05-19 16:58:46 -070051 // These are equivalent to Strict and Check, but do not attempt to
52 // evaluate the values before writing them to the Makefile. They can
53 // be used when all ninja variables have already been evaluated through
54 // Eval().
55 StrictRaw(name, value string)
56 CheckRaw(name, value string)
Colin Cross8177ad22019-11-04 10:27:48 -080057
58 // GlobWithDeps returns a list of files that match the specified pattern but do not match any
59 // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
60 // builder whenever a file matching the pattern as added or removed, without rerunning if a
61 // file that does not match the pattern is added to a searched directory.
62 GlobWithDeps(pattern string, excludes []string) ([]string, error)
Colin Crossc3d87d32020-06-04 13:25:17 -070063
64 // Phony creates a phony rule in Make, which will allow additional DistForGoal
65 // dependencies to be added to it. Phony can be called on the same name multiple
66 // times to add additional dependencies.
67 Phony(names string, deps ...Path)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -080068}
69
Dan Willemsen6a6478d2020-07-17 19:28:53 -070070// MakeVarsContext contains the set of functions available for MakeVarsProvider
71// and SingletonMakeVarsProvider implementations.
72type MakeVarsContext interface {
73 BaseMakeVarsContext
74
75 ModuleName(module blueprint.Module) string
76 ModuleDir(module blueprint.Module) string
77 ModuleSubDir(module blueprint.Module) string
78 ModuleType(module blueprint.Module) string
Yu Liu663e4502024-08-12 18:23:59 +000079 otherModuleProvider(module blueprint.Module, key blueprint.AnyProviderKey) (any, bool)
Dan Willemsen6a6478d2020-07-17 19:28:53 -070080 BlueprintFile(module blueprint.Module) string
81
82 ModuleErrorf(module blueprint.Module, format string, args ...interface{})
Cole Fausta963b942024-04-11 17:43:00 -070083 OtherModulePropertyErrorf(module Module, property, format string, args ...interface{})
Dan Willemsen6a6478d2020-07-17 19:28:53 -070084 Errorf(format string, args ...interface{})
85
86 VisitAllModules(visit func(Module))
Yu Liu2a815b62025-02-21 20:46:25 +000087 VisitAllModuleProxies(visit func(proxy ModuleProxy))
Dan Willemsen6a6478d2020-07-17 19:28:53 -070088 VisitAllModulesIf(pred func(Module) bool, visit func(Module))
89
90 // Verify the make variable matches the Soong version, fail the build
91 // if it does not. If the make variable is empty, just set it.
92 Strict(name, ninjaStr string)
93 // Check to see if the make variable matches the Soong version, warn if
94 // it does not. If the make variable is empty, just set it.
95 Check(name, ninjaStr string)
96
97 // These are equivalent to the above, but sort the make and soong
98 // variables before comparing them. They also show the unique entries
99 // in each list when displaying the difference, instead of the entire
100 // string.
101 StrictSorted(name, ninjaStr string)
102 CheckSorted(name, ninjaStr string)
103
104 // Evaluates a ninja string and returns the result. Used if more
105 // complicated modification needs to happen before giving it to Make.
106 Eval(ninjaStr string) (string, error)
107}
108
109// MakeVarsModuleContext contains the set of functions available for modules
110// implementing the ModuleMakeVarsProvider interface.
111type MakeVarsModuleContext interface {
Yu Liu2a815b62025-02-21 20:46:25 +0000112 Config() Config
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700113}
114
Colin Cross65494b92019-02-07 14:25:51 -0800115var _ PathContext = MakeVarsContext(nil)
116
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800117type MakeVarsProvider func(ctx MakeVarsContext)
118
Colin Cross0875c522017-11-28 17:34:01 -0800119func RegisterMakeVarsProvider(pctx PackageContext, provider MakeVarsProvider) {
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400120 makeVarsInitProviders = append(makeVarsInitProviders, makeVarsProvider{pctx, provider})
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800121}
122
Colin Crossed023ec2019-02-19 12:38:45 -0800123// SingletonMakeVarsProvider is a Singleton with an extra method to provide extra values to be exported to Make.
124type SingletonMakeVarsProvider interface {
Colin Crossed023ec2019-02-19 12:38:45 -0800125 // MakeVars uses a MakeVarsContext to provide extra values to be exported to Make.
126 MakeVars(ctx MakeVarsContext)
127}
128
Colin Cross06fa5882020-10-29 18:21:38 -0700129var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
130
Colin Cross6ac95762021-11-09 13:17:44 -0800131func getSingletonMakevarsProviders(config Config) *[]makeVarsProvider {
132 return config.Once(singletonMakeVarsProvidersKey, func() interface{} {
133 return &[]makeVarsProvider{}
134 }).(*[]makeVarsProvider)
135}
136
Colin Cross06fa5882020-10-29 18:21:38 -0700137// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
138// the list of MakeVarsProviders to run.
139func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
140 // Singletons are registered on the Context and may be different between different Contexts,
141 // for example when running multiple tests. Store the SingletonMakeVarsProviders in the
142 // Config so they are attached to the Context.
Colin Cross6ac95762021-11-09 13:17:44 -0800143 singletonMakeVarsProviders := getSingletonMakevarsProviders(config)
Colin Cross06fa5882020-10-29 18:21:38 -0700144
145 *singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
146 makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
Colin Crossed023ec2019-02-19 12:38:45 -0800147}
148
Colin Cross06fa5882020-10-29 18:21:38 -0700149// singletonMakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
150func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
Colin Crossed023ec2019-02-19 12:38:45 -0800151 return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
152}
153
Yu Liu2a815b62025-02-21 20:46:25 +0000154type ModuleMakeVarsValue struct {
155 // Make variable name.
156 Name string
157 // Make variable value.
158 Value string
159}
160
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700161// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make.
162type ModuleMakeVarsProvider interface {
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700163 // MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make.
Yu Liu2a815b62025-02-21 20:46:25 +0000164 MakeVars(ctx MakeVarsModuleContext) []ModuleMakeVarsValue
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700165}
166
Yu Liu2a815b62025-02-21 20:46:25 +0000167var ModuleMakeVarsInfoProvider = blueprint.NewProvider[[]ModuleMakeVarsValue]()
168
Paul Duffin8eb45732022-10-04 19:03:31 +0100169// /////////////////////////////////////////////////////////////////////////////
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800170
Colin Cross0875c522017-11-28 17:34:01 -0800171func makeVarsSingletonFunc() Singleton {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800172 return &makeVarsSingleton{}
173}
174
Colin Cross6ac95762021-11-09 13:17:44 -0800175type makeVarsSingleton struct {
Paul Duffin8eb45732022-10-04 19:03:31 +0100176 varsForTesting []makeVarsVariable
Colin Cross6ac95762021-11-09 13:17:44 -0800177 installsForTesting []byte
Cole Faustd62a4892025-02-07 16:55:11 -0800178 lateForTesting []byte
Colin Cross6ac95762021-11-09 13:17:44 -0800179}
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800180
181type makeVarsProvider struct {
Colin Cross0875c522017-11-28 17:34:01 -0800182 pctx PackageContext
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800183 call MakeVarsProvider
184}
185
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400186// Collection of makevars providers that are registered in init() methods.
187var makeVarsInitProviders []makeVarsProvider
188
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800189type makeVarsContext struct {
Colin Cross65494b92019-02-07 14:25:51 -0800190 SingletonContext
Colin Crossc3d87d32020-06-04 13:25:17 -0700191 pctx PackageContext
192 vars []makeVarsVariable
193 phonies []phony
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800194}
195
196var _ MakeVarsContext = &makeVarsContext{}
197
198type makeVarsVariable struct {
199 name string
200 value string
201 sort bool
202 strict bool
203}
204
Colin Crossc3d87d32020-06-04 13:25:17 -0700205type phony struct {
206 name string
207 deps []string
208}
209
Colin Cross3cda0d82019-09-24 13:40:07 -0700210type dist struct {
211 goals []string
Jihoon Kang593171e2025-02-05 01:54:45 +0000212 paths distCopies
Colin Cross3cda0d82019-09-24 13:40:07 -0700213}
214
Colin Cross0875c522017-11-28 17:34:01 -0800215func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
Jingwen Chencda22c92020-11-23 00:22:30 -0500216 if !ctx.Config().KatiEnabled() {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800217 return
218 }
219
Colin Cross988414c2020-01-11 01:11:46 +0000220 outFile := absolutePath(PathForOutput(ctx,
221 "make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800222
Colin Crossc3d87d32020-06-04 13:25:17 -0700223 lateOutFile := absolutePath(PathForOutput(ctx,
224 "late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
225
Colin Cross6301c3c2021-09-28 17:40:21 -0700226 installsFile := absolutePath(PathForOutput(ctx,
227 "installs"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
228
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800229 if ctx.Failed() {
230 return
231 }
232
Colin Cross3cda0d82019-09-24 13:40:07 -0700233 var vars []makeVarsVariable
234 var dists []dist
Colin Crossc3d87d32020-06-04 13:25:17 -0700235 var phonies []phony
Colin Cross6301c3c2021-09-28 17:40:21 -0700236 var katiInstalls []katiInstall
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800237 var katiInitRcInstalls []katiInstall
238 var katiVintfManifestInstalls []katiInstall
Colin Cross6301c3c2021-09-28 17:40:21 -0700239 var katiSymlinks []katiInstall
Colin Cross06fa5882020-10-29 18:21:38 -0700240
241 providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
Colin Cross6ac95762021-11-09 13:17:44 -0800242 providers = append(providers, *getSingletonMakevarsProviders(ctx.Config())...)
Colin Cross06fa5882020-10-29 18:21:38 -0700243
244 for _, provider := range providers {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800245 mctx := &makeVarsContext{
Colin Cross65494b92019-02-07 14:25:51 -0800246 SingletonContext: ctx,
247 pctx: provider.pctx,
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800248 }
249
250 provider.call(mctx)
251
252 vars = append(vars, mctx.vars...)
Colin Crossc3d87d32020-06-04 13:25:17 -0700253 phonies = append(phonies, mctx.phonies...)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800254 }
255
Cole Faustf2aab5e2025-02-11 13:32:51 -0800256 singletonDists := getSingletonDists(ctx.Config())
257 singletonDists.lock.Lock()
258 dists = append(dists, singletonDists.dists...)
259 singletonDists.lock.Unlock()
260
Yu Liu2a815b62025-02-21 20:46:25 +0000261 ctx.VisitAllModuleProxies(func(m ModuleProxy) {
262 commonInfo, _ := OtherModuleProvider(ctx, m, CommonModuleInfoKey)
263 if provider, ok := OtherModuleProvider(ctx, m, ModuleMakeVarsInfoProvider); ok &&
264 commonInfo.Enabled {
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700265 mctx := &makeVarsContext{
266 SingletonContext: ctx,
267 }
Yu Liu2a815b62025-02-21 20:46:25 +0000268 for _, val := range provider {
269 if val.Name != "" {
270 mctx.StrictRaw(val.Name, val.Value)
271 }
272 }
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700273
274 vars = append(vars, mctx.vars...)
275 phonies = append(phonies, mctx.phonies...)
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700276 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700277
Yu Liu2a815b62025-02-21 20:46:25 +0000278 if commonInfo.ExportedToMake {
Yu Liud46e5ae2024-08-15 18:46:17 +0000279 info := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider)
280 katiInstalls = append(katiInstalls, info.KatiInstalls...)
Yu Liu82a6d142024-08-27 19:02:29 +0000281 katiInitRcInstalls = append(katiInitRcInstalls, info.KatiInitRcInstalls...)
282 katiVintfManifestInstalls = append(katiVintfManifestInstalls, info.KatiVintfInstalls...)
Yu Liud46e5ae2024-08-15 18:46:17 +0000283 katiSymlinks = append(katiSymlinks, info.KatiSymlinks...)
Colin Cross6301c3c2021-09-28 17:40:21 -0700284 }
Cole Faustd62a4892025-02-07 16:55:11 -0800285
286 if distInfo, ok := OtherModuleProvider(ctx, m, DistProvider); ok {
287 dists = append(dists, distInfo.Dists...)
288 }
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700289 })
290
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800291 compareKatiInstalls := func(a, b katiInstall) int {
292 aTo, bTo := a.to.String(), b.to.String()
293 if cmpTo := cmp.Compare(aTo, bTo); cmpTo != 0 {
294 return cmpTo
295 }
296
297 aFrom, bFrom := a.from.String(), b.from.String()
298 return cmp.Compare(aFrom, bFrom)
299 }
300
301 slices.SortFunc(katiInitRcInstalls, compareKatiInstalls)
302 katiInitRcInstalls = slices.CompactFunc(katiInitRcInstalls, func(a, b katiInstall) bool {
303 return compareKatiInstalls(a, b) == 0
304 })
305 katiInstalls = append(katiInstalls, katiInitRcInstalls...)
306
307 slices.SortFunc(katiVintfManifestInstalls, compareKatiInstalls)
308 katiVintfManifestInstalls = slices.CompactFunc(katiVintfManifestInstalls, func(a, b katiInstall) bool {
309 return compareKatiInstalls(a, b) == 0
310 })
311
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800312 if ctx.Failed() {
313 return
314 }
315
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700316 sort.Slice(vars, func(i, j int) bool {
317 return vars[i].name < vars[j].name
318 })
319 sort.Slice(phonies, func(i, j int) bool {
320 return phonies[i].name < phonies[j].name
321 })
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700322 sort.Slice(dists, func(i, j int) bool {
Cole Faustfa85cca2025-02-14 11:41:14 -0800323 goals := slices.Compare(dists[i].goals, dists[j].goals)
324 if goals != 0 {
325 return goals < 0
326 }
327 return slices.Compare(dists[i].paths.Strings(), dists[j].paths.Strings()) < 0
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700328 })
329
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800330 outBytes := s.writeVars(vars)
331
Colin Crossc3d87d32020-06-04 13:25:17 -0700332 if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800333 ctx.Errorf(err.Error())
334 }
Colin Crossc3d87d32020-06-04 13:25:17 -0700335
Colin Cross3cda0d82019-09-24 13:40:07 -0700336 lateOutBytes := s.writeLate(phonies, dists)
Colin Crossc3d87d32020-06-04 13:25:17 -0700337
338 if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
339 ctx.Errorf(err.Error())
340 }
341
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800342 installsBytes := s.writeInstalls(katiInstalls, katiSymlinks, katiVintfManifestInstalls)
Colin Cross6301c3c2021-09-28 17:40:21 -0700343 if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
344 ctx.Errorf(err.Error())
345 }
Colin Cross6ac95762021-11-09 13:17:44 -0800346
Paul Duffin8eb45732022-10-04 19:03:31 +0100347 // Only save state for tests when testing.
348 if ctx.Config().RunningInsideUnitTest() {
349 s.varsForTesting = vars
350 s.installsForTesting = installsBytes
Cole Faustd62a4892025-02-07 16:55:11 -0800351 s.lateForTesting = lateOutBytes
Paul Duffin8eb45732022-10-04 19:03:31 +0100352 }
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800353}
354
355func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
356 buf := &bytes.Buffer{}
357
Dan Willemsen59339a22018-07-22 21:18:45 -0700358 fmt.Fprint(buf, `# Autogenerated file
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800359
360# Compares SOONG_$(1) against $(1), and warns if they are not equal.
361#
362# If the original variable is empty, then just set it to the SOONG_ version.
363#
364# $(1): Name of the variable to check
365# $(2): If not-empty, sort the values before comparing
366# $(3): Extra snippet to run if it does not match
367define soong-compare-var
368ifneq ($$($(1)),)
Dan Willemsen558e5172016-05-19 16:58:46 -0700369 my_val_make := $$(strip $(if $(2),$$(sort $$($(1))),$$($(1))))
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800370 my_val_soong := $(if $(2),$$(sort $$(SOONG_$(1))),$$(SOONG_$(1)))
371 ifneq ($$(my_val_make),$$(my_val_soong))
372 $$(warning $(1) does not match between Make and Soong:)
373 $(if $(2),$$(warning Make adds: $$(filter-out $$(my_val_soong),$$(my_val_make))),$$(warning Make : $$(my_val_make)))
374 $(if $(2),$$(warning Soong adds: $$(filter-out $$(my_val_make),$$(my_val_soong))),$$(warning Soong: $$(my_val_soong)))
375 $(3)
376 endif
377 my_val_make :=
378 my_val_soong :=
379else
380 $(1) := $$(SOONG_$(1))
381endif
Dan Willemsende18f472016-09-30 10:16:38 -0700382.KATI_READONLY := $(1) SOONG_$(1)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800383endef
384
385my_check_failed := false
386
387`)
388
389 // Write all the strict checks out first so that if one of them errors,
390 // we get all of the strict errors printed, but not the non-strict
391 // warnings.
392 for _, v := range vars {
393 if !v.strict {
394 continue
395 }
396
397 sort := ""
398 if v.sort {
399 sort = "true"
400 }
401
402 fmt.Fprintf(buf, "SOONG_%s := %s\n", v.name, v.value)
403 fmt.Fprintf(buf, "$(eval $(call soong-compare-var,%s,%s,my_check_failed := true))\n\n", v.name, sort)
404 }
405
Dan Willemsen59339a22018-07-22 21:18:45 -0700406 fmt.Fprint(buf, `
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800407ifneq ($(my_check_failed),false)
408 $(error Soong variable check failed)
409endif
410my_check_failed :=
411
412
413`)
414
415 for _, v := range vars {
416 if v.strict {
417 continue
418 }
419
420 sort := ""
421 if v.sort {
422 sort = "true"
423 }
424
425 fmt.Fprintf(buf, "SOONG_%s := %s\n", v.name, v.value)
426 fmt.Fprintf(buf, "$(eval $(call soong-compare-var,%s,%s))\n\n", v.name, sort)
427 }
428
429 fmt.Fprintln(buf, "\nsoong-compare-var :=")
430
Colin Crossc3d87d32020-06-04 13:25:17 -0700431 fmt.Fprintln(buf)
432
433 return buf.Bytes()
434}
435
Colin Cross3cda0d82019-09-24 13:40:07 -0700436func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
Colin Crossc3d87d32020-06-04 13:25:17 -0700437 buf := &bytes.Buffer{}
438
439 fmt.Fprint(buf, `# Autogenerated file
440
441# Values written by Soong read after parsing all Android.mk files.
442
443
444`)
445
446 for _, phony := range phonies {
447 fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
448 fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n "))
449 }
450
Colin Cross3cda0d82019-09-24 13:40:07 -0700451 fmt.Fprintln(buf)
452
453 for _, dist := range dists {
Colin Crossb5399c82021-11-11 16:33:24 -0800454 fmt.Fprintf(buf, ".PHONY: %s\n", strings.Join(dist.goals, " "))
Colin Cross3cda0d82019-09-24 13:40:07 -0700455 fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
Jihoon Kang593171e2025-02-05 01:54:45 +0000456 strings.Join(dist.goals, " "), strings.Join(dist.paths.Strings(), " "))
Colin Cross3cda0d82019-09-24 13:40:07 -0700457 }
458
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800459 return buf.Bytes()
460}
461
Colin Cross6301c3c2021-09-28 17:40:21 -0700462// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules
463// are exported to Make instead of written directly to the ninja file so that main.mk can add
464// the dependencies from the `required` property that are hard to resolve in Soong.
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800465func (s *makeVarsSingleton) writeInstalls(installs, symlinks, katiVintfManifestInstalls []katiInstall) []byte {
Colin Cross6301c3c2021-09-28 17:40:21 -0700466 buf := &bytes.Buffer{}
467
468 fmt.Fprint(buf, `# Autogenerated file
469
470# Values written by Soong to generate install rules that can be amended by Kati.
471
Cole Faust99bec752024-05-09 11:07:20 -0700472EXTRA_INSTALL_ZIPS :=
Colin Cross6301c3c2021-09-28 17:40:21 -0700473`)
474
475 preserveSymlinksFlag := "-d"
476 if runtime.GOOS == "darwin" {
477 preserveSymlinksFlag = "-R"
478 }
479
480 for _, install := range installs {
481 // Write a rule for each install request in the form:
482 // to: from [ deps ] [ | order only deps ]
483 // cp -f -d $< $@ [ && chmod +x $@ ]
484 fmt.Fprintf(buf, "%s: %s", install.to.String(), install.from.String())
485 for _, dep := range install.implicitDeps {
486 fmt.Fprintf(buf, " %s", dep.String())
487 }
Colin Cross50ed1f92021-11-12 17:41:02 -0800488 if extraFiles := install.extraFiles; extraFiles != nil {
489 fmt.Fprintf(buf, " %s", extraFiles.zip.String())
490 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700491 if len(install.orderOnlyDeps) > 0 {
492 fmt.Fprintf(buf, " |")
493 }
494 for _, dep := range install.orderOnlyDeps {
495 fmt.Fprintf(buf, " %s", dep.String())
496 }
497 fmt.Fprintln(buf)
Alessandro Astone2b17a232022-10-25 11:44:59 +0200498 fmt.Fprintln(buf, "\t@echo \"Install: $@\"")
Colin Cross50ed1f92021-11-12 17:41:02 -0800499 fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@\n", preserveSymlinksFlag)
Colin Cross6301c3c2021-09-28 17:40:21 -0700500 if install.executable {
Colin Cross50ed1f92021-11-12 17:41:02 -0800501 fmt.Fprintf(buf, "\tchmod +x $@\n")
Colin Cross6301c3c2021-09-28 17:40:21 -0700502 }
Colin Cross50ed1f92021-11-12 17:41:02 -0800503 if extraFiles := install.extraFiles; extraFiles != nil {
Romain Jobredeaux1cef6292022-05-19 11:11:51 -0400504 fmt.Fprintf(buf, "\t( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} ) || \\\n", extraFiles.dir.String(), extraFiles.zip.String())
505 fmt.Fprintf(buf, "\t ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )\n")
Cole Faust07c45372024-05-10 12:39:05 -0700506 fmt.Fprintf(buf, "EXTRA_INSTALL_ZIPS += %s:%s:%s\n", install.to.String(), extraFiles.dir.String(), extraFiles.zip.String())
Colin Cross50ed1f92021-11-12 17:41:02 -0800507 }
Cole Faust99bec752024-05-09 11:07:20 -0700508
Colin Cross6301c3c2021-09-28 17:40:21 -0700509 fmt.Fprintln(buf)
510 }
Cole Faust99bec752024-05-09 11:07:20 -0700511 fmt.Fprintf(buf, ".KATI_READONLY := EXTRA_INSTALL_ZIPS\n")
Cole Faustb23bae72024-05-15 15:44:21 -0700512 fmt.Fprintf(buf, "$(KATI_visibility_prefix EXTRA_INSTALL_ZIPS,build/make/core/Makefile)\n")
Colin Cross6301c3c2021-09-28 17:40:21 -0700513
514 for _, symlink := range symlinks {
515 fmt.Fprintf(buf, "%s:", symlink.to.String())
Colin Cross64002af2021-11-09 16:37:52 -0800516 if symlink.from != nil {
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800517 // The katiVintfManifestInstall doesn't need updating when the target is modified, but we sometimes
518 // have a dependency on a katiVintfManifestInstall to a binary instead of to the binary directly, and
519 // the mtime of the katiVintfManifestInstall must be updated when the binary is modified, so use a
Colin Cross64002af2021-11-09 16:37:52 -0800520 // normal dependency here instead of an order-only dependency.
521 fmt.Fprintf(buf, " %s", symlink.from.String())
522 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700523 for _, dep := range symlink.implicitDeps {
524 fmt.Fprintf(buf, " %s", dep.String())
525 }
Colin Cross64002af2021-11-09 16:37:52 -0800526 if len(symlink.orderOnlyDeps) > 0 {
Colin Cross6301c3c2021-09-28 17:40:21 -0700527 fmt.Fprintf(buf, " |")
528 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700529 for _, dep := range symlink.orderOnlyDeps {
530 fmt.Fprintf(buf, " %s", dep.String())
531 }
532 fmt.Fprintln(buf)
533
534 fromStr := ""
535 if symlink.from != nil {
536 rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String())
537 if err != nil {
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800538 panic(fmt.Errorf("failed to find relative path for katiVintfManifestInstall from %q to %q: %w",
Colin Cross6301c3c2021-09-28 17:40:21 -0700539 symlink.from.String(), symlink.to.String(), err))
540 }
541 fromStr = rel
542 } else {
543 fromStr = symlink.absFrom
544 }
545
Alessandro Astone2b17a232022-10-25 11:44:59 +0200546 fmt.Fprintln(buf, "\t@echo \"Symlink: $@\"")
Colin Cross6301c3c2021-09-28 17:40:21 -0700547 fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
548 fmt.Fprintln(buf)
549 fmt.Fprintln(buf)
550 }
551
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800552 for _, install := range katiVintfManifestInstalls {
553 // Write a rule for each vintf install request that calls the copy-vintf-manifest-chedk make function.
554 fmt.Fprintf(buf, "$(eval $(call copy-vintf-manifest-checked, %s, %s))\n", install.from.String(), install.to.String())
555
556 if len(install.implicitDeps) > 0 {
557 panic(fmt.Errorf("unsupported implicitDeps %q in vintf install rule %q", install.implicitDeps, install.to))
558 }
559 if len(install.orderOnlyDeps) > 0 {
560 panic(fmt.Errorf("unsupported orderOnlyDeps %q in vintf install rule %q", install.orderOnlyDeps, install.to))
561 }
562
563 fmt.Fprintln(buf)
564 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700565 return buf.Bytes()
566}
567
Dan Willemsen3fb1fae2018-03-12 15:30:26 -0700568func (c *makeVarsContext) DeviceConfig() DeviceConfig {
Colin Cross65494b92019-02-07 14:25:51 -0800569 return DeviceConfig{c.Config().deviceConfig}
Jiyong Park374510b2018-03-19 18:23:01 +0900570}
571
Colin Cross31656952018-05-24 16:11:20 -0700572var ninjaDescaper = strings.NewReplacer("$$", "$")
573
Dan Willemsen558e5172016-05-19 16:58:46 -0700574func (c *makeVarsContext) Eval(ninjaStr string) (string, error) {
Colin Cross65494b92019-02-07 14:25:51 -0800575 s, err := c.SingletonContext.Eval(c.pctx, ninjaStr)
Colin Cross31656952018-05-24 16:11:20 -0700576 if err != nil {
577 return "", err
578 }
579 // SingletonContext.Eval returns an exapnded string that is valid for a ninja file, de-escape $$ to $ for use
580 // in a Makefile
581 return ninjaDescaper.Replace(s), nil
Dan Willemsen558e5172016-05-19 16:58:46 -0700582}
583
584func (c *makeVarsContext) addVariableRaw(name, value string, strict, sort bool) {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800585 c.vars = append(c.vars, makeVarsVariable{
586 name: name,
587 value: value,
588 strict: strict,
589 sort: sort,
590 })
591}
592
Dan Willemsen558e5172016-05-19 16:58:46 -0700593func (c *makeVarsContext) addVariable(name, ninjaStr string, strict, sort bool) {
594 value, err := c.Eval(ninjaStr)
595 if err != nil {
Colin Cross65494b92019-02-07 14:25:51 -0800596 c.SingletonContext.Errorf(err.Error())
Dan Willemsen558e5172016-05-19 16:58:46 -0700597 }
598 c.addVariableRaw(name, value, strict, sort)
599}
600
Colin Crossc3d87d32020-06-04 13:25:17 -0700601func (c *makeVarsContext) addPhony(name string, deps []string) {
602 c.phonies = append(c.phonies, phony{name, deps})
603}
604
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800605func (c *makeVarsContext) Strict(name, ninjaStr string) {
606 c.addVariable(name, ninjaStr, true, false)
607}
608func (c *makeVarsContext) StrictSorted(name, ninjaStr string) {
609 c.addVariable(name, ninjaStr, true, true)
610}
Dan Willemsen558e5172016-05-19 16:58:46 -0700611func (c *makeVarsContext) StrictRaw(name, value string) {
612 c.addVariableRaw(name, value, true, false)
613}
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800614
615func (c *makeVarsContext) Check(name, ninjaStr string) {
616 c.addVariable(name, ninjaStr, false, false)
617}
618func (c *makeVarsContext) CheckSorted(name, ninjaStr string) {
619 c.addVariable(name, ninjaStr, false, true)
620}
Dan Willemsen558e5172016-05-19 16:58:46 -0700621func (c *makeVarsContext) CheckRaw(name, value string) {
622 c.addVariableRaw(name, value, false, false)
623}
Colin Crossc3d87d32020-06-04 13:25:17 -0700624
625func (c *makeVarsContext) Phony(name string, deps ...Path) {
626 c.addPhony(name, Paths(deps).Strings())
627}