blob: 81010f323a63ca45a0463a6927065a25d1650232 [file] [log] [blame]
Jeff Gastonef633e02017-10-10 13:20:31 -07001#!/bin/bash -eu
2#
3# Copyright 2017 Google Inc. All rights reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17set -e
18
19# This file makes it easy to confirm that a set of changes in source code don't result in any
20# changes to the generated ninja files. This is to reduce the effort required to be confident
21# in the correctness of refactorings
22
23function die() {
24 echo "$@" >&2
25 exit 1
26}
27
28function usage() {
29 violation="$1"
30 die "$violation
31
32 Usage: diff_build_graphs.sh [--products=product1,product2...] <OLD_VERSIONS> <NEW_VERSIONS>
33
34 This file builds and parses the build files (Android.mk, Android.bp, etc) for each requested
35 product and for both sets of versions, and checks whether the ninja files (which implement
36 the build graph) changed between the two versions.
37
38 Example: diff_build_graphs.sh 'build/soong:work^ build/blueprint:work^' 'build/soong:work build/blueprint:work'
39
40 Options:
41 --products=PRODUCTS comma-separated list of products to check"
42}
43
44PRODUCTS_ARG=""
45OLD_VERSIONS=""
46NEW_VERSIONS=""
47function parse_args() {
48 # parse optional arguments
49 while true; do
50 arg="${1-}"
51 case "$arg" in
52 --products=*) PRODUCTS_ARG="$arg";;
53 *) break;;
54 esac
55 shift
56 done
57 # parse required arguments
58 if [ "$#" != "2" ]; then
59 usage ""
60 fi
61 #argument validation
62 OLD_VERSIONS="$1"
63 NEW_VERSIONS="$2"
64
65}
66parse_args "$@"
67
68
69# find some file paths
70cd "$(dirname $0)"
71SCRIPT_DIR="$PWD"
72cd ../../..
73CHECKOUT_ROOT="$PWD"
74OUT_DIR="${OUT_DIR-}"
75if [ -z "$OUT_DIR" ]; then
76 OUT_DIR=out
77fi
78WORK_DIR="$OUT_DIR/diff"
79OUT_DIR_OLD="$WORK_DIR/out_old"
80OUT_DIR_NEW="$WORK_DIR/out_new"
81OUT_DIR_TEMP="$WORK_DIR/out_temp"
82
83
84function checkout() {
85 versionSpecs="$1"
86 for versionSpec in $versionSpecs; do
87 project="$(echo $versionSpec | sed 's|\([^:]*\):\([^:]*\)|\1|')"
88 ref="$(echo $versionSpec | sed 's|\([^:]*\):\([^:]*\)|\2|')"
89 echo "checking out ref $ref in project $project"
90 git -C "$project" checkout "$ref"
91 done
92}
93
94function run_build() {
95 echo
96 echo "Starting build"
97 # rebuild multiproduct_kati, in case it was missing before,
98 # or in case it is affected by some of the changes we're testing
99 make blueprint_tools
100 # find multiproduct_kati and have it build the ninja files for each product
101 builder="$(echo $OUT_DIR/soong/host/*/bin/multiproduct_kati)"
102 BUILD_NUMBER=sample "$builder" $PRODUCTS_ARG --keep --out "$OUT_DIR_TEMP" || true
103 echo
104}
105
106function diffProduct() {
107 product="$1"
108
109 zip1="$OUT_DIR_OLD/${product}.zip"
110 unzipped1="$OUT_DIR_OLD/$product"
111
112 zip2="$OUT_DIR_NEW/${product}.zip"
113 unzipped2="$OUT_DIR_NEW/$product"
114
115 unzip -qq "$zip1" -d "$unzipped1"
116 unzip -qq "$zip2" -d "$unzipped2"
117
118 #do a diff of the ninja files
119 diffFile="$WORK_DIR/diff.txt"
120 diff -r "$unzipped1" "$unzipped2" -x build_date.txt -x build_number.txt -x '\.*' -x '*.log' -x build_fingerprint.txt -x build.ninja.d -x '*.zip' > $diffFile || true
121 if [[ -s "$diffFile" ]]; then
122 # outputs are different, so remove the unzipped versions but keep the zipped versions
Jeff Gaston0c573d32017-11-28 16:58:37 -0800123 echo "First few differences (total diff linecount=$(wc -l $diffFile)) for product $product:"
Jeff Gastonef633e02017-10-10 13:20:31 -0700124 cat "$diffFile" | head -n 10
125 echo "End of differences for product $product"
126 rm -rf "$unzipped1" "$unzipped2"
127 else
128 # outputs are the same, so remove all of the outputs
129 rm -rf "$zip1" "$unzipped1" "$zip2" "$unzipped2"
130 fi
131}
132
133function do_builds() {
134 #reset work dir
135 rm -rf "$WORK_DIR"
136 mkdir "$WORK_DIR"
137
138 #build new code
139 checkout "$NEW_VERSIONS"
140 run_build
141 mv "$OUT_DIR_TEMP" "$OUT_DIR_NEW"
142
143 #build old code
144 #TODO do we want to cache old results? Maybe by the time we care to cache old results this will
145 #be running on a remote server somewhere and be completely different
146 checkout "$OLD_VERSIONS"
147 run_build
148 mv "$OUT_DIR_TEMP" "$OUT_DIR_OLD"
149
150 #cleanup
151 echo created "$OUT_DIR_OLD" and "$OUT_DIR_NEW"
152}
153
154function main() {
155 do_builds
156 checkout "$NEW_VERSIONS"
157
158 #find all products
159 productsFile="$WORK_DIR/all_products.txt"
160 find $OUT_DIR_OLD $OUT_DIR_NEW -mindepth 1 -maxdepth 1 -name "*.zip" | sed "s|^$OUT_DIR_OLD/||" | sed "s|^$OUT_DIR_NEW/||" | sed "s|\.zip$||" | sort | uniq > "$productsFile"
161 echo Diffing products
162 for product in $(cat $productsFile); do
163 diffProduct "$product"
164 done
165 echo Done diffing products
166 echo "Any differing outputs can be seen at $OUT_DIR_OLD/*.zip and $OUT_DIR_NEW/*.zip"
167 echo "See $WORK_DIR/diff.txt for the full list of differences for the latest product checked"
168}
169
170main