1#!/bin/bash
2
3# Ensure that GNU parallel is installed.
4# We use this to build multiple targets at the same time.
5if [[ -z $(command -v parallel) ]]; then
6  echo "Please install GNU Parallel."
7  exit
8fi
9
10if [[ $# -lt 2 ]]; then
11  echo "Usage: $0 <Android root directory> <output directory> [specific targets to build]"
12  exit
13fi
14
15android_root_dir=$1
16export out_dir=$2
17shift 2
18all_targets="$@"
19
20echo "Android tree: $android_root_dir"
21echo "Output directory: $out_dir"
22
23mkdir -p $out_dir
24
25cd $android_root_dir
26source build/envsetup.sh > /dev/null
27
28# Collect the list of targets by parsing the output of lunch.
29# TODO: This misses some targets.
30if [[ "$all_targets" = "" ]]; then
31  all_targets=`lunch 2>/dev/null <<< _ | grep "[0-9]" | sed 's/^.* //'`
32fi
33
34# Clean up targets by replacing eng with userdebug using non-aosp variants.
35declare -A targets_map
36for target in $all_targets; do
37  targets_map[$target]=$target
38done
39targets=""
40for target in $all_targets; do
41  clean_target=$(echo $target | sed 's/-eng/-userdebug/' | sed 's/aosp_//')
42  if [[ $clean_target != $target ]] && [[ ${targets_map[$clean_target]} == $clean_target ]]; then
43    echo "Ignoring $target in favor of $clean_target"
44  else
45    if [[ -z $targets ]]; then
46      targets=$target
47    else
48      targets="$targets $target"
49    fi
50  fi
51done
52
53# Calculate the number of targets to build at once.
54# This heuristic could probably be improved.
55cores=$(nproc --all)
56num_targets=$(echo "$targets" | sed 's/ /\n/g' | wc -l)
57parallel_jobs=$(expr $cores / 4)
58if [[ $num_targets -lt $parallel_jobs ]]; then
59  export mmma_jobs=$(expr $cores / $num_targets \* 2)
60else
61  export mmma_jobs=4
62fi
63
64echo "$num_targets target(s): $(echo $targets | paste -sd' ')"
65
66compile_target () {
67  target=$1
68  source build/envsetup.sh > /dev/null
69  lunch $target &> /dev/null
70  # Some targets can't lunch properly.
71  if [ $? -ne 0 ]; then
72    echo "$target cannot be lunched"
73    return 1
74  fi
75  my_out_file="$out_dir/log.$target"
76  rm -f $my_out_file
77  # Build the policy.
78  OUT_DIR=$out_dir/out.$target mmma -j$mmma_jobs system/sepolicy &>> $my_out_file
79  if [ $? -ne 0 ]; then
80    echo "$target failed to build"
81    return 2
82  fi
83  return 0
84}
85export -f compile_target
86
87parallel --no-notice -j $parallel_jobs --bar --joblog $out_dir/joblog compile_target ::: $targets
88
89echo "Failed to lunch: $(grep "\s1\s0\scompile_target" $out_dir/joblog | sed 's/^.* //' | sort | paste -sd' ')"
90echo "Failed to build: $(grep "\s2\s0\scompile_target" $out_dir/joblog | sed 's/^.* //' | sort | paste -sd' ')"
91