xref: /OK3568_Linux_fs/yocto/poky/scripts/sstate-diff-machines.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun#
3*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only
4*4882a593Smuzhiyun#
5*4882a593Smuzhiyun# Used to compare sstate checksums between MACHINES.
6*4882a593Smuzhiyun# Execute script and compare generated list.M files.
7*4882a593Smuzhiyun# Using bash to have PIPESTATUS variable.
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun# It's also usefull to keep older sstate checksums
10*4882a593Smuzhiyun# to be able to find out why something is rebuilding
11*4882a593Smuzhiyun# after updating metadata
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun# $ diff \
14*4882a593Smuzhiyun#     sstate-diff/1349348392/fake-cortexa8/list.M \
15*4882a593Smuzhiyun#     sstate-diff/1349348392/fake-cortexa9/list.M \
16*4882a593Smuzhiyun#     | wc -l
17*4882a593Smuzhiyun# 538
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun# Then to compare sigdata use something like:
20*4882a593Smuzhiyun# $ ls sstate-diff/1349348392/*/armv7a-vfp-neon*/linux-libc-headers/*do_configure*sigdata*
21*4882a593Smuzhiyun#   sstate-diff/1349348392/fake-cortexa8/armv7a-vfp-neon-oe-linux-gnueabi/linux-libc-headers/3.4.3-r0.do_configure.sigdata.cb73b3630a7b8191e72fc469c5137025
22*4882a593Smuzhiyun#   sstate-diff/1349348392/fake-cortexa9/armv7a-vfp-neon-oe-linux-gnueabi/linux-libc-headers/3.4.3-r0.do_configure.sigdata.f37ada177bf99ce8af85914df22b5a0b
23*4882a593Smuzhiyun# $ bitbake-diffsigs stamps.1349348392/*/armv7a-vfp-neon*/linux-libc-headers/*do_configure*sigdata*
24*4882a593Smuzhiyun#   basehash changed from 8d0bd67bb1da6f68717760fc3ef43171 to e869fa61426e88e9c30726ba88a1216a
25*4882a593Smuzhiyun#   Variable TUNE_CCARGS value changed from  -march=armv7-a     -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8 to  -march=armv7-a     -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a9
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun# Global vars
28*4882a593Smuzhiyuntmpdir=
29*4882a593Smuzhiyunmachines=
30*4882a593Smuzhiyuntargets=
31*4882a593Smuzhiyundefault_machines="qemuarm qemux86 qemux86-64"
32*4882a593Smuzhiyundefault_targets="core-image-base"
33*4882a593Smuzhiyunanalyze="N"
34*4882a593Smuzhiyun
35*4882a593Smuzhiyunusage () {
36*4882a593Smuzhiyun  cat << EOF
37*4882a593SmuzhiyunWelcome to utility to compare sstate checksums between different MACHINEs.
38*4882a593Smuzhiyun$0 <OPTION>
39*4882a593Smuzhiyun
40*4882a593SmuzhiyunOptions:
41*4882a593Smuzhiyun  -h, --help
42*4882a593Smuzhiyun        Display this help and exit.
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun  --tmpdir=<tmpdir>
45*4882a593Smuzhiyun        Specify tmpdir, will use the environment variable TMPDIR if it is not specified.
46*4882a593Smuzhiyun        Something like /OE/oe-core/tmp-eglibc (no / at the end).
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun  --machines=<machines>
49*4882a593Smuzhiyun        List of MACHINEs separated by space, will use the environment variable MACHINES if it is not specified.
50*4882a593Smuzhiyun        Default value is "qemuarm qemux86 qemux86-64".
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun  --targets=<targets>
53*4882a593Smuzhiyun        List of targets separated by space, will use the environment variable TARGETS if it is not specified.
54*4882a593Smuzhiyun        Default value is "core-image-base".
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun  --analyze
57*4882a593Smuzhiyun        Show the differences between MACHINEs. It assumes:
58*4882a593Smuzhiyun        * First 2 MACHINEs in --machines parameter have the same TUNE_PKGARCH
59*4882a593Smuzhiyun        * Third optional MACHINE has different TUNE_PKGARCH - only native and allarch recipes are compared).
60*4882a593Smuzhiyun        * Next MACHINEs are ignored
61*4882a593SmuzhiyunEOF
62*4882a593Smuzhiyun}
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun# Print error information and exit.
65*4882a593Smuzhiyunecho_error () {
66*4882a593Smuzhiyun  echo "ERROR: $1" >&2
67*4882a593Smuzhiyun  exit 1
68*4882a593Smuzhiyun}
69*4882a593Smuzhiyun
70*4882a593Smuzhiyunwhile [ -n "$1" ]; do
71*4882a593Smuzhiyun  case $1 in
72*4882a593Smuzhiyun    --tmpdir=*)
73*4882a593Smuzhiyun      tmpdir=`echo $1 | sed -e 's#^--tmpdir=##' | xargs readlink -e`
74*4882a593Smuzhiyun      [ -d "$tmpdir" ] || echo_error "Invalid argument to --tmpdir"
75*4882a593Smuzhiyun      shift
76*4882a593Smuzhiyun        ;;
77*4882a593Smuzhiyun    --machines=*)
78*4882a593Smuzhiyun      machines=`echo $1 | sed -e 's#^--machines="*\([^"]*\)"*#\1#'`
79*4882a593Smuzhiyun      shift
80*4882a593Smuzhiyun        ;;
81*4882a593Smuzhiyun    --targets=*)
82*4882a593Smuzhiyun      targets=`echo $1 | sed -e 's#^--targets="*\([^"]*\)"*#\1#'`
83*4882a593Smuzhiyun      shift
84*4882a593Smuzhiyun        ;;
85*4882a593Smuzhiyun    --analyze)
86*4882a593Smuzhiyun      analyze="Y"
87*4882a593Smuzhiyun      shift
88*4882a593Smuzhiyun        ;;
89*4882a593Smuzhiyun    --help|-h)
90*4882a593Smuzhiyun      usage
91*4882a593Smuzhiyun      exit 0
92*4882a593Smuzhiyun        ;;
93*4882a593Smuzhiyun    *)
94*4882a593Smuzhiyun      echo "Invalid arguments $*"
95*4882a593Smuzhiyun      echo_error "Try '$0 -h' for more information."
96*4882a593Smuzhiyun        ;;
97*4882a593Smuzhiyun  esac
98*4882a593Smuzhiyundone
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun# tmpdir directory, use environment variable TMPDIR
101*4882a593Smuzhiyun# if it was not specified, otherwise, error.
102*4882a593Smuzhiyun[ -n "$tmpdir" ] || tmpdir=$TMPDIR
103*4882a593Smuzhiyun[ -n "$tmpdir" ] || echo_error "No tmpdir found!"
104*4882a593Smuzhiyun[ -d "$tmpdir" ] || echo_error "Invalid tmpdir \"$tmpdir\""
105*4882a593Smuzhiyun[ -n "$machines" ] || machines=$MACHINES
106*4882a593Smuzhiyun[ -n "$machines" ] || machines=$default_machines
107*4882a593Smuzhiyun[ -n "$targets" ] || targets=$TARGETS
108*4882a593Smuzhiyun[ -n "$targets" ] || targets=$default_targets
109*4882a593Smuzhiyun
110*4882a593SmuzhiyunOUTPUT=${tmpdir}/sstate-diff/`date "+%s"`
111*4882a593Smuzhiyundeclare -i RESULT=0
112*4882a593Smuzhiyun
113*4882a593Smuzhiyunfor M in ${machines}; do
114*4882a593Smuzhiyun  [ -d ${tmpdir}/stamps/ ] && find ${tmpdir}/stamps/ -name \*sigdata\* | xargs rm -f
115*4882a593Smuzhiyun  mkdir -p ${OUTPUT}/${M}
116*4882a593Smuzhiyun  export MACHINE=${M}
117*4882a593Smuzhiyun  bitbake -S none ${targets} 2>&1 | tee -a ${OUTPUT}/${M}/log;
118*4882a593Smuzhiyun  RESULT+=${PIPESTATUS[0]}
119*4882a593Smuzhiyun  if ls ${tmpdir}/stamps/* >/dev/null 2>/dev/null ; then
120*4882a593Smuzhiyun    cp -ra ${tmpdir}/stamps/* ${OUTPUT}/${M}
121*4882a593Smuzhiyun    find ${OUTPUT}/${M} -name \*sigdata\* | sed "s#${OUTPUT}/${M}/##g" | sort > ${OUTPUT}/${M}/list
122*4882a593Smuzhiyun    M_UNDERSCORE=`echo ${M} | sed 's/-/_/g'`
123*4882a593Smuzhiyun    sed "s/^${M_UNDERSCORE}-/MACHINE/g" ${OUTPUT}/${M}/list | sort > ${OUTPUT}/${M}/list.M
124*4882a593Smuzhiyun    find ${tmpdir}/stamps/ -name \*sigdata\* | xargs rm -f
125*4882a593Smuzhiyun  else
126*4882a593Smuzhiyun    printf "ERROR: no sigdata files were generated for MACHINE $M in ${tmpdir}/stamps\n";
127*4882a593Smuzhiyun  fi
128*4882a593Smuzhiyundone
129*4882a593Smuzhiyun
130*4882a593SmuzhiyunCOMPARE_TASKS="do_configure.sigdata do_populate_sysroot.sigdata do_package_write_ipk.sigdata do_package_write_rpm.sigdata do_package_write_deb.sigdata do_package_write_tar.sigdata"
131*4882a593Smuzhiyun
132*4882a593Smuzhiyunfunction compareSignatures() {
133*4882a593Smuzhiyun  MACHINE1=$1
134*4882a593Smuzhiyun  MACHINE2=$2
135*4882a593Smuzhiyun  PATTERN="$3"
136*4882a593Smuzhiyun  PRE_PATTERN=""
137*4882a593Smuzhiyun  [ -n "${PATTERN}" ] || PRE_PATTERN="-v"
138*4882a593Smuzhiyun  [ -n "${PATTERN}" ] || PATTERN="MACHINE"
139*4882a593Smuzhiyun  for TASK in $COMPARE_TASKS; do
140*4882a593Smuzhiyun    printf "\n\n === Comparing signatures for task ${TASK} between ${MACHINE1} and ${MACHINE2} ===\n" | tee -a ${OUTPUT}/signatures.${MACHINE2}.${TASK}.log
141*4882a593Smuzhiyun    diff ${OUTPUT}/${MACHINE1}/list.M ${OUTPUT}/${MACHINE2}/list.M | grep ${PRE_PATTERN} "${PATTERN}" | grep ${TASK} > ${OUTPUT}/signatures.${MACHINE2}.${TASK}
142*4882a593Smuzhiyun    for i in `cat ${OUTPUT}/signatures.${MACHINE2}.${TASK} | sed 's#[^/]*/\([^/]*\)/.*#\1#g' | sort -u | xargs`; do
143*4882a593Smuzhiyun      [ -e ${OUTPUT}/${MACHINE1}/*/$i/*${TASK}* ] || echo "INFO: ${i} task ${TASK} doesn't exist in ${MACHINE1}" >&2
144*4882a593Smuzhiyun      [ -e ${OUTPUT}/${MACHINE1}/*/$i/*${TASK}* ] || continue
145*4882a593Smuzhiyun      [ -e ${OUTPUT}/${MACHINE2}/*/$i/*${TASK}* ] || echo "INFO: ${i} task ${TASK} doesn't exist in ${MACHINE2}" >&2
146*4882a593Smuzhiyun      [ -e ${OUTPUT}/${MACHINE2}/*/$i/*${TASK}* ] || continue
147*4882a593Smuzhiyun      printf "ERROR: $i different signature for task ${TASK} between ${MACHINE1} and ${MACHINE2}\n";
148*4882a593Smuzhiyun      bitbake-diffsigs ${OUTPUT}/${MACHINE1}/*/$i/*${TASK}* ${OUTPUT}/${MACHINE2}/*/$i/*${TASK}*;
149*4882a593Smuzhiyun      echo "$i" >> ${OUTPUT}/failed-recipes.log
150*4882a593Smuzhiyun      echo
151*4882a593Smuzhiyun    done | tee -a ${OUTPUT}/signatures.${MACHINE2}.${TASK}.log
152*4882a593Smuzhiyun    # don't create empty files
153*4882a593Smuzhiyun    ERRORS=`grep "^ERROR.*" ${OUTPUT}/signatures.${MACHINE2}.${TASK}.log | wc -l`
154*4882a593Smuzhiyun    if [ "${ERRORS}" != "0" ] ; then
155*4882a593Smuzhiyun      echo "ERROR: ${ERRORS} errors found in ${OUTPUT}/signatures.${MACHINE2}.${TASK}.log"
156*4882a593Smuzhiyun      RESULT+=${ERRORS}
157*4882a593Smuzhiyun    fi
158*4882a593Smuzhiyun  done
159*4882a593Smuzhiyun}
160*4882a593Smuzhiyun
161*4882a593Smuzhiyunfunction compareMachines() {
162*4882a593Smuzhiyun  [ "$#" -ge 2 ] && compareSignatures $1 $2
163*4882a593Smuzhiyun  [ "$#" -ge 3 ] && compareSignatures $1 $3 "\(^< all\)\|\(^< x86_64-linux\)\|\(^< i586-linux\)"
164*4882a593Smuzhiyun}
165*4882a593Smuzhiyun
166*4882a593Smuzhiyunif [ "${analyze}" = "Y" ] ; then
167*4882a593Smuzhiyun  compareMachines ${machines}
168*4882a593Smuzhiyunfi
169*4882a593Smuzhiyun
170*4882a593Smuzhiyunif [ "${RESULT}" != "0" -a -f ${OUTPUT}/failed-recipes.log ] ; then
171*4882a593Smuzhiyun  cat ${OUTPUT}/failed-recipes.log | sort -u >${OUTPUT}/failed-recipes.log.u && mv ${OUTPUT}/failed-recipes.log.u ${OUTPUT}/failed-recipes.log
172*4882a593Smuzhiyun  echo "ERROR: ${RESULT} issues were found in these recipes: `cat ${OUTPUT}/failed-recipes.log | xargs`"
173*4882a593Smuzhiyunfi
174*4882a593Smuzhiyun
175*4882a593Smuzhiyunecho "INFO: Output written in: ${OUTPUT}"
176*4882a593Smuzhiyunexit ${RESULT}
177