1# Build System Changes for Android.mk/Android.bp Writers
2
3## Soong genrules are now sandboxed
4
5Previously, soong genrules could access any files in the source tree, without specifying them as
6inputs. This makes them incorrect in incremental builds, and incompatible with RBE and Bazel.
7
8Now, genrules are sandboxed so they can only access their listed srcs. Modules denylisted in
9genrule/allowlists.go are exempt from this. You can also set `BUILD_BROKEN_GENRULE_SANDBOXING`
10in board config to disable this behavior.
11
12## Partitions are no longer affected by previous builds
13
14Partition builds used to include everything in their staging directories, and building an
15individual module will install it to the staging directory. Thus, previously, `m mymodule` followed
16by `m` would cause `mymodule` to be presinstalled on the device, even if it wasn't listed in
17`PRODUCT_PACKAGES`.
18
19This behavior has been changed, and now the partition images only include what they'd have if you
20did a clean build. This behavior can be disabled by setting the
21`BUILD_BROKEN_INCORRECT_PARTITION_IMAGES` environment variable or board config variable.
22
23Manually adding make rules that build to the staging directories without going through the make
24module system will not be compatible with this change. This includes many usages of
25`LOCAL_POST_INSTALL_CMD`.
26
27## Perform validation of Soong plugins
28
29Each Soong plugin will require manual work to migrate to Bazel. In order to
30minimize the manual work outside of build/soong, we are restricting plugins to
31those that exist today and those in vendor or hardware directories.
32
33If you need to extend the build system via a plugin, please reach out to the
34build team via email android-building@googlegroups.com (external) for any
35questions, or see [go/soong](http://go/soong) (internal).
36
37To omit the validation, `BUILD_BROKEN_PLUGIN_VALIDATION` expects a
38space-separated list of plugins to omit from the validation. This must be set
39within a product configuration .mk file, board config .mk file, or buildspec.mk.
40
41## Python 2 to 3 migration
42
43The path set when running builds now makes the `python` executable point to python 3,
44whereas on previous versions it pointed to python 2. If you still have python 2 scripts,
45you can change the shebang line to use `python2` explicitly. This only applies for
46scripts run directly from makefiles, or from soong genrules. This behavior can be
47temporarily overridden by setting the `BUILD_BROKEN_PYTHON_IS_PYTHON2` environment
48variable to `true`. It's only an environment variable and not a product config variable
49because product config sometimes calls python code.
50
51In addition, `python_*` soong modules no longer allow python 2. This can be temporarily
52overridden by setting the `BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES` product configuration
53variable to `true`.
54
55Python 2 is slated for complete removal in V.
56
57## Stop referencing sysprop_library directly from cc modules
58
59For the migration to Bazel, we are no longer mapping sysprop_library targets
60to their generated `cc_library` counterparts when dependning on them from a
61cc module. Instead, directly depend on the generated module by prefixing the
62module name with `lib`. For example, depending on the following module:
63
64```
65sysprop_library {
66    name: "foo",
67    srcs: ["foo.sysprop"],
68}
69```
70
71from a module named `bar` can be done like so:
72
73```
74cc_library {
75    name: "bar",
76    srcs: ["bar.cc"],
77    deps: ["libfoo"],
78}
79```
80
81Failure to do this will result in an error about a missing variant.
82
83## Gensrcs starts disallowing depfile property
84
85To migrate all gensrcs to Bazel, we are restricting the use of depfile property
86because Bazel requires specifying the dependencies directly.
87
88To fix existing uses, remove depfile and directly specify all the dependencies
89in .bp files. For example:
90
91```
92gensrcs {
93    name: "framework-cppstream-protos",
94    tools: [
95        "aprotoc",
96        "protoc-gen-cppstream",
97    ],
98    cmd: "mkdir -p $(genDir)/$(in) " +
99        "&& $(location aprotoc) " +
100        "  --plugin=$(location protoc-gen-cppstream) " +
101        "  -I . " +
102        "  $(in) ",
103    srcs: [
104        "bar.proto",
105    ],
106    output_extension: "srcjar",
107}
108```
109where `bar.proto` imports `external.proto` would become
110
111```
112gensrcs {
113    name: "framework-cppstream-protos",
114    tools: [
115        "aprotoc",
116        "protoc-gen-cpptream",
117    ],
118    tool_files: [
119        "external.proto",
120    ],
121    cmd: "mkdir -p $(genDir)/$(in) " +
122        "&& $(location aprotoc) " +
123        "  --plugin=$(location protoc-gen-cppstream) " +
124        "  $(in) ",
125    srcs: [
126        "bar.proto",
127    ],
128    output_extension: "srcjar",
129}
130```
131as in https://android-review.googlesource.com/c/platform/frameworks/base/+/2125692/.
132
133`BUILD_BROKEN_DEPFILE` can be used to allowlist usage of depfile in `gensrcs`.
134
135If `depfile` is needed for generating javastream proto, `java_library` with `proto.type`
136set `stream` is the alternative solution. Sees
137https://android-review.googlesource.com/c/platform/packages/modules/Permission/+/2118004/
138for an example.
139
140## Genrule starts disallowing directory inputs
141
142To better specify the inputs to the build, we are restricting use of directories
143as inputs to genrules.
144
145To fix existing uses, change inputs to specify the inputs and update the command
146accordingly. For example:
147
148```
149genrule: {
150    name: "foo",
151    srcs: ["bar"],
152    cmd: "cp $(location bar)/*.xml $(gendir)",
153    ...
154}
155```
156
157would become
158
159```
160genrule: {
161    name: "foo",
162    srcs: ["bar/*.xml"],
163    cmd: "cp $(in) $(gendir)",
164    ...
165}
166```
167
168`BUILD_BROKEN_INPUT_DIR_MODULES` can be used to allowlist specific directories
169with genrules that have input directories.
170
171## Dexpreopt starts enforcing `<uses-library>` checks (for Java modules)
172
173In order to construct correct class loader context for dexpreopt, build system
174needs to know about the shared library dependencies of Java modules listed in
175the `<uses-library>` tags in the manifest. Since the build system does not have
176access to the manifest contents, that information must be present in the build
177files. In simple cases Soong is able to infer it from its knowledge of Java SDK
178libraries and the `libs` property in Android.bp, but in more complex cases it is
179necessary to add the missing information in Android.bp/Android.mk manually.
180
181To specify a list of libraries for a given modules, use:
182
183* Android.bp properties: `uses_libs`, `optional_uses_libs`
184* Android.mk variables: `LOCAL_USES_LIBRARIES`, `LOCAL_OPTIONAL_USES_LIBRARIES`
185
186If a library is in `libs`, it usually should *not* be added to the above
187properties, and Soong should be able to infer the `<uses-library>` tag. But
188sometimes a library also needs additional information in its
189Android.bp/Android.mk file (e.g. when it is a `java_library` rather than a
190`java_sdk_library`, or when the library name is different from its module name,
191or when the module is defined in Android.mk rather than Android.bp). In such
192cases it is possible to tell the build system that the library provides a
193`<uses-library>` with a given name (however, this is discouraged and will be
194deprecated in the future, and it is recommended to fix the underlying problem):
195
196* Android.bp property: `provides_uses_lib`
197* Android.mk variable: `LOCAL_PROVIDES_USES_LIBRARY`
198
199It is possible to disable the check on a per-module basis. When doing that it is
200also recommended to disable dexpreopt, as disabling a failed check will result
201in incorrect class loader context recorded in the .odex file, which will cause
202class loader context mismatch and dexopt at first boot.
203
204* Android.bp property: `enforce_uses_lib`
205* Android.mk variable: `LOCAL_ENFORCE_USES_LIBRARIES`
206
207Finally, it is possible to globally disable the check:
208
209* For a given product: `PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true`
210* On the command line: `RELAX_USES_LIBRARY_CHECK=true`
211
212The environment variable overrides the product variable, so it is possible to
213disable the check for a product, but quickly re-enable it for a local build.
214
215## `LOCAL_REQUIRED_MODULES` requires listed modules to exist {#BUILD_BROKEN_MISSING_REQUIRED_MODULES}
216
217Modules listed in `LOCAL_REQUIRED_MODULES`, `LOCAL_HOST_REQUIRED_MODULES` and
218`LOCAL_TARGET_REQUIRED_MODULES` need to exist unless `ALLOW_MISSING_DEPENDENCIES`
219is set.
220
221To temporarily relax missing required modules check, use:
222
223`BUILD_BROKEN_MISSING_REQUIRED_MODULES := true`
224
225## Changes in system properties settings
226
227### Product variables
228
229System properties for each of the partition is supposed to be set via following
230product config variables.
231
232For system partition,
233
234* `PRODUCT_SYSTEM_PROPERTIES`
235* `PRODUCT_SYSTEM_DEFAULT_PROPERTIES` is highly discouraged. Will be deprecated.
236
237For vendor partition,
238
239* `PRODUCT_VENDOR_PROPERTIES`
240* `PRODUCT_PROPERTY_OVERRIDES` is highly discouraged. Will be deprecated.
241* `PRODUCT_DEFAULT_PROPERTY_OVERRIDES` is also discouraged. Will be deprecated.
242
243For odm partition,
244
245* `PRODUCT_ODM_PROPERTIES`
246
247For system_ext partition,
248
249* `PRODUCT_SYSTEM_EXT_PROPERTIES`
250
251For product partition,
252
253* `PRODUCT_PRODUCT_PROPERTIES`
254
255### Duplication is not allowed within a partition
256
257For each partition, having multiple sysprop assignments for the same name is
258prohibited. For example, the following will now trigger an error:
259
260`PRODUCT_VENDOR_PROPERTIES += foo=true foo=false`
261
262Having duplication across partitions are still allowed. So, the following is
263not an error:
264
265`PRODUCT_VENDOR_PROPERTIES += foo=true`
266`PRODUCT_SYSTEM_PROPERTIES += foo=false`
267
268In that case, the final value is determined at runtime. The precedence is
269
270* product
271* odm
272* vendor
273* system_ext
274* system
275
276So, `foo` becomes `true` because vendor has higher priority than system.
277
278To temporarily turn the build-time restriction off, use
279
280`BUILD_BROKEN_DUP_SYSPROP := true`
281
282### Optional assignments
283
284System properties can now be set as optional using the new syntax:
285
286`name ?= value`
287
288Then the system property named `name` gets the value `value` only when there
289is no other non-optional assignments having the same name. For example, the
290following is allowed and `foo` gets `true`
291
292`PRODUCT_VENDOR_PROPERTIES += foo=true foo?=false`
293
294Note that the order between the optional and the non-optional assignments
295doesn't matter. The following gives the same result as above.
296
297`PRODUCT_VENDOR_PROPERTIES += foo?=false foo=true`
298
299Optional assignments can be duplicated and in that case their order matters.
300Specifically, the last one eclipses others.
301
302`PRODUCT_VENDOR_PROPERTIES += foo?=apple foo?=banana foo?=mango`
303
304With above, `foo` becomes `mango` since its the last one.
305
306Note that this behavior is different from the previous behavior of preferring
307the first one. To go back to the original behavior for compatability reason,
308use:
309
310`BUILD_BROKEN_DUP_SYSPROP := true`
311
312## ELF prebuilts in `PRODUCT_COPY_FILES` {#BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES}
313
314ELF prebuilts in `PRODUCT_COPY_FILES` that are installed into these paths are an
315error:
316
317* `<partition>/bin/*`
318* `<partition>/lib/*`
319* `<partition>/lib64/*`
320
321Define prebuilt modules and add them to `PRODUCT_PACKAGES` instead.
322To temporarily relax this check and restore the behavior prior to this change,
323set `BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true` in `BoardConfig.mk`.
324
325## COPY_HEADERS usage now produces warnings {#copy_headers}
326
327We've considered `BUILD_COPY_HEADERS`/`LOCAL_COPY_HEADERS` to be deprecated for
328a long time, and the places where it's been able to be used have shrinked over
329the last several releases. Equivalent functionality is not available in Soong.
330
331See the [build/soong/docs/best_practices.md#headers] for more information about
332how best to handle headers in Android.
333
334## `m4` is not available on `$PATH`
335
336There is a prebuilt of it available in prebuilts/build-tools, and a make
337variable `M4` that contains the path.
338
339Beyond the direct usage, whenever you use bison or flex directly, they call m4
340behind the scene, so you must set the M4 environment variable (and depend upon
341it for incremental build correctness):
342
343```
344$(intermediates)/foo.c: .KATI_IMPLICIT_OUTPUTS := $(intermediates)/foo.h
345$(intermediates)/foo.c: $(LOCAL_PATH)/foo.y $(M4) $(BISON) $(BISON_DATA)
346	M4=$(M4) $(BISON) ...
347```
348
349## Rules executed within limited environment
350
351With `ALLOW_NINJA_ENV=false` (soon to be the default), ninja, and all the
352rules/actions executed within it will only have access to a limited number of
353environment variables. Ninja does not track when environment variables change
354in order to trigger rebuilds, so changing behavior based on arbitrary variables
355is not safe with incremental builds.
356
357Kati and Soong can safely use environment variables, so the expectation is that
358you'd embed any environment variables that you need to use within the command
359line generated by those tools. See the [export section](#export_keyword) below
360for examples.
361
362For a temporary workaround, you can set `ALLOW_NINJA_ENV=true` in your
363environment to restore the previous behavior, or set
364`BUILD_BROKEN_NINJA_USES_ENV_VAR := <var> <var2> ...` in your `BoardConfig.mk`
365to allow specific variables to be passed through until you've fixed the rules.
366
367## LOCAL_C_INCLUDES outside the source/output trees are an error {#BUILD_BROKEN_OUTSIDE_INCLUDE_DIRS}
368
369Include directories are expected to be within the source tree (or in the output
370directory, generated during the build). This has been checked in some form
371since Oreo, but now has better checks.
372
373There's now a `BUILD_BROKEN_OUTSIDE_INCLUDE_DIRS` variable, that when set, will
374turn these errors into warnings temporarily. I don't expect this to last more
375than a release, since they're fairly easy to clean up.
376
377Neither of these cases are supported by Soong, and will produce errors when
378converting your module.
379
380### Absolute paths
381
382This has been checked since Oreo. The common reason to hit this is because a
383makefile is calculating a path, and ran abspath/realpath/etc. This is a problem
384because it makes your build non-reproducible. It's very unlikely that your
385source path is the same on every machine.
386
387### Using `../` to leave the source/output directories
388
389This is the new check that has been added. In every case I've found, this has
390been a mistake in the Android.mk -- assuming that `LOCAL_C_INCLUDES` (which is
391relative to the top of the source tree) acts like `LOCAL_SRC_FILES` (which is
392relative to `LOCAL_PATH`).
393
394Since this usually isn't a valid path, you can almost always just remove the
395offending line.
396
397
398## `BOARD_HAL_STATIC_LIBRARIES` and `LOCAL_HAL_STATIC_LIBRARIES` are obsolete {#BOARD_HAL_STATIC_LIBRARIES}
399
400Define proper HIDL / Stable AIDL HAL instead.
401
402* For libhealthd, use health HAL. See instructions for implementing
403  health HAL:
404
405  * [hardware/interfaces/health/2.1/README.md] for health 2.1 HAL (recommended)
406  * [hardware/interfaces/health/1.0/README.md] for health 1.0 HAL
407
408* For libdumpstate, use at least Dumpstate HAL 1.0.
409
410## PRODUCT_STATIC_BOOT_CONTROL_HAL is obsolete {#PRODUCT_STATIC_BOOT_CONTROL_HAL}
411
412`PRODUCT_STATIC_BOOT_CONTROL_HAL` was the workaround to allow sideloading with
413statically linked boot control HAL, before shared library HALs were supported
414under recovery. Android Q has added such support (HALs will be loaded in
415passthrough mode), and the workarounds are being removed. Targets should build
416and install the recovery variant of boot control HAL modules into recovery
417image, similar to the ones installed for normal boot. See the change to
418crosshatch for example of this:
419
420* [device/google/crosshatch/bootctrl/Android.bp] for `bootctrl.sdm845` building
421  rules
422* [device/google/crosshatch/device.mk] for installing `bootctrl.sdm845.recovery`
423  and `android.hardware.boot@1.0-impl.recovery` into recovery image
424
425[device/google/crosshatch/bootctrl/Android.bp]: https://android.googlesource.com/device/google/crosshatch/+/master/bootctrl/Android.bp
426[device/google/crosshatch/device.mk]: https://android.googlesource.com/device/google/crosshatch/+/master/device.mk
427
428## Deprecation of `BUILD_*` module types
429
430See [build/make/Deprecation.md](Deprecation.md) for the current status.
431
432## `PRODUCT_HOST_PACKAGES` split from `PRODUCT_PACKAGES` {#PRODUCT_HOST_PACKAGES}
433
434Previously, adding a module to `PRODUCT_PACKAGES` that supported both the host
435and the target (`host_supported` in Android.bp; two modules with the same name
436in Android.mk) would cause both to be built and installed. In many cases you
437only want either the host or target versions to be built/installed by default,
438and would be over-building with both. So `PRODUCT_PACKAGES` will be changing to
439just affect target modules, while `PRODUCT_HOST_PACKAGES` is being added for
440host modules.
441
442Functional differences between `PRODUCT_PACKAGES` and `PRODUCT_HOST_PACKAGES`:
443
444* `PRODUCT_HOST_PACKAGES` does not have `_ENG`/`_DEBUG` variants, as that's a
445  property of the target, not the host.
446* `PRODUCT_HOST_PACKAGES` does not support `LOCAL_MODULE_OVERRIDES`.
447* `PRODUCT_HOST_PACKAGES` requires listed modules to exist, and be host
448  modules. (Unless `ALLOW_MISSING_DEPENDENCIES` is set)
449
450This is still an active migration, so currently it still uses
451`PRODUCT_PACKAGES` to make installation decisions, but verifies that if we used
452`PRODUCT_HOST_PACKAGES`, it would trigger installation for all of the same host
453packages. This check ignores shared libraries, as those are not normally
454necessary in `PRODUCT_*PACKAGES`, and tended to be over-built (especially the
45532-bit variants).
456
457Future changes will switch installation decisions to `PRODUCT_HOST_PACKAGES`
458for host modules, error when there's a host-only module in `PRODUCT_PACKAGES`,
459and do some further cleanup where `LOCAL_REQUIRED_MODULES` are still merged
460between host and target modules with the same name.
461
462## `*.c.arm` / `*.cpp.arm` deprecation  {#file_arm}
463
464In Android.mk files, you used to be able to change LOCAL_ARM_MODE for each
465source file by appending `.arm` to the end of the filename in
466`LOCAL_SRC_FILES`.
467
468Soong does not support this uncommonly used behavior, instead expecting those
469files to be split out into a separate static library that chooses `arm` over
470`thumb` for the entire library. This must now also be done in Android.mk files.
471
472## Windows cross-compiles no longer supported in Android.mk
473
474Modules that build for Windows (our only `HOST_CROSS` OS currently) must now be
475defined in `Android.bp` files.
476
477## `LOCAL_MODULE_TAGS := eng debug` are obsolete {#LOCAL_MODULE_TAGS}
478
479`LOCAL_MODULE_TAGS` value `eng` and `debug` are now obsolete. They allowed
480modules to specify that they should always be installed on `-eng`, or `-eng`
481and `-userdebug` builds. This conflicted with the ability for products to
482specify which modules should be installed, effectively making it impossible to
483build a stripped down product configuration that did not include those modules.
484
485For the equivalent functionality, specify the modules in `PRODUCT_PACKAGES_ENG`
486or `PRODUCT_PACKAGES_DEBUG` in the appropriate product makefiles.
487
488Core android packages like `su` got added to the list in
489`build/make/target/product/base_system.mk`, but for device-specific modules
490there are often better base product makefiles to use instead.
491
492## `USER` deprecation  {#USER}
493
494`USER` will soon be `nobody` in many cases due to the addition of a sandbox
495around the Android build. Most of the time you shouldn't need to know the
496identity of the user running the build, but if you do, it's available in the
497make variable `BUILD_USERNAME` for now.
498
499Similarly, the `hostname` tool will also be returning a more consistent value
500of `android-build`. The real value is available as `BUILD_HOSTNAME`.
501
502## `BUILD_NUMBER` removal from Android.mk  {#BUILD_NUMBER}
503
504`BUILD_NUMBER` should not be used directly in Android.mk files, as it would
505trigger them to be re-read every time the `BUILD_NUMBER` changes (which it does
506on every build server build). If possible, just remove the use so that your
507builds are more reproducible. If you do need it, use `BUILD_NUMBER_FROM_FILE`:
508
509``` make
510$(LOCAL_BUILT_MODULE):
511	mytool --build_number $(BUILD_NUMBER_FROM_FILE) -o $@
512```
513
514That will expand out to a subshell that will read the current `BUILD_NUMBER`
515whenever it's run. It will not re-run your command if the build number has
516changed, so incremental builds will have the build number from the last time
517the particular output was rebuilt.
518
519## `DIST_DIR`, `dist_goal`, and `dist-for-goals`  {#dist}
520
521`DIST_DIR` and `dist_goal` are no longer available when reading Android.mk
522files (or other build tasks). Always use `dist-for-goals` instead, which takes
523a PHONY goal, and a list of files to copy to `$DIST_DIR`. Whenever `dist` is
524specified, and the goal would be built (either explicitly on the command line,
525or as a dependency of something on the command line), that file will be copied
526into `$DIST_DIR`. For example,
527
528``` make
529$(call dist-for-goals,foo,bar/baz)
530```
531
532will copy `bar/baz` into `$DIST_DIR/baz` when `m foo dist` is run.
533
534#### FILE_NAME_TAG  {#FILE_NAME_TAG}
535
536To embed the `BUILD_NUMBER` (or for local builds, `eng.${USER}`), include
537`FILE_NAME_TAG_PLACEHOLDER` in the destination:
538
539``` make
540# you can use dist-for-goals-with-filenametag function
541$(call dist-for-goals-with-filenametag,foo,bar.zip)
542# or use FILE_NAME_TAG_PLACEHOLDER manually
543$(call dist-for-goals,foo,bar.zip:baz-FILE_NAME_TAG_PLACEHOLDER.zip)
544```
545
546Which will produce `$DIST_DIR/baz-1234567.zip` on build servers which set
547`BUILD_NUMBER=1234567`, or `$DIST_DIR/baz-eng.builder.zip` for local builds.
548
549If you just want to append `BUILD_NUMBER` at the end of basename, use
550`dist-for-goals-with-filenametag` instead of `dist-for-goals`.
551
552#### Renames during copy
553
554Instead of specifying just a file, a destination name can be specified,
555including subdirectories:
556
557``` make
558$(call dist-for-goals,foo,bar/baz:logs/foo.log)
559```
560
561will copy `bar/baz` into `$DIST_DIR/logs/foo.log` when `m foo dist` is run.
562
563## `.PHONY` rule enforcement  {#phony_targets}
564
565There are several new warnings/errors meant to ensure the proper use of
566`.PHONY` targets in order to improve the speed and reliability of incremental
567builds.
568
569`.PHONY`-marked targets are often used as shortcuts to provide "friendly" names
570for real files to be built, but any target marked with `.PHONY` is also always
571considered dirty, needing to be rebuilt every build. This isn't a problem for
572aliases or one-off user-requested operations, but if real builds steps depend
573on a `.PHONY` target, it can get quite expensive for what should be a tiny
574build.
575
576``` make
577...mk:42: warning: PHONY target "out/.../foo" looks like a real file (contains a "/")
578```
579
580Between this warning and the next, we're requiring that `.PHONY` targets do not
581have "/" in them, and real file targets do have a "/". This makes it more
582obvious when reading makefiles what is happening, and will help the build
583system differentiate these in the future too.
584
585``` make
586...mk:42: warning: writing to readonly directory: "kernel-modules"
587```
588
589This warning will show up for one of two reasons:
590
5911. The target isn't intended to be a real file, and should be marked with
592   `.PHONY`. This would be the case for this example.
5932. The target is a real file, but it's outside the output directories. All
594   outputs from the build system should be within the output directory,
595   otherwise `m clean` is unable to clean the build, and future builds may not
596   work properly.
597
598``` make
599...mk:42: warning: real file "out/.../foo" depends on PHONY target "buildbins"
600```
601
602If the first target isn't intended to be a real file, then it should be marked
603with `.PHONY`, which will satisfy this warning. This isn't the case for this
604example, as we require `.PHONY` targets not to have '/' in them.
605
606If the second (PHONY) target is a real file, it may unnecessarily be marked
607with `.PHONY`.
608
609### `.PHONY` and calling other build systems
610
611One common pattern (mostly outside AOSP) that we've seen hit these warning is
612when building with external build systems (firmware, bootloader, kernel, etc).
613Those are often marked as `.PHONY` because the Android build system doesn't
614have enough dependencies to know when to run the other build system again
615during an incremental build.
616
617We recommend to build these outside of Android, and deliver prebuilts into the
618Android tree instead of decreasing the speed and reliability of the incremental
619Android build.
620
621In cases where that's not desired, to preserve the speed of Android
622incrementals, over-specifying dependencies is likely a better option than
623marking it with `.PHONY`:
624
625``` make
626out/target/.../zImage: $(sort $(shell find -L $(KERNEL_SRCDIR)))
627	...
628```
629
630For reliability, many of these other build systems do not guarantee the same
631level of incremental build assurances as the Android Build is attempting to do
632-- without custom checks, Make doesn't rebuild objects when CFLAGS change, etc.
633In order to fix this, our recommendation is to do clean builds for each of
634these external build systems every time anything they rely on changes. For
635relatively smaller builds (like the kernel), this may be reasonable as long as
636you're not trying to actively debug the kernel.
637
638## `export` and `unexport` deprecation  {#export_keyword}
639
640The `export` and `unexport` keywords are obsolete, and will throw errors when
641used.
642
643Device specific configuration should not be able to affect common core build
644steps -- we're looking at triggering build steps to be invalidated if the set
645of environment variables they can access changes. If device specific
646configuration is allowed to change those, switching devices with the same
647output directory could become significantly more expensive than it already can
648be.
649
650If used during Android.mk files, and later tasks, it is increasingly likely
651that they are being used incorrectly. Attempting to change the environment for
652a single build step, and instead setting it for hundreds of thousands.
653
654It is not recommended to just move the environment variable setting outside of
655the build (in vendorsetup.sh, or some other configuration script or wrapper).
656We expect to limit the environment variables that the build respects in the
657future, others will be cleared. (There will be methods to get custom variables
658into the build, just not to every build step)
659
660Instead, write the export commands into the rule command lines themselves:
661
662``` make
663$(intermediates)/generated_output.img:
664	rm -rf $@
665	export MY_ENV_A="$(MY_A)"; make ...
666```
667
668If you want to set many environment variables, and/or use them many times,
669write them out to a script and source the script:
670
671``` make
672envsh := $(intermediates)/env.sh
673$(envsh):
674	rm -rf $@
675	echo 'export MY_ENV_A="$(MY_A)"' >$@
676	echo 'export MY_ENV_B="$(MY_B)"' >>$@
677
678$(intermediates)/generated_output.img: PRIVATE_ENV := $(envsh)
679$(intermediates)/generated_output.img: $(envsh) a/b/c/package.sh
680	rm -rf $@
681	source $(PRIVATE_ENV); make ...
682	source $(PRIVATE_ENV); a/b/c/package.sh ...
683```
684
685## Implicit make rules are obsolete {#implicit_rules}
686
687Implicit rules look something like the following:
688
689``` make
690$(TARGET_OUT_SHARED_LIBRARIES)/%_vendor.so: $(TARGET_OUT_SHARED_LIBRARIES)/%.so
691	...
692
693%.o : %.foo
694	...
695```
696
697These can have wide ranging effects across unrelated modules, so they're now obsolete. Instead, use static pattern rules, which are similar, but explicitly match the specified outputs:
698
699``` make
700libs := $(foreach lib,libfoo libbar,$(TARGET_OUT_SHARED_LIBRARIES)/$(lib)_vendor.so)
701$(libs): %_vendor.so: %.so
702	...
703
704files := $(wildcard $(LOCAL_PATH)/*.foo)
705gen := $(patsubst $(LOCAL_PATH)/%.foo,$(intermediates)/%.o,$(files))
706$(gen): %.o : %.foo
707	...
708```
709
710## Removing '/' from Valid Module Names {#name_slash}
711
712The build system uses module names in path names in many places. Having an
713extra '/' or '../' being inserted can cause problems -- and not just build
714breaks, but stranger invalid behavior.
715
716In every case we've seen, the fix is relatively simple: move the directory into
717`LOCAL_MODULE_RELATIVE_PATH` (or `LOCAL_MODULE_PATH` if you're still using it).
718If this causes multiple modules to be named the same, use unique module names
719and `LOCAL_MODULE_STEM` to change the installed file name:
720
721``` make
722include $(CLEAR_VARS)
723LOCAL_MODULE := ver1/code.bin
724LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware
725...
726include $(BUILD_PREBUILT)
727
728include $(CLEAR_VARS)
729LOCAL_MODULE := ver2/code.bin
730LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware
731...
732include $(BUILD_PREBUILT)
733```
734
735Can be rewritten as:
736
737```
738include $(CLEAR_VARS)
739LOCAL_MODULE := ver1_code.bin
740LOCAL_MODULE_STEM := code.bin
741LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/ver1
742...
743include $(BUILD_PREBUILT)
744
745include $(CLEAR_VARS)
746LOCAL_MODULE := ver2_code.bin
747LOCAL_MODULE_STEM := code.bin
748LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/ver2
749...
750include $(BUILD_PREBUILT)
751```
752
753You just need to make sure that any other references (`PRODUCT_PACKAGES`,
754`LOCAL_REQUIRED_MODULES`, etc) are converted to the new names.
755
756## Valid Module Names {#name}
757
758We've adopted lexical requirements very similar to [Bazel's
759requirements](https://docs.bazel.build/versions/master/build-ref.html#name) for
760target names. Valid characters are `a-z`, `A-Z`, `0-9`, and the special
761characters `_.+-=,@~`. This currently applies to `LOCAL_PACKAGE_NAME`,
762`LOCAL_MODULE`, and `LOCAL_MODULE_SUFFIX`, and `LOCAL_MODULE_STEM*`.
763
764Many other characters already caused problems if you used them, so we don't
765expect this to have a large effect.
766
767## PATH Tools {#PATH_Tools}
768
769The build has started restricting the external host tools usable inside the
770build. This will help ensure that build results are reproducible across
771different machines, and catch mistakes before they become larger issues.
772
773To start with, this includes replacing the $PATH with our own directory of
774tools, mirroring that of the host PATH.  The only difference so far is the
775removal of the host GCC tools. Anything that is not explicitly in the
776configuration as allowed will continue functioning, but will generate a log
777message. This is expected to become more restrictive over time.
778
779The configuration is located in build/soong/ui/build/paths/config.go, and
780contains all the common tools in use in many builds. Anything not in that list
781will currently print a warning in the `$OUT_DIR/soong.log` file, including the
782command and arguments used, and the process tree in order to help locate the
783usage.
784
785In order to fix any issues brought up by these checks, the best way to fix them
786is to use tools checked into the tree -- either as prebuilts, or building them
787as host tools during the build.
788
789As a temporary measure, you can set `TEMPORARY_DISABLE_PATH_RESTRICTIONS=true`
790in your environment to temporarily turn off the error checks and allow any tool
791to be used (with logging). Beware that GCC didn't work well with the interposer
792used for logging, so this may not help in all cases.
793
794## Deprecating / obsoleting envsetup.sh variables in Makefiles
795
796It is not required to source envsetup.sh before running a build. Many scripts,
797including a majority of our automated build systems, do not do so. Make will
798transparently make every environment variable available as a make variable.
799This means that relying on environment variables only set up in envsetup.sh will
800produce different output for local users and scripted users.
801
802Many of these variables also include absolute path names, which we'd like to
803keep out of the generated files, so that you don't need to do a full rebuild if
804you move the source tree.
805
806To fix this, we're marking the variables that are set in envsetup.sh as
807deprecated in the makefiles. This will trigger a warning every time one is read
808(or written) inside Kati. Once all the warnings have been removed for a
809particular variable, we'll switch it to obsolete, and any references will become
810errors.
811
812### envsetup.sh variables with make equivalents
813
814| instead of                                                   | use                  |
815|--------------------------------------------------------------|----------------------|
816| OUT {#OUT}                                                   | PRODUCT_OUT          |
817| ANDROID_HOST_OUT {#ANDROID_HOST_OUT}                         | HOST_OUT             |
818| ANDROID_PRODUCT_OUT {#ANDROID_PRODUCT_OUT}                   | PRODUCT_OUT          |
819| ANDROID_HOST_OUT_TESTCASES {#ANDROID_HOST_OUT_TESTCASES}     | HOST_OUT_TESTCASES   |
820| ANDROID_TARGET_OUT_TESTCASES {#ANDROID_TARGET_OUT_TESTCASES} | TARGET_OUT_TESTCASES |
821
822All of the make variables may be relative paths from the current directory, or
823absolute paths if the output directory was specified as an absolute path. If you
824need an absolute variable, convert it to absolute during a rule, so that it's
825not expanded into the generated ninja file:
826
827``` make
828$(PRODUCT_OUT)/gen.img: my/src/path/gen.sh
829	export PRODUCT_OUT=$$(cd $(PRODUCT_OUT); pwd); cd my/src/path; ./gen.sh -o $${PRODUCT_OUT}/gen.img
830```
831
832### ANDROID_BUILD_TOP  {#ANDROID_BUILD_TOP}
833
834In Android.mk files, you can always assume that the current directory is the
835root of the source tree, so this can just be replaced with '.' (which is what
836$TOP is hardcoded to), or removed entirely. If you need an absolute path, see
837the instructions above.
838
839### Stop using PATH directly  {#PATH}
840
841This isn't only set by envsetup.sh, but it is modified by it. Due to that it's
842rather easy for this to change between different shells, and it's not ideal to
843reread the makefiles every time this changes.
844
845In most cases, you shouldn't need to touch PATH at all. When you need to have a
846rule reference a particular binary that's part of the source tree or outputs,
847it's preferrable to just use the path to the file itself (since you should
848already be adding that as a dependency).
849
850Depending on the rule, passing the file path itself may not be feasible due to
851layers of unchangable scripts/binaries. In that case, be sure to add the
852dependency, but modify the PATH within the rule itself:
853
854``` make
855$(TARGET): myscript my/path/binary
856	PATH=my/path:$$PATH myscript -o $@
857```
858
859### Stop using PYTHONPATH directly  {#PYTHONPATH}
860
861Like PATH, this isn't only set by envsetup.sh, but it is modified by it. Due to
862that it's rather easy for this to change between different shells, and it's not
863ideal to reread the makefiles every time.
864
865The best solution here is to start switching to Soong's python building support,
866which packages the python interpreter, libraries, and script all into one file
867that no longer needs PYTHONPATH. See fontchain_lint for examples of this:
868
869* [external/fonttools/Lib/fontTools/Android.bp] for python_library_host
870* [frameworks/base/Android.bp] for python_binary_host
871* [frameworks/base/data/fonts/Android.mk] to execute the python binary
872
873If you still need to use PYTHONPATH, do so within the rule itself, just like
874path:
875
876``` make
877$(TARGET): myscript.py $(sort $(shell find my/python/lib -name '*.py'))
878	PYTHONPATH=my/python/lib:$$PYTHONPATH myscript.py -o $@
879```
880### Stop using PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE directly {#PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE}
881
882Specify Framework Compatibility Matrix Version in device manifest by adding a `target-level`
883attribute to the root element `<manifest>`. If `PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE`
884is 26 or 27, you can add `"target-level"="1"` to your device manifest instead.
885
886### Stop using USE_CLANG_PLATFORM_BUILD {#USE_CLANG_PLATFORM_BUILD}
887
888Clang is the default and only supported Android compiler, so there is no reason
889for this option to exist.
890
891### Stop using clang property
892
893The clang property has been deleted from Soong. To fix any build errors, remove the clang
894property from affected Android.bp files using bpmodify.
895
896
897``` make
898go run bpmodify.go -w -m=module_name -remove-property=true -property=clang filepath
899```
900
901`BUILD_BROKEN_CLANG_PROPERTY` can be used as temporarily workaround
902
903
904### Stop using clang_cflags and clang_asflags
905
906clang_cflags and clang_asflags are deprecated.
907To fix any build errors, use bpmodify to either
908    - move the contents of clang_asflags/clang_cflags into asflags/cflags or
909    - delete clang_cflags/as_flags as necessary
910
911To Move the contents:
912``` make
913go run bpmodify.go -w -m=module_name -move-property=true -property=clang_cflags -new-location=cflags filepath
914```
915
916To Delete:
917``` make
918go run bpmodify.go -w -m=module_name -remove-property=true -property=clang_cflags filepath
919```
920
921`BUILD_BROKEN_CLANG_ASFLAGS` and `BUILD_BROKEN_CLANG_CFLAGS` can be used as temporarily workarounds
922
923### Other envsetup.sh variables  {#other_envsetup_variables}
924
925* ANDROID_TOOLCHAIN
926* ANDROID_TOOLCHAIN_2ND_ARCH
927* ANDROID_DEV_SCRIPTS
928* ANDROID_EMULATOR_PREBUILTS
929* ANDROID_PRE_BUILD_PATHS
930
931These are all exported from envsetup.sh, but don't have clear equivalents within
932the makefile system. If you need one of them, you'll have to set up your own
933version.
934
935## Soong config variables
936
937### Soong config string variables must list all values they can be set to
938
939In order to facilitate the transition to bazel, all soong_config_string_variables
940must only be set to a value listed in their `values` property, or an empty string.
941It is a build error otherwise.
942
943Example Android.bp:
944```
945soong_config_string_variable {
946    name: "my_string_variable",
947    values: [
948        "foo",
949        "bar",
950    ],
951}
952
953soong_config_module_type {
954    name: "my_cc_defaults",
955    module_type: "cc_defaults",
956    config_namespace: "my_namespace",
957    variables: ["my_string_variable"],
958    properties: [
959        "shared_libs",
960        "static_libs",
961    ],
962}
963```
964Product config:
965```
966$(call soong_config_set,my_namespace,my_string_variable,baz) # Will be an error as baz is not listed in my_string_variable's values.
967```
968
969[build/soong/Changes.md]: https://android.googlesource.com/platform/build/soong/+/master/Changes.md
970[build/soong/docs/best_practices.md#headers]: https://android.googlesource.com/platform/build/soong/+/master/docs/best_practices.md#headers
971[external/fonttools/Lib/fontTools/Android.bp]: https://android.googlesource.com/platform/external/fonttools/+/master/Lib/fontTools/Android.bp
972[frameworks/base/Android.bp]: https://android.googlesource.com/platform/frameworks/base/+/master/Android.bp
973[frameworks/base/data/fonts/Android.mk]: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/Android.mk
974[hardware/interfaces/health/1.0/README.md]: https://android.googlesource.com/platform/hardware/interfaces/+/master/health/1.0/README.md
975[hardware/interfaces/health/2.1/README.md]: https://android.googlesource.com/platform/hardware/interfaces/+/master/health/2.1/README.md
976