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