1#! /bin/bash -eu 2 3# Run CKati step separately, tracing given Makefile variables. 4# It is expected that the regular Android null build (`m nothing`) 5# has been run so that $OUT_DIR/soong/Android-${TARGET_PRODUCT}.mk, 6# $OUT_DIR/soong/make_vars-${TARGET_PRODUCT}.mk, etc. files exist. 7# 8# The output file is in JSON format and can be processed with, say, 9# `jq`. For instance, the following invocation outputs all assignment 10# traces concisely: 11# jq -c '.assignments[] | (select (.operation == "assign")) | {("n"): .name, ("l"): .value_stack[0]?, ("v"): .value }' out/ckati.trace 12# generates 13# {"n":"<var1>","l":"<file>:<line>","v":"<value1>"} 14# ... 15 16function die() { format=$1; shift; printf "$format\n" $@; exit 1; } 17function usage() { die "Usage: %s [-o FILE] VAR ...\n(without -o the output goes to ${outfile})" ${0##*/}; } 18 19[[ -d build/soong ]] || die "run this script from the top of the Android source tree" 20declare -r out=${OUT_DIR:-out} 21[[ -x ${out}/soong_ui ]] || die "run Android build first" 22: ${TARGET_PRODUCT:?not set, run lunch?} 23: ${TARGET_BUILD_VARIANT:?not set, run lunch?} 24declare -r androidmk=${out}/soong/Android-${TARGET_PRODUCT}.mk 25declare -r makevarsmk=${out}/soong/make_vars-${TARGET_PRODUCT}.mk 26declare -r target_device_dir=$(${out}/soong_ui --dumpvar-mode TARGET_DEVICE_DIR) 27: ${target_device_dir:?cannot find device directory for ${TARGET_PRODUCT}} 28declare -r target_device=$(${out}/soong_ui --dumpvar-mode TARGET_DEVICE) 29: ${target_device:?cannot find target device for ${TARGET_PRODUCT}} 30declare -r timestamp_file=${out}/build_date.txt 31# Files should exist, so ls should succeed: 32ls -1d "$androidmk" "$makevarsmk" "$target_device_dir" "$timestamp_file" >/dev/null 33 34outfile=${out}/ckati.trace 35while getopts "ho:" opt; do 36 case $opt in 37 h) usage ;; 38 o) outfile=$OPTARG ;; 39 ?) usage ;; 40 esac 41done 42 43if (($#>0)); then 44 declare -a tracing=(--variable_assignment_trace_filter="$*" --dump_variable_assignment_trace "$outfile") 45else 46 printf "running ckati without tracing variables\n" 47fi 48 49# Touch one input for ckati, otherwise it will just print 50# 'No need to regenerate ninja file' and exit. 51touch "$androidmk" 52prebuilts/build-tools/linux-x86/bin/ckati \ 53 --gen_all_targets \ 54 -i \ 55 --ignore_optional_include=out/%.P \ 56 --ninja \ 57 --ninja_dir=out \ 58 --ninja_suffix=-${TARGET_PRODUCT} \ 59 --no_builtin_rules \ 60 --no_ninja_prelude \ 61 --regen \ 62 --top_level_phony \ 63 --use_find_emulator \ 64 --use_ninja_phony_output \ 65 --use_ninja_symlink_outputs \ 66 --werror_find_emulator \ 67 --werror_implicit_rules \ 68 --werror_overriding_commands \ 69 --werror_phony_looks_real \ 70 --werror_real_to_phony \ 71 --werror_suffix_rules \ 72 --werror_writable \ 73 --writable out/ \ 74 -f build/make/core/main.mk \ 75 "${tracing[@]}" \ 76 ANDROID_JAVA_HOME=prebuilts/jdk/jdk21/linux-x86 \ 77 ASAN_SYMBOLIZER_PATH=$PWD/prebuilts/clang/host/linux-x86/llvm-binutils-stable/llvm-symbolizer \ 78 BUILD_DATETIME_FILE="$timestamp_file" \ 79 BUILD_HOSTNAME=$(hostname) \ 80 BUILD_USERNAME="$USER" \ 81 JAVA_HOME=$PWD/prebuilts/jdk/jdk21/linux-x86 \ 82 KATI_PACKAGE_MK_DIR="{$out}/target/product/${target_device}/CONFIG/kati_packaging" \ 83 OUT_DIR="$out" \ 84 PATH="$PWD/prebuilts/build-tools/path/linux-x86:$PWD/${out}/.path" \ 85 PYTHONDONTWRITEBYTECODE=1 \ 86 SOONG_ANDROID_MK="$androidmk" \ 87 SOONG_MAKEVARS_MK="$makevarsmk" \ 88 TARGET_BUILD_VARIANT="$TARGET_BUILD_VARIANT" \ 89 TARGET_DEVICE_DIR="$target_device_dir" \ 90 TARGET_PRODUCT=${TARGET_PRODUCT} \ 91 TMPDIR="$PWD/$out/soong/.temp" 92