• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Build System Changes for Android.mk Writers
2
3## `PRODUCT_HOST_PACKAGES` split from `PRODUCT_PACKAGES` {#PRODUCT_HOST_PACKAGES}
4
5Previously, adding a module to `PRODUCT_PACKAGES` that supported both the host
6and the target (`host_supported` in Android.bp; two modules with the same name
7in Android.mk) would cause both to be built and installed. In many cases you
8only want either the host or target versions to be built/installed by default,
9and would be over-building with both. So `PRODUCT_PACKAGES` will be changing to
10just affect target modules, while `PRODUCT_HOST_PACKAGES` is being added for
11host modules.
12
13Functional differences between `PRODUCT_PACKAGES` and `PRODUCT_HOST_PACKAGES`:
14
15* `PRODUCT_HOST_PACKAGES` does not have `_ENG`/`_DEBUG` variants, as that's a
16  property of the target, not the host.
17* `PRODUCT_HOST_PACKAGES` does not support `LOCAL_MODULE_OVERRIDES`.
18* `PRODUCT_HOST_PACKAGES` requires listed modules to exist, and be host
19  modules. (Unless `ALLOW_MISSING_DEPENDENCIES` is set)
20
21This is still an active migration, so currently it still uses
22`PRODUCT_PACKAGES` to make installation decisions, but verifies that if we used
23`PRODUCT_HOST_PACKAGES`, it would trigger installation for all of the same host
24packages. This check ignores shared libraries, as those are not normally
25necessary in `PRODUCT_*PACKAGES`, and tended to be over-built (especially the
2632-bit variants).
27
28Future changes will switch installation decisions to `PRODUCT_HOST_PACKAGES`
29for host modules, error when there's a host-only module in `PRODUCT_PACKAGES`,
30and do some further cleanup where `LOCAL_REQUIRED_MODULES` are still merged
31between host and target modules with the same name.
32
33## `*.c.arm` / `*.cpp.arm` deprecation  {#file_arm}
34
35In Android.mk files, you used to be able to change LOCAL_ARM_MODE for each
36source file by appending `.arm` to the end of the filename in
37`LOCAL_SRC_FILES`.
38
39Soong does not support this uncommonly used behavior, instead expecting those
40files to be split out into a separate static library that chooses `arm` over
41`thumb` for the entire library. This must now also be done in Android.mk files.
42
43## Windows cross-compiles no longer supported in Android.mk
44
45Modules that build for Windows (our only `HOST_CROSS` OS currently) must now be
46defined in `Android.bp` files.
47
48## `LOCAL_MODULE_TAGS := eng debug` deprecation  {#LOCAL_MODULE_TAGS}
49
50`LOCAL_MODULE_TAGS` value `eng` and `debug` are being deprecated. They allowed
51modules to specify that they should always be installed on `-eng`, or `-eng`
52and `-userdebug` builds. This conflicted with the ability for products to
53specify which modules should be installed, effectively making it impossible to
54build a stripped down product configuration that did not include those modules.
55
56For the equivalent functionality, specify the modules in `PRODUCT_PACKAGES_ENG`
57or `PRODUCT_PACKAGES_DEBUG` in the appropriate product makefiles.
58
59Core android packages like `su` got added to the list in
60`build/make/target/product/base_system.mk`, but for device-specific modules
61there are often better base product makefiles to use instead.
62
63## `USER` deprecation  {#USER}
64
65`USER` will soon be `nobody` in many cases due to the addition of a sandbox
66around the Android build. Most of the time you shouldn't need to know the
67identity of the user running the build, but if you do, it's available in the
68make variable `BUILD_USERNAME` for now.
69
70Similarly, the `hostname` tool will also be returning a more consistent value
71of `android-build`. The real value is available as `BUILD_HOSTNAME`.
72
73## `BUILD_NUMBER` removal from Android.mk  {#BUILD_NUMBER}
74
75`BUILD_NUMBER` should not be used directly in Android.mk files, as it would
76trigger them to be re-read every time the `BUILD_NUMBER` changes (which it does
77on every build server build). If possible, just remove the use so that your
78builds are more reproducible. If you do need it, use `BUILD_NUMBER_FROM_FILE`:
79
80``` make
81$(LOCAL_BUILT_MODULE):
82	mytool --build_number $(BUILD_NUMBER_FROM_FILE) -o $@
83```
84
85That will expand out to a subshell that will read the current `BUILD_NUMBER`
86whenever it's run. It will not re-run your command if the build number has
87changed, so incremental builds will have the build number from the last time
88the particular output was rebuilt.
89
90## `DIST_DIR`, `dist_goal`, and `dist-for-goals`  {#dist}
91
92`DIST_DIR` and `dist_goal` are no longer available when reading Android.mk
93files (or other build tasks). Always use `dist-for-goals` instead, which takes
94a PHONY goal, and a list of files to copy to `$DIST_DIR`. Whenever `dist` is
95specified, and the goal would be built (either explicitly on the command line,
96or as a dependency of something on the command line), that file will be copied
97into `$DIST_DIR`. For example,
98
99``` make
100$(call dist-for-goals,foo,bar/baz)
101```
102
103will copy `bar/baz` into `$DIST_DIR/baz` when `m foo dist` is run.
104
105#### Renames during copy
106
107Instead of specifying just a file, a destination name can be specified,
108including subdirectories:
109
110``` make
111$(call dist-for-goals,foo,bar/baz:logs/foo.log)
112```
113
114will copy `bar/baz` into `$DIST_DIR/logs/foo.log` when `m foo dist` is run.
115
116## `.PHONY` rule enforcement  {#phony_targets}
117
118There are several new warnings/errors meant to ensure the proper use of
119`.PHONY` targets in order to improve the speed and reliability of incremental
120builds.
121
122`.PHONY`-marked targets are often used as shortcuts to provide "friendly" names
123for real files to be built, but any target marked with `.PHONY` is also always
124considered dirty, needing to be rebuilt every build. This isn't a problem for
125aliases or one-off user-requested operations, but if real builds steps depend
126on a `.PHONY` target, it can get quite expensive for what should be a tiny
127build.
128
129``` make
130...mk:42: warning: PHONY target "out/.../foo" looks like a real file (contains a "/")
131```
132
133Between this warning and the next, we're requiring that `.PHONY` targets do not
134have "/" in them, and real file targets do have a "/". This makes it more
135obvious when reading makefiles what is happening, and will help the build
136system differentiate these in the future too.
137
138``` make
139...mk:42: warning: writing to readonly directory: "kernel-modules"
140```
141
142This warning will show up for one of two reasons:
143
1441. The target isn't intended to be a real file, and should be marked with
145   `.PHONY`. This would be the case for this example.
1462. The target is a real file, but it's outside the output directories. All
147   outputs from the build system should be within the output directory,
148   otherwise `m clean` is unable to clean the build, and future builds may not
149   work properly.
150
151``` make
152...mk:42: warning: real file "out/.../foo" depends on PHONY target "buildbins"
153```
154
155If the first target isn't intended to be a real file, then it should be marked
156with `.PHONY`, which will satisfy this warning. This isn't the case for this
157example, as we require `.PHONY` targets not to have '/' in them.
158
159If the second (PHONY) target is a real file, it may unnecessarily be marked
160with `.PHONY`.
161
162### `.PHONY` and calling other build systems
163
164One common pattern (mostly outside AOSP) that we've seen hit these warning is
165when building with external build systems (firmware, bootloader, kernel, etc).
166Those are often marked as `.PHONY` because the Android build system doesn't
167have enough dependencies to know when to run the other build system again
168during an incremental build.
169
170We recommend to build these outside of Android, and deliver prebuilts into the
171Android tree instead of decreasing the speed and reliability of the incremental
172Android build.
173
174In cases where that's not desired, to preserve the speed of Android
175incrementals, over-specifying dependencies is likely a better option than
176marking it with `.PHONY`:
177
178``` make
179out/target/.../zImage: $(sort $(shell find -L $(KERNEL_SRCDIR)))
180	...
181```
182
183For reliability, many of these other build systems do not guarantee the same
184level of incremental build assurances as the Android Build is attempting to do
185-- without custom checks, Make doesn't rebuild objects when CFLAGS change, etc.
186In order to fix this, our recommendation is to do clean builds for each of
187these external build systems every time anything they rely on changes. For
188relatively smaller builds (like the kernel), this may be reasonable as long as
189you're not trying to actively debug the kernel.
190
191## `export` and `unexport` deprecation  {#export_keyword}
192
193The `export` and `unexport` keywords have been deprecated, and will throw
194warnings or errors depending on where they are used.
195
196Early in the make system, during product configuration and BoardConfig.mk
197reading: these will throw a warnings, and will be an error in the future.
198Device specific configuration should not be able to affect common core build
199steps -- we're looking at triggering build steps to be invalidated if the set
200of environment variables they can access changes. If device specific
201configuration is allowed to change those, switching devices with the same
202output directory could become significantly more expensive than it already can
203be.
204
205Later, during Android.mk files, and later tasks: these will throw errors, since
206it is increasingly likely that they are being used incorrectly, attempting to
207change the environment for a single build step, and instead setting it for
208hundreds of thousands.
209
210It is not recommended to just move the environment variable setting outside of
211the build (in vendorsetup.sh, or some other configuration script or wrapper).
212We expect to limit the environment variables that the build respects in the
213future, others will be cleared. (There will be methods to get custom variables
214into the build, just not to every build step)
215
216Instead, write the export commands into the rule command lines themselves:
217
218``` make
219$(intermediates)/generated_output.img:
220	rm -rf $@
221	export MY_ENV_A="$(MY_A)"; make ...
222```
223
224If you want to set many environment variables, and/or use them many times,
225write them out to a script and source the script:
226
227``` make
228envsh := $(intermediates)/env.sh
229$(envsh):
230	rm -rf $@
231	echo 'export MY_ENV_A="$(MY_A)"' >$@
232	echo 'export MY_ENV_B="$(MY_B)"' >>$@
233
234$(intermediates)/generated_output.img: PRIVATE_ENV := $(envsh)
235$(intermediates)/generated_output.img: $(envsh) a/b/c/package.sh
236	rm -rf $@
237	source $(PRIVATE_ENV); make ...
238	source $(PRIVATE_ENV); a/b/c/package.sh ...
239```
240
241## Implicit make rules are obsolete {#implicit_rules}
242
243Implicit rules look something like the following:
244
245``` make
246$(TARGET_OUT_SHARED_LIBRARIES)/%_vendor.so: $(TARGET_OUT_SHARED_LIBRARIES)/%.so
247	...
248
249%.o : %.foo
250	...
251```
252
253These 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:
254
255``` make
256libs := $(foreach lib,libfoo libbar,$(TARGET_OUT_SHARED_LIBRARIES)/$(lib)_vendor.so)
257$(libs): %_vendor.so: %.so
258	...
259
260files := $(wildcard $(LOCAL_PATH)/*.foo)
261gen := $(patsubst $(LOCAL_PATH)/%.foo,$(intermediates)/%.o,$(files))
262$(gen): %.o : %.foo
263	...
264```
265
266## Removing '/' from Valid Module Names {#name_slash}
267
268The build system uses module names in path names in many places. Having an
269extra '/' or '../' being inserted can cause problems -- and not just build
270breaks, but stranger invalid behavior.
271
272In every case we've seen, the fix is relatively simple: move the directory into
273`LOCAL_MODULE_RELATIVE_PATH` (or `LOCAL_MODULE_PATH` if you're still using it).
274If this causes multiple modules to be named the same, use unique module names
275and `LOCAL_MODULE_STEM` to change the installed file name:
276
277``` make
278include $(CLEAR_VARS)
279LOCAL_MODULE := ver1/code.bin
280LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware
281...
282include $(BUILD_PREBUILT)
283
284include $(CLEAR_VARS)
285LOCAL_MODULE := ver2/code.bin
286LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/firmware
287...
288include $(BUILD_PREBUILT)
289```
290
291Can be rewritten as:
292
293```
294include $(CLEAR_VARS)
295LOCAL_MODULE := ver1_code.bin
296LOCAL_MODULE_STEM := code.bin
297LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/ver1
298...
299include $(BUILD_PREBUILT)
300
301include $(CLEAR_VARS)
302LOCAL_MODULE := ver2_code.bin
303LOCAL_MODULE_STEM := code.bin
304LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/firmware/ver2
305...
306include $(BUILD_PREBUILT)
307```
308
309You just need to make sure that any other references (`PRODUCT_PACKAGES`,
310`LOCAL_REQUIRED_MODULES`, etc) are converted to the new names.
311
312## Valid Module Names {#name}
313
314We've adopted lexical requirements very similar to [Bazel's
315requirements](https://docs.bazel.build/versions/master/build-ref.html#name) for
316target names. Valid characters are `a-z`, `A-Z`, `0-9`, and the special
317characters `_.+-=,@~`. This currently applies to `LOCAL_PACKAGE_NAME`,
318`LOCAL_MODULE`, and `LOCAL_MODULE_SUFFIX`, and `LOCAL_MODULE_STEM*`.
319
320Many other characters already caused problems if you used them, so we don't
321expect this to have a large effect.
322
323## PATH Tools {#PATH_Tools}
324
325The build has started restricting the external host tools usable inside the
326build. This will help ensure that build results are reproducible across
327different machines, and catch mistakes before they become larger issues.
328
329To start with, this includes replacing the $PATH with our own directory of
330tools, mirroring that of the host PATH.  The only difference so far is the
331removal of the host GCC tools. Anything that is not explicitly in the
332configuration as allowed will continue functioning, but will generate a log
333message. This is expected to become more restrictive over time.
334
335The configuration is located in build/soong/ui/build/paths/config.go, and
336contains all the common tools in use in many builds. Anything not in that list
337will currently print a warning in the `$OUT_DIR/soong.log` file, including the
338command and arguments used, and the process tree in order to help locate the
339usage.
340
341In order to fix any issues brought up by these checks, the best way to fix them
342is to use tools checked into the tree -- either as prebuilts, or building them
343as host tools during the build.
344
345As a temporary measure, you can set `TEMPORARY_DISABLE_PATH_RESTRICTIONS=true`
346in your environment to temporarily turn off the error checks and allow any tool
347to be used (with logging). Beware that GCC didn't work well with the interposer
348used for logging, so this may not help in all cases.
349
350## Deprecating / obsoleting envsetup.sh variables in Makefiles
351
352It is not required to source envsetup.sh before running a build. Many scripts,
353including a majority of our automated build systems, do not do so. Make will
354transparently make every environment variable available as a make variable.
355This means that relying on environment variables only set up in envsetup.sh will
356produce different output for local users and scripted users.
357
358Many of these variables also include absolute path names, which we'd like to
359keep out of the generated files, so that you don't need to do a full rebuild if
360you move the source tree.
361
362To fix this, we're marking the variables that are set in envsetup.sh as
363deprecated in the makefiles. This will trigger a warning every time one is read
364(or written) inside Kati. Once all the warnings have been removed for a
365particular variable, we'll switch it to obsolete, and any references will become
366errors.
367
368### envsetup.sh variables with make equivalents
369
370| instead of                                                   | use                  |
371|--------------------------------------------------------------|----------------------|
372| OUT {#OUT}                                                   | OUT_DIR              |
373| ANDROID_HOST_OUT {#ANDROID_HOST_OUT}                         | HOST_OUT             |
374| ANDROID_PRODUCT_OUT {#ANDROID_PRODUCT_OUT}                   | PRODUCT_OUT          |
375| ANDROID_HOST_OUT_TESTCASES {#ANDROID_HOST_OUT_TESTCASES}     | HOST_OUT_TESTCASES   |
376| ANDROID_TARGET_OUT_TESTCASES {#ANDROID_TARGET_OUT_TESTCASES} | TARGET_OUT_TESTCASES |
377
378All of the make variables may be relative paths from the current directory, or
379absolute paths if the output directory was specified as an absolute path. If you
380need an absolute variable, convert it to absolute during a rule, so that it's
381not expanded into the generated ninja file:
382
383``` make
384$(PRODUCT_OUT)/gen.img: my/src/path/gen.sh
385	export PRODUCT_OUT=$$(cd $(PRODUCT_OUT); pwd); cd my/src/path; ./gen.sh -o $${PRODUCT_OUT}/gen.img
386```
387
388### ANDROID_BUILD_TOP  {#ANDROID_BUILD_TOP}
389
390In Android.mk files, you can always assume that the current directory is the
391root of the source tree, so this can just be replaced with '.' (which is what
392$TOP is hardcoded to), or removed entirely. If you need an absolute path, see
393the instructions above.
394
395### Stop using PATH directly  {#PATH}
396
397This isn't only set by envsetup.sh, but it is modified by it. Due to that it's
398rather easy for this to change between different shells, and it's not ideal to
399reread the makefiles every time this changes.
400
401In most cases, you shouldn't need to touch PATH at all. When you need to have a
402rule reference a particular binary that's part of the source tree or outputs,
403it's preferrable to just use the path to the file itself (since you should
404already be adding that as a dependency).
405
406Depending on the rule, passing the file path itself may not be feasible due to
407layers of unchangable scripts/binaries. In that case, be sure to add the
408dependency, but modify the PATH within the rule itself:
409
410``` make
411$(TARGET): myscript my/path/binary
412	PATH=my/path:$$PATH myscript -o $@
413```
414
415### Stop using PYTHONPATH directly  {#PYTHONPATH}
416
417Like PATH, this isn't only set by envsetup.sh, but it is modified by it. Due to
418that it's rather easy for this to change between different shells, and it's not
419ideal to reread the makefiles every time.
420
421The best solution here is to start switching to Soong's python building support,
422which packages the python interpreter, libraries, and script all into one file
423that no longer needs PYTHONPATH. See fontchain_lint for examples of this:
424
425* [external/fonttools/Lib/fontTools/Android.bp] for python_library_host
426* [frameworks/base/Android.bp] for python_binary_host
427* [frameworks/base/data/fonts/Android.mk] to execute the python binary
428
429If you still need to use PYTHONPATH, do so within the rule itself, just like
430path:
431
432``` make
433$(TARGET): myscript.py $(sort $(shell find my/python/lib -name '*.py'))
434	PYTHONPATH=my/python/lib:$$PYTHONPATH myscript.py -o $@
435```
436### Stop using PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE directly {#PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE}
437
438Specify Framework Compatibility Matrix Version in device manifest by adding a `target-level`
439attribute to the root element `<manifest>`. If `PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE`
440is 26 or 27, you can add `"target-level"="1"` to your device manifest instead.
441
442### Stop using USE_CLANG_PLATFORM_BUILD {#USE_CLANG_PLATFORM_BUILD}
443
444Clang is the default and only supported Android compiler, so there is no reason
445for this option to exist.
446
447### Other envsetup.sh variables  {#other_envsetup_variables}
448
449* ANDROID_TOOLCHAIN
450* ANDROID_TOOLCHAIN_2ND_ARCH
451* ANDROID_DEV_SCRIPTS
452* ANDROID_EMULATOR_PREBUILTS
453* ANDROID_PRE_BUILD_PATHS
454
455These are all exported from envsetup.sh, but don't have clear equivalents within
456the makefile system. If you need one of them, you'll have to set up your own
457version.
458
459
460[build/soong/Changes.md]: https://android.googlesource.com/platform/build/soong/+/master/Changes.md
461[external/fonttools/Lib/fontTools/Android.bp]: https://android.googlesource.com/platform/external/fonttools/+/master/Lib/fontTools/Android.bp
462[frameworks/base/Android.bp]: https://android.googlesource.com/platform/frameworks/base/+/master/Android.bp
463[frameworks/base/data/fonts/Android.mk]: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/Android.mk
464