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