blob: 2931d0bed478364d4dadb5a22d01ff504797195b [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))
87 VisitAllModulesIf(pred func(Module) bool, visit func(Module))
88
89 // Verify the make variable matches the Soong version, fail the build
90 // if it does not. If the make variable is empty, just set it.
91 Strict(name, ninjaStr string)
92 // Check to see if the make variable matches the Soong version, warn if
93 // it does not. If the make variable is empty, just set it.
94 Check(name, ninjaStr string)
95
96 // These are equivalent to the above, but sort the make and soong
97 // variables before comparing them. They also show the unique entries
98 // in each list when displaying the difference, instead of the entire
99 // string.
100 StrictSorted(name, ninjaStr string)
101 CheckSorted(name, ninjaStr string)
102
103 // Evaluates a ninja string and returns the result. Used if more
104 // complicated modification needs to happen before giving it to Make.
105 Eval(ninjaStr string) (string, error)
106}
107
108// MakeVarsModuleContext contains the set of functions available for modules
109// implementing the ModuleMakeVarsProvider interface.
110type MakeVarsModuleContext interface {
111 BaseMakeVarsContext
112}
113
Colin Cross65494b92019-02-07 14:25:51 -0800114var _ PathContext = MakeVarsContext(nil)
115
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800116type MakeVarsProvider func(ctx MakeVarsContext)
117
Colin Cross0875c522017-11-28 17:34:01 -0800118func RegisterMakeVarsProvider(pctx PackageContext, provider MakeVarsProvider) {
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400119 makeVarsInitProviders = append(makeVarsInitProviders, makeVarsProvider{pctx, provider})
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800120}
121
Colin Crossed023ec2019-02-19 12:38:45 -0800122// SingletonMakeVarsProvider is a Singleton with an extra method to provide extra values to be exported to Make.
123type SingletonMakeVarsProvider interface {
Colin Crossed023ec2019-02-19 12:38:45 -0800124 // MakeVars uses a MakeVarsContext to provide extra values to be exported to Make.
125 MakeVars(ctx MakeVarsContext)
126}
127
Colin Cross06fa5882020-10-29 18:21:38 -0700128var singletonMakeVarsProvidersKey = NewOnceKey("singletonMakeVarsProvidersKey")
129
Colin Cross6ac95762021-11-09 13:17:44 -0800130func getSingletonMakevarsProviders(config Config) *[]makeVarsProvider {
131 return config.Once(singletonMakeVarsProvidersKey, func() interface{} {
132 return &[]makeVarsProvider{}
133 }).(*[]makeVarsProvider)
134}
135
Colin Cross06fa5882020-10-29 18:21:38 -0700136// registerSingletonMakeVarsProvider adds a singleton that implements SingletonMakeVarsProvider to
137// the list of MakeVarsProviders to run.
138func registerSingletonMakeVarsProvider(config Config, singleton SingletonMakeVarsProvider) {
139 // Singletons are registered on the Context and may be different between different Contexts,
140 // for example when running multiple tests. Store the SingletonMakeVarsProviders in the
141 // Config so they are attached to the Context.
Colin Cross6ac95762021-11-09 13:17:44 -0800142 singletonMakeVarsProviders := getSingletonMakevarsProviders(config)
Colin Cross06fa5882020-10-29 18:21:38 -0700143
144 *singletonMakeVarsProviders = append(*singletonMakeVarsProviders,
145 makeVarsProvider{pctx, singletonMakeVarsProviderAdapter(singleton)})
Colin Crossed023ec2019-02-19 12:38:45 -0800146}
147
Colin Cross06fa5882020-10-29 18:21:38 -0700148// singletonMakeVarsProviderAdapter converts a SingletonMakeVarsProvider to a MakeVarsProvider.
149func singletonMakeVarsProviderAdapter(singleton SingletonMakeVarsProvider) MakeVarsProvider {
Colin Crossed023ec2019-02-19 12:38:45 -0800150 return func(ctx MakeVarsContext) { singleton.MakeVars(ctx) }
151}
152
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700153// ModuleMakeVarsProvider is a Module with an extra method to provide extra values to be exported to Make.
154type ModuleMakeVarsProvider interface {
155 Module
156
157 // MakeVars uses a MakeVarsModuleContext to provide extra values to be exported to Make.
158 MakeVars(ctx MakeVarsModuleContext)
159}
160
Paul Duffin8eb45732022-10-04 19:03:31 +0100161// /////////////////////////////////////////////////////////////////////////////
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800162
Colin Cross0875c522017-11-28 17:34:01 -0800163func makeVarsSingletonFunc() Singleton {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800164 return &makeVarsSingleton{}
165}
166
Colin Cross6ac95762021-11-09 13:17:44 -0800167type makeVarsSingleton struct {
Paul Duffin8eb45732022-10-04 19:03:31 +0100168 varsForTesting []makeVarsVariable
Colin Cross6ac95762021-11-09 13:17:44 -0800169 installsForTesting []byte
Cole Faustd62a4892025-02-07 16:55:11 -0800170 lateForTesting []byte
Colin Cross6ac95762021-11-09 13:17:44 -0800171}
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800172
173type makeVarsProvider struct {
Colin Cross0875c522017-11-28 17:34:01 -0800174 pctx PackageContext
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800175 call MakeVarsProvider
176}
177
Chris Parsonsf3c96ef2020-09-29 02:23:17 -0400178// Collection of makevars providers that are registered in init() methods.
179var makeVarsInitProviders []makeVarsProvider
180
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800181type makeVarsContext struct {
Colin Cross65494b92019-02-07 14:25:51 -0800182 SingletonContext
Colin Crossc3d87d32020-06-04 13:25:17 -0700183 pctx PackageContext
184 vars []makeVarsVariable
185 phonies []phony
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800186}
187
188var _ MakeVarsContext = &makeVarsContext{}
189
190type makeVarsVariable struct {
191 name string
192 value string
193 sort bool
194 strict bool
195}
196
Colin Crossc3d87d32020-06-04 13:25:17 -0700197type phony struct {
198 name string
199 deps []string
200}
201
Colin Cross3cda0d82019-09-24 13:40:07 -0700202type dist struct {
203 goals []string
Jihoon Kang593171e2025-02-05 01:54:45 +0000204 paths distCopies
Colin Cross3cda0d82019-09-24 13:40:07 -0700205}
206
Colin Cross0875c522017-11-28 17:34:01 -0800207func (s *makeVarsSingleton) GenerateBuildActions(ctx SingletonContext) {
Jingwen Chencda22c92020-11-23 00:22:30 -0500208 if !ctx.Config().KatiEnabled() {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800209 return
210 }
211
Colin Cross988414c2020-01-11 01:11:46 +0000212 outFile := absolutePath(PathForOutput(ctx,
213 "make_vars"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800214
Colin Crossc3d87d32020-06-04 13:25:17 -0700215 lateOutFile := absolutePath(PathForOutput(ctx,
216 "late"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
217
Colin Cross6301c3c2021-09-28 17:40:21 -0700218 installsFile := absolutePath(PathForOutput(ctx,
219 "installs"+proptools.String(ctx.Config().productVariables.Make_suffix)+".mk").String())
220
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800221 if ctx.Failed() {
222 return
223 }
224
Colin Cross3cda0d82019-09-24 13:40:07 -0700225 var vars []makeVarsVariable
226 var dists []dist
Colin Crossc3d87d32020-06-04 13:25:17 -0700227 var phonies []phony
Colin Cross6301c3c2021-09-28 17:40:21 -0700228 var katiInstalls []katiInstall
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800229 var katiInitRcInstalls []katiInstall
230 var katiVintfManifestInstalls []katiInstall
Colin Cross6301c3c2021-09-28 17:40:21 -0700231 var katiSymlinks []katiInstall
Colin Cross06fa5882020-10-29 18:21:38 -0700232
233 providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
Colin Cross6ac95762021-11-09 13:17:44 -0800234 providers = append(providers, *getSingletonMakevarsProviders(ctx.Config())...)
Colin Cross06fa5882020-10-29 18:21:38 -0700235
236 for _, provider := range providers {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800237 mctx := &makeVarsContext{
Colin Cross65494b92019-02-07 14:25:51 -0800238 SingletonContext: ctx,
239 pctx: provider.pctx,
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800240 }
241
242 provider.call(mctx)
243
244 vars = append(vars, mctx.vars...)
Colin Crossc3d87d32020-06-04 13:25:17 -0700245 phonies = append(phonies, mctx.phonies...)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800246 }
247
Cole Faustf2aab5e2025-02-11 13:32:51 -0800248 singletonDists := getSingletonDists(ctx.Config())
249 singletonDists.lock.Lock()
250 dists = append(dists, singletonDists.dists...)
251 singletonDists.lock.Unlock()
252
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700253 ctx.VisitAllModules(func(m Module) {
Cole Fausta963b942024-04-11 17:43:00 -0700254 if provider, ok := m.(ModuleMakeVarsProvider); ok && m.Enabled(ctx) {
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700255 mctx := &makeVarsContext{
256 SingletonContext: ctx,
257 }
258
259 provider.MakeVars(mctx)
260
261 vars = append(vars, mctx.vars...)
262 phonies = append(phonies, mctx.phonies...)
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700263 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700264
265 if m.ExportedToMake() {
Yu Liud46e5ae2024-08-15 18:46:17 +0000266 info := OtherModuleProviderOrDefault(ctx, m, InstallFilesProvider)
267 katiInstalls = append(katiInstalls, info.KatiInstalls...)
Yu Liu82a6d142024-08-27 19:02:29 +0000268 katiInitRcInstalls = append(katiInitRcInstalls, info.KatiInitRcInstalls...)
269 katiVintfManifestInstalls = append(katiVintfManifestInstalls, info.KatiVintfInstalls...)
Yu Liud46e5ae2024-08-15 18:46:17 +0000270 katiSymlinks = append(katiSymlinks, info.KatiSymlinks...)
Colin Cross6301c3c2021-09-28 17:40:21 -0700271 }
Cole Faustd62a4892025-02-07 16:55:11 -0800272
273 if distInfo, ok := OtherModuleProvider(ctx, m, DistProvider); ok {
274 dists = append(dists, distInfo.Dists...)
275 }
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700276 })
277
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800278 compareKatiInstalls := func(a, b katiInstall) int {
279 aTo, bTo := a.to.String(), b.to.String()
280 if cmpTo := cmp.Compare(aTo, bTo); cmpTo != 0 {
281 return cmpTo
282 }
283
284 aFrom, bFrom := a.from.String(), b.from.String()
285 return cmp.Compare(aFrom, bFrom)
286 }
287
288 slices.SortFunc(katiInitRcInstalls, compareKatiInstalls)
289 katiInitRcInstalls = slices.CompactFunc(katiInitRcInstalls, func(a, b katiInstall) bool {
290 return compareKatiInstalls(a, b) == 0
291 })
292 katiInstalls = append(katiInstalls, katiInitRcInstalls...)
293
294 slices.SortFunc(katiVintfManifestInstalls, compareKatiInstalls)
295 katiVintfManifestInstalls = slices.CompactFunc(katiVintfManifestInstalls, func(a, b katiInstall) bool {
296 return compareKatiInstalls(a, b) == 0
297 })
298
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800299 if ctx.Failed() {
300 return
301 }
302
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700303 sort.Slice(vars, func(i, j int) bool {
304 return vars[i].name < vars[j].name
305 })
306 sort.Slice(phonies, func(i, j int) bool {
307 return phonies[i].name < phonies[j].name
308 })
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700309 sort.Slice(dists, func(i, j int) bool {
Cole Faustfa85cca2025-02-14 11:41:14 -0800310 goals := slices.Compare(dists[i].goals, dists[j].goals)
311 if goals != 0 {
312 return goals < 0
313 }
314 return slices.Compare(dists[i].paths.Strings(), dists[j].paths.Strings()) < 0
Dan Willemsen6a6478d2020-07-17 19:28:53 -0700315 })
316
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800317 outBytes := s.writeVars(vars)
318
Colin Crossc3d87d32020-06-04 13:25:17 -0700319 if err := pathtools.WriteFileIfChanged(outFile, outBytes, 0666); err != nil {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800320 ctx.Errorf(err.Error())
321 }
Colin Crossc3d87d32020-06-04 13:25:17 -0700322
Colin Cross3cda0d82019-09-24 13:40:07 -0700323 lateOutBytes := s.writeLate(phonies, dists)
Colin Crossc3d87d32020-06-04 13:25:17 -0700324
325 if err := pathtools.WriteFileIfChanged(lateOutFile, lateOutBytes, 0666); err != nil {
326 ctx.Errorf(err.Error())
327 }
328
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800329 installsBytes := s.writeInstalls(katiInstalls, katiSymlinks, katiVintfManifestInstalls)
Colin Cross6301c3c2021-09-28 17:40:21 -0700330 if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
331 ctx.Errorf(err.Error())
332 }
Colin Cross6ac95762021-11-09 13:17:44 -0800333
Paul Duffin8eb45732022-10-04 19:03:31 +0100334 // Only save state for tests when testing.
335 if ctx.Config().RunningInsideUnitTest() {
336 s.varsForTesting = vars
337 s.installsForTesting = installsBytes
Cole Faustd62a4892025-02-07 16:55:11 -0800338 s.lateForTesting = lateOutBytes
Paul Duffin8eb45732022-10-04 19:03:31 +0100339 }
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800340}
341
342func (s *makeVarsSingleton) writeVars(vars []makeVarsVariable) []byte {
343 buf := &bytes.Buffer{}
344
Dan Willemsen59339a22018-07-22 21:18:45 -0700345 fmt.Fprint(buf, `# Autogenerated file
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800346
347# Compares SOONG_$(1) against $(1), and warns if they are not equal.
348#
349# If the original variable is empty, then just set it to the SOONG_ version.
350#
351# $(1): Name of the variable to check
352# $(2): If not-empty, sort the values before comparing
353# $(3): Extra snippet to run if it does not match
354define soong-compare-var
355ifneq ($$($(1)),)
Dan Willemsen558e5172016-05-19 16:58:46 -0700356 my_val_make := $$(strip $(if $(2),$$(sort $$($(1))),$$($(1))))
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800357 my_val_soong := $(if $(2),$$(sort $$(SOONG_$(1))),$$(SOONG_$(1)))
358 ifneq ($$(my_val_make),$$(my_val_soong))
359 $$(warning $(1) does not match between Make and Soong:)
360 $(if $(2),$$(warning Make adds: $$(filter-out $$(my_val_soong),$$(my_val_make))),$$(warning Make : $$(my_val_make)))
361 $(if $(2),$$(warning Soong adds: $$(filter-out $$(my_val_make),$$(my_val_soong))),$$(warning Soong: $$(my_val_soong)))
362 $(3)
363 endif
364 my_val_make :=
365 my_val_soong :=
366else
367 $(1) := $$(SOONG_$(1))
368endif
Dan Willemsende18f472016-09-30 10:16:38 -0700369.KATI_READONLY := $(1) SOONG_$(1)
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800370endef
371
372my_check_failed := false
373
374`)
375
376 // Write all the strict checks out first so that if one of them errors,
377 // we get all of the strict errors printed, but not the non-strict
378 // warnings.
379 for _, v := range vars {
380 if !v.strict {
381 continue
382 }
383
384 sort := ""
385 if v.sort {
386 sort = "true"
387 }
388
389 fmt.Fprintf(buf, "SOONG_%s := %s\n", v.name, v.value)
390 fmt.Fprintf(buf, "$(eval $(call soong-compare-var,%s,%s,my_check_failed := true))\n\n", v.name, sort)
391 }
392
Dan Willemsen59339a22018-07-22 21:18:45 -0700393 fmt.Fprint(buf, `
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800394ifneq ($(my_check_failed),false)
395 $(error Soong variable check failed)
396endif
397my_check_failed :=
398
399
400`)
401
402 for _, v := range vars {
403 if v.strict {
404 continue
405 }
406
407 sort := ""
408 if v.sort {
409 sort = "true"
410 }
411
412 fmt.Fprintf(buf, "SOONG_%s := %s\n", v.name, v.value)
413 fmt.Fprintf(buf, "$(eval $(call soong-compare-var,%s,%s))\n\n", v.name, sort)
414 }
415
416 fmt.Fprintln(buf, "\nsoong-compare-var :=")
417
Colin Crossc3d87d32020-06-04 13:25:17 -0700418 fmt.Fprintln(buf)
419
420 return buf.Bytes()
421}
422
Colin Cross3cda0d82019-09-24 13:40:07 -0700423func (s *makeVarsSingleton) writeLate(phonies []phony, dists []dist) []byte {
Colin Crossc3d87d32020-06-04 13:25:17 -0700424 buf := &bytes.Buffer{}
425
426 fmt.Fprint(buf, `# Autogenerated file
427
428# Values written by Soong read after parsing all Android.mk files.
429
430
431`)
432
433 for _, phony := range phonies {
434 fmt.Fprintf(buf, ".PHONY: %s\n", phony.name)
435 fmt.Fprintf(buf, "%s: %s\n", phony.name, strings.Join(phony.deps, "\\\n "))
436 }
437
Colin Cross3cda0d82019-09-24 13:40:07 -0700438 fmt.Fprintln(buf)
439
440 for _, dist := range dists {
Colin Crossb5399c82021-11-11 16:33:24 -0800441 fmt.Fprintf(buf, ".PHONY: %s\n", strings.Join(dist.goals, " "))
Colin Cross3cda0d82019-09-24 13:40:07 -0700442 fmt.Fprintf(buf, "$(call dist-for-goals,%s,%s)\n",
Jihoon Kang593171e2025-02-05 01:54:45 +0000443 strings.Join(dist.goals, " "), strings.Join(dist.paths.Strings(), " "))
Colin Cross3cda0d82019-09-24 13:40:07 -0700444 }
445
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800446 return buf.Bytes()
447}
448
Colin Cross6301c3c2021-09-28 17:40:21 -0700449// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules
450// are exported to Make instead of written directly to the ninja file so that main.mk can add
451// the dependencies from the `required` property that are hard to resolve in Soong.
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800452func (s *makeVarsSingleton) writeInstalls(installs, symlinks, katiVintfManifestInstalls []katiInstall) []byte {
Colin Cross6301c3c2021-09-28 17:40:21 -0700453 buf := &bytes.Buffer{}
454
455 fmt.Fprint(buf, `# Autogenerated file
456
457# Values written by Soong to generate install rules that can be amended by Kati.
458
Cole Faust99bec752024-05-09 11:07:20 -0700459EXTRA_INSTALL_ZIPS :=
Colin Cross6301c3c2021-09-28 17:40:21 -0700460`)
461
462 preserveSymlinksFlag := "-d"
463 if runtime.GOOS == "darwin" {
464 preserveSymlinksFlag = "-R"
465 }
466
467 for _, install := range installs {
468 // Write a rule for each install request in the form:
469 // to: from [ deps ] [ | order only deps ]
470 // cp -f -d $< $@ [ && chmod +x $@ ]
471 fmt.Fprintf(buf, "%s: %s", install.to.String(), install.from.String())
472 for _, dep := range install.implicitDeps {
473 fmt.Fprintf(buf, " %s", dep.String())
474 }
Colin Cross50ed1f92021-11-12 17:41:02 -0800475 if extraFiles := install.extraFiles; extraFiles != nil {
476 fmt.Fprintf(buf, " %s", extraFiles.zip.String())
477 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700478 if len(install.orderOnlyDeps) > 0 {
479 fmt.Fprintf(buf, " |")
480 }
481 for _, dep := range install.orderOnlyDeps {
482 fmt.Fprintf(buf, " %s", dep.String())
483 }
484 fmt.Fprintln(buf)
Alessandro Astone2b17a232022-10-25 11:44:59 +0200485 fmt.Fprintln(buf, "\t@echo \"Install: $@\"")
Colin Cross50ed1f92021-11-12 17:41:02 -0800486 fmt.Fprintf(buf, "\trm -f $@ && cp -f %s $< $@\n", preserveSymlinksFlag)
Colin Cross6301c3c2021-09-28 17:40:21 -0700487 if install.executable {
Colin Cross50ed1f92021-11-12 17:41:02 -0800488 fmt.Fprintf(buf, "\tchmod +x $@\n")
Colin Cross6301c3c2021-09-28 17:40:21 -0700489 }
Colin Cross50ed1f92021-11-12 17:41:02 -0800490 if extraFiles := install.extraFiles; extraFiles != nil {
Romain Jobredeaux1cef6292022-05-19 11:11:51 -0400491 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())
492 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 -0700493 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 -0800494 }
Cole Faust99bec752024-05-09 11:07:20 -0700495
Colin Cross6301c3c2021-09-28 17:40:21 -0700496 fmt.Fprintln(buf)
497 }
Cole Faust99bec752024-05-09 11:07:20 -0700498 fmt.Fprintf(buf, ".KATI_READONLY := EXTRA_INSTALL_ZIPS\n")
Cole Faustb23bae72024-05-15 15:44:21 -0700499 fmt.Fprintf(buf, "$(KATI_visibility_prefix EXTRA_INSTALL_ZIPS,build/make/core/Makefile)\n")
Colin Cross6301c3c2021-09-28 17:40:21 -0700500
501 for _, symlink := range symlinks {
502 fmt.Fprintf(buf, "%s:", symlink.to.String())
Colin Cross64002af2021-11-09 16:37:52 -0800503 if symlink.from != nil {
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800504 // The katiVintfManifestInstall doesn't need updating when the target is modified, but we sometimes
505 // have a dependency on a katiVintfManifestInstall to a binary instead of to the binary directly, and
506 // the mtime of the katiVintfManifestInstall must be updated when the binary is modified, so use a
Colin Cross64002af2021-11-09 16:37:52 -0800507 // normal dependency here instead of an order-only dependency.
508 fmt.Fprintf(buf, " %s", symlink.from.String())
509 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700510 for _, dep := range symlink.implicitDeps {
511 fmt.Fprintf(buf, " %s", dep.String())
512 }
Colin Cross64002af2021-11-09 16:37:52 -0800513 if len(symlink.orderOnlyDeps) > 0 {
Colin Cross6301c3c2021-09-28 17:40:21 -0700514 fmt.Fprintf(buf, " |")
515 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700516 for _, dep := range symlink.orderOnlyDeps {
517 fmt.Fprintf(buf, " %s", dep.String())
518 }
519 fmt.Fprintln(buf)
520
521 fromStr := ""
522 if symlink.from != nil {
523 rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String())
524 if err != nil {
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800525 panic(fmt.Errorf("failed to find relative path for katiVintfManifestInstall from %q to %q: %w",
Colin Cross6301c3c2021-09-28 17:40:21 -0700526 symlink.from.String(), symlink.to.String(), err))
527 }
528 fromStr = rel
529 } else {
530 fromStr = symlink.absFrom
531 }
532
Alessandro Astone2b17a232022-10-25 11:44:59 +0200533 fmt.Fprintln(buf, "\t@echo \"Symlink: $@\"")
Colin Cross6301c3c2021-09-28 17:40:21 -0700534 fmt.Fprintf(buf, "\trm -f $@ && ln -sfn %s $@", fromStr)
535 fmt.Fprintln(buf)
536 fmt.Fprintln(buf)
537 }
538
Colin Crossd9bbf4b2023-11-17 16:23:48 -0800539 for _, install := range katiVintfManifestInstalls {
540 // Write a rule for each vintf install request that calls the copy-vintf-manifest-chedk make function.
541 fmt.Fprintf(buf, "$(eval $(call copy-vintf-manifest-checked, %s, %s))\n", install.from.String(), install.to.String())
542
543 if len(install.implicitDeps) > 0 {
544 panic(fmt.Errorf("unsupported implicitDeps %q in vintf install rule %q", install.implicitDeps, install.to))
545 }
546 if len(install.orderOnlyDeps) > 0 {
547 panic(fmt.Errorf("unsupported orderOnlyDeps %q in vintf install rule %q", install.orderOnlyDeps, install.to))
548 }
549
550 fmt.Fprintln(buf)
551 }
Colin Cross6301c3c2021-09-28 17:40:21 -0700552 return buf.Bytes()
553}
554
Dan Willemsen3fb1fae2018-03-12 15:30:26 -0700555func (c *makeVarsContext) DeviceConfig() DeviceConfig {
Colin Cross65494b92019-02-07 14:25:51 -0800556 return DeviceConfig{c.Config().deviceConfig}
Jiyong Park374510b2018-03-19 18:23:01 +0900557}
558
Colin Cross31656952018-05-24 16:11:20 -0700559var ninjaDescaper = strings.NewReplacer("$$", "$")
560
Dan Willemsen558e5172016-05-19 16:58:46 -0700561func (c *makeVarsContext) Eval(ninjaStr string) (string, error) {
Colin Cross65494b92019-02-07 14:25:51 -0800562 s, err := c.SingletonContext.Eval(c.pctx, ninjaStr)
Colin Cross31656952018-05-24 16:11:20 -0700563 if err != nil {
564 return "", err
565 }
566 // SingletonContext.Eval returns an exapnded string that is valid for a ninja file, de-escape $$ to $ for use
567 // in a Makefile
568 return ninjaDescaper.Replace(s), nil
Dan Willemsen558e5172016-05-19 16:58:46 -0700569}
570
571func (c *makeVarsContext) addVariableRaw(name, value string, strict, sort bool) {
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800572 c.vars = append(c.vars, makeVarsVariable{
573 name: name,
574 value: value,
575 strict: strict,
576 sort: sort,
577 })
578}
579
Dan Willemsen558e5172016-05-19 16:58:46 -0700580func (c *makeVarsContext) addVariable(name, ninjaStr string, strict, sort bool) {
581 value, err := c.Eval(ninjaStr)
582 if err != nil {
Colin Cross65494b92019-02-07 14:25:51 -0800583 c.SingletonContext.Errorf(err.Error())
Dan Willemsen558e5172016-05-19 16:58:46 -0700584 }
585 c.addVariableRaw(name, value, strict, sort)
586}
587
Colin Crossc3d87d32020-06-04 13:25:17 -0700588func (c *makeVarsContext) addPhony(name string, deps []string) {
589 c.phonies = append(c.phonies, phony{name, deps})
590}
591
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800592func (c *makeVarsContext) Strict(name, ninjaStr string) {
593 c.addVariable(name, ninjaStr, true, false)
594}
595func (c *makeVarsContext) StrictSorted(name, ninjaStr string) {
596 c.addVariable(name, ninjaStr, true, true)
597}
Dan Willemsen558e5172016-05-19 16:58:46 -0700598func (c *makeVarsContext) StrictRaw(name, value string) {
599 c.addVariableRaw(name, value, true, false)
600}
Dan Willemsen4b7d5de2016-01-12 23:20:28 -0800601
602func (c *makeVarsContext) Check(name, ninjaStr string) {
603 c.addVariable(name, ninjaStr, false, false)
604}
605func (c *makeVarsContext) CheckSorted(name, ninjaStr string) {
606 c.addVariable(name, ninjaStr, false, true)
607}
Dan Willemsen558e5172016-05-19 16:58:46 -0700608func (c *makeVarsContext) CheckRaw(name, value string) {
609 c.addVariableRaw(name, value, false, false)
610}
Colin Crossc3d87d32020-06-04 13:25:17 -0700611
612func (c *makeVarsContext) Phony(name string, deps ...Path) {
613 c.addPhony(name, Paths(deps).Strings())
614}