# mkcompare: Compare generated Android-TARGET.mk makefiles ## Summary This tool shows the differences between two `Android-`_target_`.mk` makefile. This makefile contains information about the Soong build graph that is exposed to Make (Android.mk) and packaging rules. ## Usage ```shell # run product config $ lunch ${target} # run soong for reference build $ m nothing && cp out/soong/Android-${target}.mk Android-${target}.mk.ref # apply your local changes.. $ m nothing && cp out/soong/Android-${target}.mk Android-${target}.mk.new # compare! $ GOWORK=$PWD/build/bazel/mkcompare/go.work go run android/bazel/mkcompare/cmd \ -json \ Android-${target}.mk.ref \ Android-${target}.mk.new > ${target}.mk.json ``` ## Options ## The comparator optionally: * Generates a JSON file with all the differences (`-json`). This option turns off all out output. * Stops after finding given _N_ different modules `-m N`) * Ignores variables with given names (`--ignore_variables=VAR,...`) * Shows per-variable value difference (`--show_module_diffs`) * For each module type, shows the names of the modules with this difference (`--show_type_modules`) ## How it works We assume that both makefiles were generated for the same configuration (i.e., the same _target_ value, and our goal is thus to find out the difference that a change contributes to the Makefile interface between Soong and Make. Currently, the comparator inspects only the module sections of a file. A _module section_ looks something like this: ```makefile include $(CLEAR_VARS) # LOCAL_MODULE := mymod LOCAL_MODULE_CLASS := ETC include $(BUILD_PREBUILT) ``` i.e., it always starts with `include $(CLEAR_VARS)` ('module header') line and spans until the blank line. Before a blank line there is an `include ` line ('module footer'), which may be followed by a few extra variable assignments. Between those two `include ` lines are the assignment lines. The name of the module is synthesized from the value of the `LOCAL_MODULE` variable and target configuration, e.g, `apex_tzdata.com.android.tzdata|cls:ETC|target_arch:arm64` or `aac_dec_fuzzer|cls:EXECUTABLES|host_arch:x86_64` The module header includes the module type as a comment (the plan was to use the _mkfile_ on the footer line, but it proved to be common to most of the modules, so Soong was modified to provide a module detailed module type as a comment on the header line). A module section in the reference file is compared with the identically named module section of our file. The following items are compared: * module types * the number of extra lines following the section footer * the variables and their values ## Summary Output The default outputs look as follows: ``` 159 missing modules, by type: apex.apexBundle.files (159 modules) Missing variables (14): ... LOCAL_REQUIRED_MODULES, by type: art_cc_library (2 modules) art_cc_library_static (4 modules) cc_library (28 modules) cc_library_shared (2 modules) LOCAL_SHARED_LIBRARIES, by type: art_cc_library (60 modules) .... Extra variables (7): LOCAL_EXPORT_CFLAGS, by type: cc_library (4 modules) LOCAL_EXPORT_C_INCLUDE_DEPS, by type: art_cc_library (28 modules) ... Diff variables: (18) LOCAL_EXPORT_C_INCLUDE_DEPS, by type: aidl_interface.go_android/soong/aidl.wrapLibraryFactory.func1__topDownMutatorModule (1721 modules) art_cc_library (12 modules) LOCAL_PREBUILT_MODULE_FILE, by type: apex.apexBundle (7 modules) apex.apexBundle.files (625 modules) ... ``` ## JSON Output ## It looks like this: ```JSON { "RefPath": "<...>/out/soong/Android-aosp_arm64.mk", "OurPath": "<...>/out.mixed/soong/Android-aosp_arm64.mk", "MissingModules": [ "adbd.com.android.adbd|cls:EXECUTABLES|target_arch:arm64", "android.hardware.common-V2-ndk.com.android.media.swcodec|cls:SHARED_LIBRARIES|target_arch:arm64", "android.hardware.graphics.allocator-V1-ndk.com.android.media.swcodec|cls:SHARED_LIBRARIES|target_arch:arm64", "android.hardware.graphics.allocator@2.0.com.android.media.swcodec|cls:SHARED_LIBRARIES|target_arch:arm64", ... ], "DiffModules": [ { "Name": "_makenames|cls:EXECUTABLES|target_arch:arm64", "RefLocation": 137674, "OurLocation": 137673, "MissingVars": [ "LOCAL_SHARED_LIBRARIES", "LOCAL_STATIC_LIBRARIES" ], "DiffVars": [ { "Name": "LOCAL_PREBUILT_MODULE_FILE", "MissingItems": [ "out/soong/.intermediates/external/libcap/_makenames/android_arm64_armv8-a/_makenames" ], "ExtraItems": [ "out/bazel-bin/external/libcap/_makenames" ] }, { "Name": "LOCAL_SOONG_UNSTRIPPED_BINARY", "MissingItems": [ "out/soong/.intermediates/external/libcap/_makenames/android_arm64_armv8-a/unstripped/_makenames" ], "ExtraItems": [ "out/bazel-bin/external/libcap/_makenames_unstripped" ] } ] }, ... ] } ``` Use JSON query tool like [`jq`](https://github.com/stedolan/jq) to slice and dice it.