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