README.md
1# mkcompare: Compare generated Android-TARGET.mk makefiles
2
3## Summary
4
5This tool shows the differences between two `Android-`_target_`.mk` makefile.
6This makefile contains information about the Soong build graph that is exposed
7to Make (Android.mk) and packaging rules.
8
9## Usage
10
11```shell
12# run product config
13$ lunch ${target}
14
15# run soong for reference build
16$ m nothing && cp out/soong/Android-${target}.mk Android-${target}.mk.ref
17
18# apply your local changes..
19$ m nothing && cp out/soong/Android-${target}.mk Android-${target}.mk.new
20
21# compare!
22$ GOWORK=$PWD/build/bazel/mkcompare/go.work go run android/bazel/mkcompare/cmd \
23 -json \
24 Android-${target}.mk.ref \
25 Android-${target}.mk.new > ${target}.mk.json
26```
27
28## Options ##
29
30The comparator optionally:
31
32* Generates a JSON file with all the differences (`-json`). This option turns off all out output.
33* Stops after finding given _N_ different modules `-m N`)
34* Ignores variables with given names (`--ignore_variables=VAR,...`)
35* Shows per-variable value difference (`--show_module_diffs`)
36* For each module type, shows the names of the modules with this difference (`--show_type_modules`)
37
38## How it works
39
40We assume that both makefiles were generated for the same configuration (i.e.,
41the same _target_ value, and our goal is thus to find out the difference that
42a change contributes to the Makefile interface between Soong and Make.
43
44Currently, the comparator inspects only the module sections of a file.
45
46A _module section_ looks something like this:
47```makefile
48include $(CLEAR_VARS) # <module type>
49LOCAL_MODULE := mymod
50LOCAL_MODULE_CLASS := ETC
51include $(BUILD_PREBUILT)
52```
53
54i.e., it always starts with `include $(CLEAR_VARS)` ('module header') line
55and spans until the blank line. Before a blank line there is an
56`include <mkfile>` line ('module footer'), which may be followed by a few extra
57variable assignments. Between those two `include ` lines are the assignment lines.
58
59The name of the module is synthesized from the value of the `LOCAL_MODULE` variable
60and target configuration, e.g, `apex_tzdata.com.android.tzdata|cls:ETC|target_arch:arm64`
61or `aac_dec_fuzzer|cls:EXECUTABLES|host_arch:x86_64`
62
63The module header includes the module type as a comment (the plan was to use the
64_mkfile_ on the footer line, but it proved to be common to most of the modules,
65so Soong was modified to provide a module detailed module type as a comment
66on the header line).
67
68A module section in the reference file is compared with the
69identically named module section of our file. The following items are compared:
70
71* module types
72* the number of extra lines following the section footer
73* the variables and their values
74
75## Summary Output
76
77The default outputs look as follows:
78```
79159 missing modules, by type:
80 apex.apexBundle.files (159 modules)
81
82Missing variables (14):
83 ...
84 LOCAL_REQUIRED_MODULES, by type:
85 art_cc_library (2 modules)
86 art_cc_library_static (4 modules)
87 cc_library (28 modules)
88 cc_library_shared (2 modules)
89 LOCAL_SHARED_LIBRARIES, by type:
90 art_cc_library (60 modules)
91 ....
92Extra variables (7):
93 LOCAL_EXPORT_CFLAGS, by type:
94 cc_library (4 modules)
95 LOCAL_EXPORT_C_INCLUDE_DEPS, by type:
96 art_cc_library (28 modules)
97 ...
98Diff variables: (18)
99 LOCAL_EXPORT_C_INCLUDE_DEPS, by type:
100 aidl_interface.go_android/soong/aidl.wrapLibraryFactory.func1__topDownMutatorModule (1721 modules)
101 art_cc_library (12 modules)
102 LOCAL_PREBUILT_MODULE_FILE, by type:
103 apex.apexBundle (7 modules)
104 apex.apexBundle.files (625 modules)
105 ...
106```
107
108## JSON Output ##
109
110It looks like this:
111```JSON
112{
113 "RefPath": "<...>/out/soong/Android-aosp_arm64.mk",
114 "OurPath": "<...>/out.mixed/soong/Android-aosp_arm64.mk",
115 "MissingModules": [
116 "adbd.com.android.adbd|cls:EXECUTABLES|target_arch:arm64",
117 "android.hardware.common-V2-ndk.com.android.media.swcodec|cls:SHARED_LIBRARIES|target_arch:arm64",
118 "android.hardware.graphics.allocator-V1-ndk.com.android.media.swcodec|cls:SHARED_LIBRARIES|target_arch:arm64",
119 "android.hardware.graphics.allocator@2.0.com.android.media.swcodec|cls:SHARED_LIBRARIES|target_arch:arm64",
120 ...
121 ],
122 "DiffModules": [
123 {
124 "Name": "_makenames|cls:EXECUTABLES|target_arch:arm64",
125 "RefLocation": 137674,
126 "OurLocation": 137673,
127 "MissingVars": [ "LOCAL_SHARED_LIBRARIES", "LOCAL_STATIC_LIBRARIES" ],
128 "DiffVars": [
129 {
130 "Name": "LOCAL_PREBUILT_MODULE_FILE",
131 "MissingItems": [ "out/soong/.intermediates/external/libcap/_makenames/android_arm64_armv8-a/_makenames" ],
132 "ExtraItems": [ "out/bazel-bin/external/libcap/_makenames" ]
133 },
134 {
135 "Name": "LOCAL_SOONG_UNSTRIPPED_BINARY",
136 "MissingItems": [ "out/soong/.intermediates/external/libcap/_makenames/android_arm64_armv8-a/unstripped/_makenames" ],
137 "ExtraItems": [ "out/bazel-bin/external/libcap/_makenames_unstripped" ]
138 }
139 ]
140 },
141 ...
142 ]
143}
144```
145Use JSON query tool like [`jq`](https://github.com/stedolan/jq) to slice and dice it.
146