1*333d2b36SAndroid Build Coastguard Worker#!/bin/bash 2*333d2b36SAndroid Build Coastguard Worker 3*333d2b36SAndroid Build Coastguard Workerset -eu 4*333d2b36SAndroid Build Coastguard Worker 5*333d2b36SAndroid Build Coastguard Worker# Copyright 2020 Google Inc. All rights reserved. 6*333d2b36SAndroid Build Coastguard Worker# 7*333d2b36SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 8*333d2b36SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 9*333d2b36SAndroid Build Coastguard Worker# You may obtain a copy of the License at 10*333d2b36SAndroid Build Coastguard Worker# 11*333d2b36SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 12*333d2b36SAndroid Build Coastguard Worker# 13*333d2b36SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 14*333d2b36SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 15*333d2b36SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16*333d2b36SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 17*333d2b36SAndroid Build Coastguard Worker# limitations under the License. 18*333d2b36SAndroid Build Coastguard Worker 19*333d2b36SAndroid Build Coastguard Worker# Tool to evaluate the transitive closure of the ninja dependency graph of the 20*333d2b36SAndroid Build Coastguard Worker# files and targets a given target depends on. 21*333d2b36SAndroid Build Coastguard Worker# 22*333d2b36SAndroid Build Coastguard Worker# i.e. the list of things that, if changed, could cause a change to a target. 23*333d2b36SAndroid Build Coastguard Worker 24*333d2b36SAndroid Build Coastguard Workerreadonly me=$(basename "${0}") 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Workerreadonly usage="usage: ${me} {options} target [target...] 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard WorkerEvaluate the transitive closure of files and ninja targets that one or more 29*333d2b36SAndroid Build Coastguard Workertargets depend on. 30*333d2b36SAndroid Build Coastguard Worker 31*333d2b36SAndroid Build Coastguard WorkerDependency Options: 32*333d2b36SAndroid Build Coastguard Worker 33*333d2b36SAndroid Build Coastguard Worker -(no)order_deps Whether to include order-only dependencies. (Default false) 34*333d2b36SAndroid Build Coastguard Worker -(no)implicit Whether to include implicit dependencies. (Default true) 35*333d2b36SAndroid Build Coastguard Worker -(no)explicit Whether to include regular / explicit deps. (Default true) 36*333d2b36SAndroid Build Coastguard Worker 37*333d2b36SAndroid Build Coastguard Worker -nofollow Unanchored regular expression. Matching paths and targets 38*333d2b36SAndroid Build Coastguard Worker always get reported. Their dependencies do not get reported 39*333d2b36SAndroid Build Coastguard Worker unless first encountered in a 'container' file type. 40*333d2b36SAndroid Build Coastguard Worker Multiple allowed and combined using '|'. 41*333d2b36SAndroid Build Coastguard Worker e.g. -nofollow='*.so' not -nofollow='.so$' 42*333d2b36SAndroid Build Coastguard Worker -nofollow='*.so|*.dex' or -nofollow='*.so' -nofollow='.dex' 43*333d2b36SAndroid Build Coastguard Worker (Defaults to no matches) 44*333d2b36SAndroid Build Coastguard Worker -container Unanchored regular expression. Matching file extensions get 45*333d2b36SAndroid Build Coastguard Worker treated as 'container' files for -nofollow option. 46*333d2b36SAndroid Build Coastguard Worker Multiple allowed and combines using '|' 47*333d2b36SAndroid Build Coastguard Worker (Default 'apex|apk|zip|jar|tar|tgz') 48*333d2b36SAndroid Build Coastguard Worker 49*333d2b36SAndroid Build Coastguard WorkerOutput Options: 50*333d2b36SAndroid Build Coastguard Worker 51*333d2b36SAndroid Build Coastguard Worker -(no)quiet Suppresses progress output to stderr and interactive 52*333d2b36SAndroid Build Coastguard Worker alias -(no)q prompts. By default, when stderr is a tty, progress gets 53*333d2b36SAndroid Build Coastguard Worker reported to stderr; when both stderr and stdin are tty, 54*333d2b36SAndroid Build Coastguard Worker the script asks user whether to delete intermediate files. 55*333d2b36SAndroid Build Coastguard Worker When suppressed or not prompted, script always deletes the 56*333d2b36SAndroid Build Coastguard Worker temporary / intermediate files. 57*333d2b36SAndroid Build Coastguard Worker -sep=<delim> Use 'delim' as output field separator between notice 58*333d2b36SAndroid Build Coastguard Worker checksum and notice filename in notice output. 59*333d2b36SAndroid Build Coastguard Worker e.g. sep='\\t' 60*333d2b36SAndroid Build Coastguard Worker (Default space) 61*333d2b36SAndroid Build Coastguard Worker -csv Shorthand for -sep=',' 62*333d2b36SAndroid Build Coastguard Worker -directories=<f> Output directory names of dependencies to 'f'. 63*333d2b36SAndroid Build Coastguard Worker alias -d User '/dev/stdout' to send directories to stdout. Defaults 64*333d2b36SAndroid Build Coastguard Worker to no directory output. 65*333d2b36SAndroid Build Coastguard Worker -notices=<file> Output license and notice file paths to 'file'. 66*333d2b36SAndroid Build Coastguard Worker alias -n Use '/dev/stdout' to send notices to stdout. Defaults to no 67*333d2b36SAndroid Build Coastguard Worker license/notice output. 68*333d2b36SAndroid Build Coastguard Worker -projects=<file> Output git project names to 'file'. Use '/dev/stdout' to 69*333d2b36SAndroid Build Coastguard Worker alias -p send projects to stdout. Defaults to no project output. 70*333d2b36SAndroid Build Coastguard Worker -targets=<fils> Output target dependencies to 'file'. Use '/dev/stdout' to 71*333d2b36SAndroid Build Coastguard Worker alias -t send targets to stdout. 72*333d2b36SAndroid Build Coastguard Worker When no directory, notice, project or target output options 73*333d2b36SAndroid Build Coastguard Worker given, defaults to stdout. Otherwise, defaults to no target 74*333d2b36SAndroid Build Coastguard Worker output. 75*333d2b36SAndroid Build Coastguard Worker 76*333d2b36SAndroid Build Coastguard WorkerAt minimum, before running this script, you must first run: 77*333d2b36SAndroid Build Coastguard Worker$ source build/envsetup.sh 78*333d2b36SAndroid Build Coastguard Worker$ lunch 79*333d2b36SAndroid Build Coastguard Worker$ m nothing 80*333d2b36SAndroid Build Coastguard Workerto setup the build environment, choose a target platform, and build the ninja 81*333d2b36SAndroid Build Coastguard Workerdependency graph. 82*333d2b36SAndroid Build Coastguard Worker" 83*333d2b36SAndroid Build Coastguard Worker 84*333d2b36SAndroid Build Coastguard Workerfunction die() { echo -e "${*}" >&2; exit 2; } 85*333d2b36SAndroid Build Coastguard Worker 86*333d2b36SAndroid Build Coastguard Worker# Reads one input target per line from stdin; outputs (isnotice target) tuples. 87*333d2b36SAndroid Build Coastguard Worker# 88*333d2b36SAndroid Build Coastguard Worker# output target is a ninja target that the input target depends on 89*333d2b36SAndroid Build Coastguard Worker# isnotice in {0,1} with 1 for output targets believed to be license or notice 90*333d2b36SAndroid Build Coastguard Workerfunction getDeps() { 91*333d2b36SAndroid Build Coastguard Worker (tr '\n' '\0' | xargs -0 -r "${ninja_bin}" -f "${ninja_file}" -t query) \ 92*333d2b36SAndroid Build Coastguard Worker | awk -v include_order="${include_order_deps}" \ 93*333d2b36SAndroid Build Coastguard Worker -v include_implicit="${include_implicit_deps}" \ 94*333d2b36SAndroid Build Coastguard Worker -v include_explicit="${include_deps}" \ 95*333d2b36SAndroid Build Coastguard Worker -v containers="${container_types}" \ 96*333d2b36SAndroid Build Coastguard Worker ' 97*333d2b36SAndroid Build Coastguard Worker BEGIN { 98*333d2b36SAndroid Build Coastguard Worker ininput = 0 99*333d2b36SAndroid Build Coastguard Worker isnotice = 0 100*333d2b36SAndroid Build Coastguard Worker currFileName = "" 101*333d2b36SAndroid Build Coastguard Worker currExt = "" 102*333d2b36SAndroid Build Coastguard Worker } 103*333d2b36SAndroid Build Coastguard Worker $1 == "outputs:" || $1 == "validations:" { 104*333d2b36SAndroid Build Coastguard Worker ininput = 0 105*333d2b36SAndroid Build Coastguard Worker } 106*333d2b36SAndroid Build Coastguard Worker ininput == 0 && $0 ~ /^\S\S*:$/ { 107*333d2b36SAndroid Build Coastguard Worker isnotice = ($0 ~ /.*NOTICE.*[.]txt:$/) 108*333d2b36SAndroid Build Coastguard Worker currFileName = gensub(/^.*[/]([^/]*)[:]$/, "\\1", "g") 109*333d2b36SAndroid Build Coastguard Worker currExt = gensub(/^.*[.]([^./]*)[:]$/, "\\1", "g") 110*333d2b36SAndroid Build Coastguard Worker } 111*333d2b36SAndroid Build Coastguard Worker ininput != 0 && $1 !~ /^[|][|]?/ { 112*333d2b36SAndroid Build Coastguard Worker if (include_explicit == "true") { 113*333d2b36SAndroid Build Coastguard Worker fileName = gensub(/^.*[/]([^/]*)$/, "\\1", "g") 114*333d2b36SAndroid Build Coastguard Worker print ( \ 115*333d2b36SAndroid Build Coastguard Worker (isnotice && $0 !~ /^\s*build[/]soong[/]scripts[/]/) \ 116*333d2b36SAndroid Build Coastguard Worker || $0 ~ /NOTICE|LICEN[CS]E/ \ 117*333d2b36SAndroid Build Coastguard Worker || $0 ~ /(notice|licen[cs]e)[.]txt/ \ 118*333d2b36SAndroid Build Coastguard Worker )" "(fileName == currFileName||currExt ~ "^(" containers ")$")" "gensub(/^\s*/, "", "g") 119*333d2b36SAndroid Build Coastguard Worker } 120*333d2b36SAndroid Build Coastguard Worker } 121*333d2b36SAndroid Build Coastguard Worker ininput != 0 && $1 == "|" { 122*333d2b36SAndroid Build Coastguard Worker if (include_implicit == "true") { 123*333d2b36SAndroid Build Coastguard Worker fileName = gensub(/^.*[/]([^/]*)$/, "\\1", "g") 124*333d2b36SAndroid Build Coastguard Worker $1 = "" 125*333d2b36SAndroid Build Coastguard Worker print ( \ 126*333d2b36SAndroid Build Coastguard Worker (isnotice && $0 !~ /^\s*build[/]soong[/]scripts[/]/) \ 127*333d2b36SAndroid Build Coastguard Worker || $0 ~ /NOTICE|LICEN[CS]E/ \ 128*333d2b36SAndroid Build Coastguard Worker || $0 ~ /(notice|licen[cs]e)[.]txt/ \ 129*333d2b36SAndroid Build Coastguard Worker )" "(fileName == currFileName||currExt ~ "^(" containers ")$")" "gensub(/^\s*/, "", "g") 130*333d2b36SAndroid Build Coastguard Worker } 131*333d2b36SAndroid Build Coastguard Worker } 132*333d2b36SAndroid Build Coastguard Worker ininput != 0 && $1 == "||" { 133*333d2b36SAndroid Build Coastguard Worker if (include_order == "true") { 134*333d2b36SAndroid Build Coastguard Worker fileName = gensub(/^.*[/]([^/]*)$/, "\\1", "g") 135*333d2b36SAndroid Build Coastguard Worker $1 = "" 136*333d2b36SAndroid Build Coastguard Worker print ( \ 137*333d2b36SAndroid Build Coastguard Worker (isnotice && $0 !~ /^\s*build[/]soong[/]scripts[/]/) \ 138*333d2b36SAndroid Build Coastguard Worker || $0 ~ /NOTICE|LICEN[CS]E/ \ 139*333d2b36SAndroid Build Coastguard Worker || $0 ~ /(notice|licen[cs]e)[.]txt/ \ 140*333d2b36SAndroid Build Coastguard Worker )" "(fileName == currFileName||currExt ~ "^(" containers ")$")" "gensub(/^\s*/, "", "g") 141*333d2b36SAndroid Build Coastguard Worker } 142*333d2b36SAndroid Build Coastguard Worker } 143*333d2b36SAndroid Build Coastguard Worker $1 == "input:" { 144*333d2b36SAndroid Build Coastguard Worker ininput = 1 145*333d2b36SAndroid Build Coastguard Worker } 146*333d2b36SAndroid Build Coastguard Worker ' 147*333d2b36SAndroid Build Coastguard Worker} 148*333d2b36SAndroid Build Coastguard Worker 149*333d2b36SAndroid Build Coastguard Worker# Reads one input directory per line from stdin; outputs unique git projects. 150*333d2b36SAndroid Build Coastguard Workerfunction getProjects() { 151*333d2b36SAndroid Build Coastguard Worker while read d; do 152*333d2b36SAndroid Build Coastguard Worker while [ "${d}" != '.' ] && [ "${d}" != '/' ]; do 153*333d2b36SAndroid Build Coastguard Worker if [ -d "${d}/.git/" ]; then 154*333d2b36SAndroid Build Coastguard Worker echo "${d}" 155*333d2b36SAndroid Build Coastguard Worker break 156*333d2b36SAndroid Build Coastguard Worker fi 157*333d2b36SAndroid Build Coastguard Worker d=$(dirname "${d}") 158*333d2b36SAndroid Build Coastguard Worker done 159*333d2b36SAndroid Build Coastguard Worker done | sort -u 160*333d2b36SAndroid Build Coastguard Worker} 161*333d2b36SAndroid Build Coastguard Worker 162*333d2b36SAndroid Build Coastguard Worker 163*333d2b36SAndroid Build Coastguard Workerif [ -z "${ANDROID_BUILD_TOP}" ]; then 164*333d2b36SAndroid Build Coastguard Worker die "${me}: Run 'lunch' to configure the build environment" 165*333d2b36SAndroid Build Coastguard Workerfi 166*333d2b36SAndroid Build Coastguard Worker 167*333d2b36SAndroid Build Coastguard Workerif [ -z "${TARGET_PRODUCT}" ]; then 168*333d2b36SAndroid Build Coastguard Worker die "${me}: Run 'lunch' to configure the build environment" 169*333d2b36SAndroid Build Coastguard Workerfi 170*333d2b36SAndroid Build Coastguard Worker 171*333d2b36SAndroid Build Coastguard Workerreadonly ninja_file="${ANDROID_BUILD_TOP}/out/combined-${TARGET_PRODUCT}.ninja" 172*333d2b36SAndroid Build Coastguard Workerif [ ! -f "${ninja_file}" ]; then 173*333d2b36SAndroid Build Coastguard Worker die "${me}: Run 'm nothing' to build the dependency graph" 174*333d2b36SAndroid Build Coastguard Workerfi 175*333d2b36SAndroid Build Coastguard Worker 176*333d2b36SAndroid Build Coastguard Workerreadonly ninja_bin="${ANDROID_BUILD_TOP}/prebuilts/build-tools/linux-x86/bin/ninja" 177*333d2b36SAndroid Build Coastguard Workerif [ ! -x "${ninja_bin}" ]; then 178*333d2b36SAndroid Build Coastguard Worker die "${me}: Cannot find ninja executable expected at ${ninja_bin}" 179*333d2b36SAndroid Build Coastguard Workerfi 180*333d2b36SAndroid Build Coastguard Worker 181*333d2b36SAndroid Build Coastguard Worker 182*333d2b36SAndroid Build Coastguard Worker# parse the command-line 183*333d2b36SAndroid Build Coastguard Worker 184*333d2b36SAndroid Build Coastguard Workerdeclare -a targets # one or more targets to evaluate 185*333d2b36SAndroid Build Coastguard Worker 186*333d2b36SAndroid Build Coastguard Workerinclude_order_deps=false # whether to trace through || "order dependencies" 187*333d2b36SAndroid Build Coastguard Workerinclude_implicit_deps=true # whether to trace through | "implicit deps" 188*333d2b36SAndroid Build Coastguard Workerinclude_deps=true # whether to trace through regular explicit deps 189*333d2b36SAndroid Build Coastguard Workerquiet=false # whether to suppress progress 190*333d2b36SAndroid Build Coastguard Worker 191*333d2b36SAndroid Build Coastguard Workerprojects_out='' # where to output the list of projects 192*333d2b36SAndroid Build Coastguard Workerdirectories_out='' # where to output the list of directories 193*333d2b36SAndroid Build Coastguard Workertargets_out='' # where to output the list of targets/source files 194*333d2b36SAndroid Build Coastguard Workernotices_out='' # where to output the list of license/notice files 195*333d2b36SAndroid Build Coastguard Worker 196*333d2b36SAndroid Build Coastguard Workersep=" " # separator between md5sum and notice filename 197*333d2b36SAndroid Build Coastguard Worker 198*333d2b36SAndroid Build Coastguard Workernofollow='' # regularexp must fully match targets to skip 199*333d2b36SAndroid Build Coastguard Worker 200*333d2b36SAndroid Build Coastguard Workercontainer_types='' # regularexp must full match file extension 201*333d2b36SAndroid Build Coastguard Worker # defaults to 'apex|apk|zip|jar|tar|tgz' below. 202*333d2b36SAndroid Build Coastguard Worker 203*333d2b36SAndroid Build Coastguard Workeruse_stdin=false # whether to read targets from stdin i.e. target - 204*333d2b36SAndroid Build Coastguard Worker 205*333d2b36SAndroid Build Coastguard Workerwhile [ $# -gt 0 ]; do 206*333d2b36SAndroid Build Coastguard Worker case "${1:-}" in 207*333d2b36SAndroid Build Coastguard Worker -) 208*333d2b36SAndroid Build Coastguard Worker use_stdin=true 209*333d2b36SAndroid Build Coastguard Worker ;; 210*333d2b36SAndroid Build Coastguard Worker -*) 211*333d2b36SAndroid Build Coastguard Worker flag=$(expr "${1}" : '^-*\(.*\)$') 212*333d2b36SAndroid Build Coastguard Worker case "${flag:-}" in 213*333d2b36SAndroid Build Coastguard Worker order_deps) 214*333d2b36SAndroid Build Coastguard Worker include_order_deps=true;; 215*333d2b36SAndroid Build Coastguard Worker noorder_deps) 216*333d2b36SAndroid Build Coastguard Worker include_order_deps=false;; 217*333d2b36SAndroid Build Coastguard Worker implicit) 218*333d2b36SAndroid Build Coastguard Worker include_implicit_deps=true;; 219*333d2b36SAndroid Build Coastguard Worker noimplicit) 220*333d2b36SAndroid Build Coastguard Worker include_implicit_deps=false;; 221*333d2b36SAndroid Build Coastguard Worker explicit) 222*333d2b36SAndroid Build Coastguard Worker include_deps=true;; 223*333d2b36SAndroid Build Coastguard Worker noexplicit) 224*333d2b36SAndroid Build Coastguard Worker include_deps=false;; 225*333d2b36SAndroid Build Coastguard Worker csv) 226*333d2b36SAndroid Build Coastguard Worker sep=",";; 227*333d2b36SAndroid Build Coastguard Worker sep) 228*333d2b36SAndroid Build Coastguard Worker sep="${2?"${usage}"}"; shift;; 229*333d2b36SAndroid Build Coastguard Worker sep=) 230*333d2b36SAndroid Build Coastguard Worker sep=$(expr "${flag}" : '^sep=\(.*\)$');; 231*333d2b36SAndroid Build Coastguard Worker q) ;& 232*333d2b36SAndroid Build Coastguard Worker quiet) 233*333d2b36SAndroid Build Coastguard Worker quiet=true;; 234*333d2b36SAndroid Build Coastguard Worker noq) ;& 235*333d2b36SAndroid Build Coastguard Worker noquiet) 236*333d2b36SAndroid Build Coastguard Worker quiet=false;; 237*333d2b36SAndroid Build Coastguard Worker nofollow) 238*333d2b36SAndroid Build Coastguard Worker case "${nofollow}" in 239*333d2b36SAndroid Build Coastguard Worker '') 240*333d2b36SAndroid Build Coastguard Worker nofollow="${2?"${usage}"}";; 241*333d2b36SAndroid Build Coastguard Worker *) 242*333d2b36SAndroid Build Coastguard Worker nofollow="${nofollow}|${2?"${usage}"}";; 243*333d2b36SAndroid Build Coastguard Worker esac 244*333d2b36SAndroid Build Coastguard Worker shift 245*333d2b36SAndroid Build Coastguard Worker ;; 246*333d2b36SAndroid Build Coastguard Worker nofollow=*) 247*333d2b36SAndroid Build Coastguard Worker case "${nofollow}" in 248*333d2b36SAndroid Build Coastguard Worker '') 249*333d2b36SAndroid Build Coastguard Worker nofollow=$(expr "${flag}" : '^nofollow=\(.*\)$');; 250*333d2b36SAndroid Build Coastguard Worker *) 251*333d2b36SAndroid Build Coastguard Worker nofollow="${nofollow}|"$(expr "${flag}" : '^nofollow=\(.*\)$');; 252*333d2b36SAndroid Build Coastguard Worker esac 253*333d2b36SAndroid Build Coastguard Worker ;; 254*333d2b36SAndroid Build Coastguard Worker container) 255*333d2b36SAndroid Build Coastguard Worker container_types="${container_types}|${2?"${usage}"}";; 256*333d2b36SAndroid Build Coastguard Worker container=*) 257*333d2b36SAndroid Build Coastguard Worker container_types="${container_types}|"$(expr "${flag}" : '^container=\(.*\)$');; 258*333d2b36SAndroid Build Coastguard Worker p) ;& 259*333d2b36SAndroid Build Coastguard Worker projects) 260*333d2b36SAndroid Build Coastguard Worker projects_out="${2?"${usage}"}"; shift;; 261*333d2b36SAndroid Build Coastguard Worker p=*) ;& 262*333d2b36SAndroid Build Coastguard Worker projects=*) 263*333d2b36SAndroid Build Coastguard Worker projects_out=$(expr "${flag}" : '^.*=\(.*\)$');; 264*333d2b36SAndroid Build Coastguard Worker d) ;& 265*333d2b36SAndroid Build Coastguard Worker directores) 266*333d2b36SAndroid Build Coastguard Worker directories_out="${2?"${usage}"}"; shift;; 267*333d2b36SAndroid Build Coastguard Worker d=*) ;& 268*333d2b36SAndroid Build Coastguard Worker directories=*) 269*333d2b36SAndroid Build Coastguard Worker directories_out=$(expr "${flag}" : '^.*=\(.*\)$');; 270*333d2b36SAndroid Build Coastguard Worker t) ;& 271*333d2b36SAndroid Build Coastguard Worker targets) 272*333d2b36SAndroid Build Coastguard Worker targets_out="${2?"${usage}"}"; shift;; 273*333d2b36SAndroid Build Coastguard Worker t=*) ;& 274*333d2b36SAndroid Build Coastguard Worker targets=) 275*333d2b36SAndroid Build Coastguard Worker targets_out=$(expr "${flag}" : '^.*=\(.*\)$');; 276*333d2b36SAndroid Build Coastguard Worker n) ;& 277*333d2b36SAndroid Build Coastguard Worker notices) 278*333d2b36SAndroid Build Coastguard Worker notices_out="${2?"${usage}"}"; shift;; 279*333d2b36SAndroid Build Coastguard Worker n=*) ;& 280*333d2b36SAndroid Build Coastguard Worker notices=) 281*333d2b36SAndroid Build Coastguard Worker notices_out=$(expr "${flag}" : '^.*=\(.*\)$');; 282*333d2b36SAndroid Build Coastguard Worker *) 283*333d2b36SAndroid Build Coastguard Worker die "${usage}\n\nUnknown flag ${1}";; 284*333d2b36SAndroid Build Coastguard Worker esac 285*333d2b36SAndroid Build Coastguard Worker ;; 286*333d2b36SAndroid Build Coastguard Worker *) 287*333d2b36SAndroid Build Coastguard Worker targets+=("${1:-}") 288*333d2b36SAndroid Build Coastguard Worker ;; 289*333d2b36SAndroid Build Coastguard Worker esac 290*333d2b36SAndroid Build Coastguard Worker shift 291*333d2b36SAndroid Build Coastguard Workerdone 292*333d2b36SAndroid Build Coastguard Worker 293*333d2b36SAndroid Build Coastguard Worker 294*333d2b36SAndroid Build Coastguard Worker# fail fast if command-line arguments are invalid 295*333d2b36SAndroid Build Coastguard Worker 296*333d2b36SAndroid Build Coastguard Workerif [ ! -v targets[0] ] && ! ${use_stdin}; then 297*333d2b36SAndroid Build Coastguard Worker die "${usage}\n\nNo target specified." 298*333d2b36SAndroid Build Coastguard Workerfi 299*333d2b36SAndroid Build Coastguard Worker 300*333d2b36SAndroid Build Coastguard Workerif [ -z "${projects_out}" ] \ 301*333d2b36SAndroid Build Coastguard Worker && [ -z "${directories_out}" ] \ 302*333d2b36SAndroid Build Coastguard Worker && [ -z "${targets_out}" ] \ 303*333d2b36SAndroid Build Coastguard Worker && [ -z "${notices_out}" ] 304*333d2b36SAndroid Build Coastguard Workerthen 305*333d2b36SAndroid Build Coastguard Worker targets_out='/dev/stdout' 306*333d2b36SAndroid Build Coastguard Workerfi 307*333d2b36SAndroid Build Coastguard Worker 308*333d2b36SAndroid Build Coastguard Workerif [ -z "${container_types}" ]; then 309*333d2b36SAndroid Build Coastguard Worker container_types='apex|apk|zip|jar|tar|tgz' 310*333d2b36SAndroid Build Coastguard Workerfi 311*333d2b36SAndroid Build Coastguard Worker 312*333d2b36SAndroid Build Coastguard Worker# showProgress when stderr is a tty 313*333d2b36SAndroid Build Coastguard Workerif [ -t 2 ] && ! ${quiet}; then 314*333d2b36SAndroid Build Coastguard Worker showProgress=true 315*333d2b36SAndroid Build Coastguard Workerelse 316*333d2b36SAndroid Build Coastguard Worker showProgress=false 317*333d2b36SAndroid Build Coastguard Workerfi 318*333d2b36SAndroid Build Coastguard Worker 319*333d2b36SAndroid Build Coastguard Worker# interactive when both stderr and stdin are tty 320*333d2b36SAndroid Build Coastguard Workerif ${showProgress} && [ -t 0 ]; then 321*333d2b36SAndroid Build Coastguard Worker interactive=true 322*333d2b36SAndroid Build Coastguard Workerelse 323*333d2b36SAndroid Build Coastguard Worker interactive=false 324*333d2b36SAndroid Build Coastguard Workerfi 325*333d2b36SAndroid Build Coastguard Worker 326*333d2b36SAndroid Build Coastguard Worker 327*333d2b36SAndroid Build Coastguard Workerreadonly tmpFiles=$(mktemp -d "${TMPDIR}.tdeps.XXXXXXXXX") 328*333d2b36SAndroid Build Coastguard Workerif [ -z "${tmpFiles}" ]; then 329*333d2b36SAndroid Build Coastguard Worker die "${me}: unable to create temporary directory" 330*333d2b36SAndroid Build Coastguard Workerfi 331*333d2b36SAndroid Build Coastguard Worker 332*333d2b36SAndroid Build Coastguard Worker# The deps files contain unique (isnotice target) tuples where 333*333d2b36SAndroid Build Coastguard Worker# isnotice in {0,1} with 1 when ninja target 'target' is a license or notice. 334*333d2b36SAndroid Build Coastguard Workerreadonly oldDeps="${tmpFiles}/old" 335*333d2b36SAndroid Build Coastguard Workerreadonly newDeps="${tmpFiles}/new" 336*333d2b36SAndroid Build Coastguard Workerreadonly allDeps="${tmpFiles}/all" 337*333d2b36SAndroid Build Coastguard Worker 338*333d2b36SAndroid Build Coastguard Workerif ${use_stdin}; then # start deps by reading 1 target per line from stdin 339*333d2b36SAndroid Build Coastguard Worker awk ' 340*333d2b36SAndroid Build Coastguard Worker NF > 0 { 341*333d2b36SAndroid Build Coastguard Worker print ( \ 342*333d2b36SAndroid Build Coastguard Worker $0 ~ /NOTICE|LICEN[CS]E/ \ 343*333d2b36SAndroid Build Coastguard Worker || $0 ~ /(notice|licen[cs]e)[.]txt/ \ 344*333d2b36SAndroid Build Coastguard Worker )" "gensub(/\s*$/, "", "g", gensub(/^\s*/, "", "g")) 345*333d2b36SAndroid Build Coastguard Worker } 346*333d2b36SAndroid Build Coastguard Worker ' > "${newDeps}" 347*333d2b36SAndroid Build Coastguard Workerelse # start with no deps by clearing file 348*333d2b36SAndroid Build Coastguard Worker : > "${newDeps}" 349*333d2b36SAndroid Build Coastguard Workerfi 350*333d2b36SAndroid Build Coastguard Worker 351*333d2b36SAndroid Build Coastguard Worker# extend deps by appending targets from command-line 352*333d2b36SAndroid Build Coastguard Workerfor idx in "${!targets[*]}"; do 353*333d2b36SAndroid Build Coastguard Worker isnotice='0' 354*333d2b36SAndroid Build Coastguard Worker case "${targets[${idx}]}" in 355*333d2b36SAndroid Build Coastguard Worker *NOTICE*) ;& 356*333d2b36SAndroid Build Coastguard Worker *LICEN[CS]E*) ;& 357*333d2b36SAndroid Build Coastguard Worker *notice.txt) ;& 358*333d2b36SAndroid Build Coastguard Worker *licen[cs]e.txt) 359*333d2b36SAndroid Build Coastguard Worker isnotice='1';; 360*333d2b36SAndroid Build Coastguard Worker esac 361*333d2b36SAndroid Build Coastguard Worker echo "${isnotice} 1 ${targets[${idx}]}" >> "${newDeps}" 362*333d2b36SAndroid Build Coastguard Workerdone 363*333d2b36SAndroid Build Coastguard Worker 364*333d2b36SAndroid Build Coastguard Worker# remove duplicates and start with new, old and all the same 365*333d2b36SAndroid Build Coastguard Workersort -u < "${newDeps}" > "${allDeps}" 366*333d2b36SAndroid Build Coastguard Workercp "${allDeps}" "${newDeps}" 367*333d2b36SAndroid Build Coastguard Workercp "${allDeps}" "${oldDeps}" 368*333d2b36SAndroid Build Coastguard Worker 369*333d2b36SAndroid Build Coastguard Worker# report depth of dependenciens when showProgress 370*333d2b36SAndroid Build Coastguard Workerdepth=0 371*333d2b36SAndroid Build Coastguard Worker 372*333d2b36SAndroid Build Coastguard Worker# 1st iteration always unfiltered 373*333d2b36SAndroid Build Coastguard Workerfilter='cat' 374*333d2b36SAndroid Build Coastguard Workerwhile [ $(wc -l < "${newDeps}") -gt 0 ]; do 375*333d2b36SAndroid Build Coastguard Worker if ${showProgress}; then 376*333d2b36SAndroid Build Coastguard Worker echo "depth ${depth} has "$(wc -l < "${newDeps}")" targets" >&2 377*333d2b36SAndroid Build Coastguard Worker depth=$(expr ${depth} + 1) 378*333d2b36SAndroid Build Coastguard Worker fi 379*333d2b36SAndroid Build Coastguard Worker ( # recalculate dependencies by combining unique inputs of new deps w. old 380*333d2b36SAndroid Build Coastguard Worker set +e 381*333d2b36SAndroid Build Coastguard Worker sh -c "${filter}" < "${newDeps}" | cut -d\ -f3- | getDeps 382*333d2b36SAndroid Build Coastguard Worker set -e 383*333d2b36SAndroid Build Coastguard Worker cat "${oldDeps}" 384*333d2b36SAndroid Build Coastguard Worker ) | sort -u > "${allDeps}" 385*333d2b36SAndroid Build Coastguard Worker # recalculate new dependencies as net additions to old dependencies 386*333d2b36SAndroid Build Coastguard Worker set +e 387*333d2b36SAndroid Build Coastguard Worker diff "${oldDeps}" "${allDeps}" --old-line-format='' --new-line-format='%L' \ 388*333d2b36SAndroid Build Coastguard Worker --unchanged-line-format='' > "${newDeps}" 389*333d2b36SAndroid Build Coastguard Worker set -e 390*333d2b36SAndroid Build Coastguard Worker # apply filters on subsequent iterations 391*333d2b36SAndroid Build Coastguard Worker case "${nofollow}" in 392*333d2b36SAndroid Build Coastguard Worker '') 393*333d2b36SAndroid Build Coastguard Worker filter='cat';; 394*333d2b36SAndroid Build Coastguard Worker *) 395*333d2b36SAndroid Build Coastguard Worker filter="egrep -v '^[01] 0 (${nofollow})$'" 396*333d2b36SAndroid Build Coastguard Worker ;; 397*333d2b36SAndroid Build Coastguard Worker esac 398*333d2b36SAndroid Build Coastguard Worker # recalculate old dependencies for next iteration 399*333d2b36SAndroid Build Coastguard Worker cp "${allDeps}" "${oldDeps}" 400*333d2b36SAndroid Build Coastguard Workerdone 401*333d2b36SAndroid Build Coastguard Worker 402*333d2b36SAndroid Build Coastguard Worker# found all deps -- clean up last iteration of old and new 403*333d2b36SAndroid Build Coastguard Workerrm -f "${oldDeps}" 404*333d2b36SAndroid Build Coastguard Workerrm -f "${newDeps}" 405*333d2b36SAndroid Build Coastguard Worker 406*333d2b36SAndroid Build Coastguard Workerif ${showProgress}; then 407*333d2b36SAndroid Build Coastguard Worker echo $(wc -l < "${allDeps}")" targets" >&2 408*333d2b36SAndroid Build Coastguard Workerfi 409*333d2b36SAndroid Build Coastguard Worker 410*333d2b36SAndroid Build Coastguard Workerif [ -n "${targets_out}" ]; then 411*333d2b36SAndroid Build Coastguard Worker cut -d\ -f3- "${allDeps}" | sort -u > "${targets_out}" 412*333d2b36SAndroid Build Coastguard Workerfi 413*333d2b36SAndroid Build Coastguard Worker 414*333d2b36SAndroid Build Coastguard Workerif [ -n "${directories_out}" ] \ 415*333d2b36SAndroid Build Coastguard Worker || [ -n "${projects_out}" ] \ 416*333d2b36SAndroid Build Coastguard Worker || [ -n "${notices_out}" ] 417*333d2b36SAndroid Build Coastguard Workerthen 418*333d2b36SAndroid Build Coastguard Worker readonly allDirs="${tmpFiles}/dirs" 419*333d2b36SAndroid Build Coastguard Worker ( 420*333d2b36SAndroid Build Coastguard Worker cut -d\ -f3- "${allDeps}" | tr '\n' '\0' | xargs -0 dirname 421*333d2b36SAndroid Build Coastguard Worker ) | sort -u > "${allDirs}" 422*333d2b36SAndroid Build Coastguard Worker if ${showProgress}; then 423*333d2b36SAndroid Build Coastguard Worker echo $(wc -l < "${allDirs}")" directories" >&2 424*333d2b36SAndroid Build Coastguard Worker fi 425*333d2b36SAndroid Build Coastguard Worker 426*333d2b36SAndroid Build Coastguard Worker case "${directories_out}" in 427*333d2b36SAndroid Build Coastguard Worker '') : do nothing;; 428*333d2b36SAndroid Build Coastguard Worker *) 429*333d2b36SAndroid Build Coastguard Worker cat "${allDirs}" > "${directories_out}" 430*333d2b36SAndroid Build Coastguard Worker ;; 431*333d2b36SAndroid Build Coastguard Worker esac 432*333d2b36SAndroid Build Coastguard Workerfi 433*333d2b36SAndroid Build Coastguard Worker 434*333d2b36SAndroid Build Coastguard Workerif [ -n "${projects_out}" ] \ 435*333d2b36SAndroid Build Coastguard Worker || [ -n "${notices_out}" ] 436*333d2b36SAndroid Build Coastguard Workerthen 437*333d2b36SAndroid Build Coastguard Worker readonly allProj="${tmpFiles}/projects" 438*333d2b36SAndroid Build Coastguard Worker set +e 439*333d2b36SAndroid Build Coastguard Worker egrep -v '^out[/]' "${allDirs}" | getProjects > "${allProj}" 440*333d2b36SAndroid Build Coastguard Worker set -e 441*333d2b36SAndroid Build Coastguard Worker if ${showProgress}; then 442*333d2b36SAndroid Build Coastguard Worker echo $(wc -l < "${allProj}")" projects" >&2 443*333d2b36SAndroid Build Coastguard Worker fi 444*333d2b36SAndroid Build Coastguard Worker 445*333d2b36SAndroid Build Coastguard Worker case "${projects_out}" in 446*333d2b36SAndroid Build Coastguard Worker '') : do nothing;; 447*333d2b36SAndroid Build Coastguard Worker *) 448*333d2b36SAndroid Build Coastguard Worker cat "${allProj}" > "${projects_out}" 449*333d2b36SAndroid Build Coastguard Worker ;; 450*333d2b36SAndroid Build Coastguard Worker esac 451*333d2b36SAndroid Build Coastguard Workerfi 452*333d2b36SAndroid Build Coastguard Worker 453*333d2b36SAndroid Build Coastguard Workercase "${notices_out}" in 454*333d2b36SAndroid Build Coastguard Worker '') : do nothing;; 455*333d2b36SAndroid Build Coastguard Worker *) 456*333d2b36SAndroid Build Coastguard Worker readonly allNotice="${tmpFiles}/notices" 457*333d2b36SAndroid Build Coastguard Worker set +e 458*333d2b36SAndroid Build Coastguard Worker egrep '^1' "${allDeps}" | cut -d\ -f3- | egrep -v '^out/' > "${allNotice}" 459*333d2b36SAndroid Build Coastguard Worker set -e 460*333d2b36SAndroid Build Coastguard Worker cat "${allProj}" | while read proj; do 461*333d2b36SAndroid Build Coastguard Worker for f in LICENSE LICENCE NOTICE license.txt notice.txt; do 462*333d2b36SAndroid Build Coastguard Worker if [ -f "${proj}/${f}" ]; then 463*333d2b36SAndroid Build Coastguard Worker echo "${proj}/${f}" 464*333d2b36SAndroid Build Coastguard Worker fi 465*333d2b36SAndroid Build Coastguard Worker done 466*333d2b36SAndroid Build Coastguard Worker done >> "${allNotice}" 467*333d2b36SAndroid Build Coastguard Worker if ${showProgress}; then 468*333d2b36SAndroid Build Coastguard Worker echo $(cat "${allNotice}" | sort -u | wc -l)" notice targets" >&2 469*333d2b36SAndroid Build Coastguard Worker fi 470*333d2b36SAndroid Build Coastguard Worker readonly hashedNotice="${tmpFiles}/hashednotices" 471*333d2b36SAndroid Build Coastguard Worker ( # md5sum outputs checksum space indicator(space or *) filename newline 472*333d2b36SAndroid Build Coastguard Worker set +e 473*333d2b36SAndroid Build Coastguard Worker sort -u "${allNotice}" | tr '\n' '\0' | xargs -0 -r md5sum 2>/dev/null 474*333d2b36SAndroid Build Coastguard Worker set -e 475*333d2b36SAndroid Build Coastguard Worker # use sed to replace space and indicator with separator 476*333d2b36SAndroid Build Coastguard Worker ) > "${hashedNotice}" 477*333d2b36SAndroid Build Coastguard Worker if ${showProgress}; then 478*333d2b36SAndroid Build Coastguard Worker echo $(cut -d\ -f2- "${hashedNotice}" | sort -u | wc -l)" notice files" >&2 479*333d2b36SAndroid Build Coastguard Worker echo $(cut -d\ -f1 "${hashedNotice}" | sort -u | wc -l)" distinct notices" >&2 480*333d2b36SAndroid Build Coastguard Worker fi 481*333d2b36SAndroid Build Coastguard Worker sed 's/^\([^ ]*\) [* ]/\1'"${sep}"'/g' "${hashedNotice}" | sort > "${notices_out}" 482*333d2b36SAndroid Build Coastguard Worker ;; 483*333d2b36SAndroid Build Coastguard Workeresac 484*333d2b36SAndroid Build Coastguard Worker 485*333d2b36SAndroid Build Coastguard Workerif ${interactive}; then 486*333d2b36SAndroid Build Coastguard Worker echo -n "$(date '+%F %-k:%M:%S') Delete ${tmpFiles} ? [n] " >&2 487*333d2b36SAndroid Build Coastguard Worker read answer 488*333d2b36SAndroid Build Coastguard Worker case "${answer}" in [yY]*) rm -fr "${tmpFiles}";; esac 489*333d2b36SAndroid Build Coastguard Workerelse 490*333d2b36SAndroid Build Coastguard Worker rm -fr "${tmpFiles}" 491*333d2b36SAndroid Build Coastguard Workerfi 492