Home | History | Annotate | Download | only in etc
      1 #!/bin/bash
      2 #
      3 # Copyright (C) 2008 The Android Open Source Project
      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 
     17 # Stop if something fails.
     18 set -e
     19 
     20 # Set default values for directories.
     21 if [ -d smali ]; then
     22   HAS_SMALI=true
     23 else
     24   HAS_SMALI=false
     25 fi
     26 
     27 # .j files in jasmin get compiled into classes.jar
     28 if [ -d jasmin ]; then
     29   HAS_JASMIN=true
     30 else
     31   HAS_JASMIN=false
     32 fi
     33 
     34 if [ -d src ]; then
     35   HAS_SRC=true
     36 else
     37   HAS_SRC=false
     38 fi
     39 
     40 # .java files in src-art get compiled with libcore on the bootclasspath
     41 if [ -d src-art ]; then
     42   HAS_SRC_ART=true
     43 else
     44   HAS_SRC_ART=false
     45 fi
     46 
     47 if [ -d src2 ]; then
     48   HAS_SRC2=true
     49 else
     50   HAS_SRC2=false
     51 fi
     52 
     53 if [ -d src-multidex ]; then
     54   HAS_SRC_MULTIDEX=true
     55 else
     56   HAS_SRC_MULTIDEX=false
     57 fi
     58 
     59 if [ -d smali-multidex ]; then
     60   HAS_SMALI_MULTIDEX=true
     61 else
     62   HAS_SMALI_MULTIDEX=false
     63 fi
     64 
     65 # .j files in jasmin-multidex get compiled into classes2.jar
     66 if [ -d jasmin-multidex ]; then
     67   HAS_JASMIN_MULTIDEX=true
     68 else
     69   HAS_JASMIN_MULTIDEX=false
     70 fi
     71 
     72 if [ -d src-ex ]; then
     73   HAS_SRC_EX=true
     74 else
     75   HAS_SRC_EX=false
     76 fi
     77 
     78 if [ -d src-dex2oat-unresolved ]; then
     79   HAS_SRC_DEX2OAT_UNRESOLVED=true
     80 else
     81   HAS_SRC_DEX2OAT_UNRESOLVED=false
     82 fi
     83 
     84 # DESUGAR=false run-test... will disable desugar.
     85 if [[ "$DESUGAR" == false ]]; then
     86   USE_DESUGAR=false
     87 fi
     88 
     89 # Allow overriding ZIP_COMPRESSION_METHOD with e.g. 'store'
     90 ZIP_COMPRESSION_METHOD="deflate"
     91 # Align every ZIP file made by calling $ZIPALIGN command?
     92 WITH_ZIP_ALIGN=false
     93 ZIP_ALIGN_BYTES="-1"
     94 
     95 DX_FLAGS="--min-sdk-version=24"
     96 DX_VM_FLAGS=""
     97 EXPERIMENTAL=""
     98 
     99 BUILD_MODE="target"
    100 DEV_MODE="no"
    101 
    102 # The key for default arguments if no experimental things are enabled.
    103 DEFAULT_EXPERIMENT="no-experiment"
    104 
    105 # Setup experimental flag mappings in a bash associative array.
    106 declare -A JACK_EXPERIMENTAL_ARGS
    107 JACK_EXPERIMENTAL_ARGS["agents"]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
    108 JACK_EXPERIMENTAL_ARGS["default-methods"]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
    109 JACK_EXPERIMENTAL_ARGS["lambdas"]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
    110 JACK_EXPERIMENTAL_ARGS["method-handles"]="-D jack.java.source.version=1.7 -D jack.android.min-api-level=o-b1"
    111 JACK_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-D jack.java.source.version=1.8 -D jack.android.min-api-level=24"
    112 
    113 declare -A SMALI_EXPERIMENTAL_ARGS
    114 SMALI_EXPERIMENTAL_ARGS["default-methods"]="--api 24"
    115 SMALI_EXPERIMENTAL_ARGS["method-handles"]="--api 26"
    116 SMALI_EXPERIMENTAL_ARGS["agents"]="--api 26"
    117 
    118 declare -A JAVAC_EXPERIMENTAL_ARGS
    119 JAVAC_EXPERIMENTAL_ARGS["default-methods"]="-source 1.8 -target 1.8"
    120 JAVAC_EXPERIMENTAL_ARGS["lambdas"]="-source 1.8 -target 1.8"
    121 JAVAC_EXPERIMENTAL_ARGS["method-handles"]="-source 1.8 -target 1.8"
    122 # We need to leave javac at default 1.7 so that dx will continue to work
    123 JAVAC_EXPERIMENTAL_ARGS[${DEFAULT_EXPERIMENT}]="-source 1.8 -target 1.8"
    124 JAVAC_EXPERIMENTAL_ARGS["agents"]="-source 1.8 -target 1.8"
    125 
    126 declare -A DX_EXPERIMENTAL_ARGS
    127 DX_EXPERIMENTAL_ARGS["method-handles"]="--min-sdk-version=26"
    128 
    129 while true; do
    130   if [ "x$1" = "x--dx-option" ]; then
    131     shift
    132     option="$1"
    133     DX_FLAGS="${DX_FLAGS} $option"
    134     shift
    135   elif [ "x$1" = "x--dx-vm-option" ]; then
    136     shift
    137     option="$1"
    138     DX_VM_FLAGS="${DX_VM_FLAGS} $option"
    139     shift
    140   elif [ "x$1" = "x--jvm" ]; then
    141     shift
    142   elif [ "x$1" = "x--no-src" ]; then
    143     HAS_SRC=false
    144     shift
    145   elif [ "x$1" = "x--no-src2" ]; then
    146     HAS_SRC2=false
    147     shift
    148   elif [ "x$1" = "x--no-src-multidex" ]; then
    149     HAS_SRC_MULTIDEX=false
    150     shift
    151   elif [ "x$1" = "x--no-smali-multidex" ]; then
    152     HAS_SMALI_MULTIDEX=false
    153     shift
    154   elif [ "x$1" = "x--no-src-ex" ]; then
    155     HAS_SRC_EX=false
    156     shift
    157   elif [ "x$1" = "x--no-smali" ]; then
    158     HAS_SMALI=false
    159     shift
    160   elif [ "x$1" = "x--experimental" ]; then
    161     shift
    162     # We have a specific experimental configuration so don't use the default.
    163     DEFAULT_EXPERIMENT=""
    164     EXPERIMENTAL="${EXPERIMENTAL} $1"
    165     shift
    166   elif [ "x$1" = "x--zip-compression-method" ]; then
    167     # Allow using different zip compression method, e.g. 'store'
    168     shift
    169     ZIP_COMPRESSION_METHOD="$1"
    170     shift
    171   elif [ "x$1" = "x--zip-align" ]; then
    172     # Align ZIP entries to some # of bytes.
    173     shift
    174     WITH_ZIP_ALIGN=true
    175     ZIP_ALIGN_BYTES="$1"
    176     shift
    177   elif [ "x$1" = "x--host" ]; then
    178     BUILD_MODE="host"
    179     shift
    180   elif [ "x$1" = "x--target" ]; then
    181     BUILD_MODE="target"
    182     shift
    183   elif [ "x$1" = "x--dev" ]; then
    184     DEV_MODE="yes"
    185     shift
    186   elif expr "x$1" : "x--" >/dev/null 2>&1; then
    187     echo "unknown $0 option: $1" 1>&2
    188     exit 1
    189   else
    190     break
    191   fi
    192 done
    193 
    194 # Be sure to get any default arguments if not doing any experiments.
    195 EXPERIMENTAL="${EXPERIMENTAL} ${DEFAULT_EXPERIMENT}"
    196 
    197 if [ "${JACK_SERVER}" = "false" ]; then
    198   # Run in single-threaded mode for the continuous buildbot.
    199   JACK_ARGS="${JACK_ARGS} -D sched.runner=single-threaded"
    200 else
    201   # Run with 4 threads to reduce memory footprint and thread contention.
    202   JACK_ARGS="${JACK_ARGS} -D sched.runner=multi-threaded"
    203   JACK_ARGS="${JACK_ARGS} -D sched.runner.thread.kind=fixed"
    204   JACK_ARGS="${JACK_ARGS} -D sched.runner.thread.fixed.count=4"
    205 fi
    206 
    207 # Add args from the experimental mappings.
    208 for experiment in ${EXPERIMENTAL}; do
    209   JACK_ARGS="${JACK_ARGS} ${JACK_EXPERIMENTAL_ARGS[${experiment}]}"
    210   SMALI_ARGS="${SMALI_ARGS} ${SMALI_EXPERIMENTAL_ARGS[${experiment}]}"
    211   JAVAC_ARGS="${JAVAC_ARGS} ${JAVAC_EXPERIMENTAL_ARGS[${experiment}]}"
    212   DX_FLAGS="${DX_FLAGS} ${DX_EXPERIMENTAL_ARGS[${experiment}]}"
    213 done
    214 
    215 #########################################
    216 
    217 # Catch all commands to 'ZIP' and prepend extra flags.
    218 # Optionally, zipalign results to some alignment.
    219 function zip() {
    220   local zip_target="$1"
    221   local entry_src="$2"
    222   shift 2
    223 
    224   command zip --compression-method "$ZIP_COMPRESSION_METHOD" "$zip_target" "$entry_src" "$@"
    225 
    226   if "$WITH_ZIP_ALIGN"; then
    227     # zipalign does not operate in-place, so write results to a temp file.
    228     local tmp_file="$(mktemp)"
    229     "$ZIPALIGN" -f "$ZIP_ALIGN_BYTES" "$zip_target" "$tmp_file"
    230     # replace original zip target with our temp file.
    231     mv "$tmp_file" "$zip_target"
    232   fi
    233 }
    234 
    235 function make_jasmin() {
    236   local out_directory="$1"
    237   shift
    238   local jasmin_sources=("$@")
    239 
    240   mkdir -p "$out_directory"
    241 
    242   if [[ $DEV_MODE == yes ]]; then
    243     echo ${JASMIN} -d "$out_directory" "${jasmin_sources[@]}"
    244     ${JASMIN} -d "$out_directory" "${jasmin_sources[@]}"
    245   else
    246     ${JASMIN} -d "$out_directory" "${jasmin_sources[@]}" >/dev/null
    247   fi
    248 }
    249 
    250 function desugar() {
    251   local desugar_args=--mode=host
    252   if [[ $BUILD_MODE == target ]]; then
    253     desugar_args=--mode=target
    254   fi
    255 
    256   if [[ $DEV_MODE == yes ]]; then
    257     desugar_args="$desugar_args --show-commands"
    258   fi
    259 
    260   "$DESUGAR" --core-only $desugar_args "$@"
    261 }
    262 
    263 # Like regular javac but includes libcore on the bootclasspath.
    264 function javac_with_bootclasspath {
    265   local javac_args=--mode=host
    266   if [[ $BUILD_MODE == target ]]; then
    267     javac_args=--mode=target
    268   fi
    269 
    270   if [[ $DEV_MODE == yes ]]; then
    271     javac_args="$javac_args --show-commands"
    272   fi
    273 
    274   "$ANDROID_BUILD_TOP/art/tools/javac-helper.sh" --core-only $javac_args "$@"
    275 }
    276 
    277 # Make a "dex" file given a directory of classes in $1.
    278 # Also calls desugar on the classes first to convert lambdas.
    279 function make_dex() {
    280   local name="$1"
    281 
    282   local dx_input
    283   if [[ "$USE_DESUGAR" == "true" ]]; then
    284     # Make a jar first so desugar doesn't need every .class file individually.
    285     jar cf "$name.before-desugar.jar" -C "$name" .
    286 
    287     dx_input="${name}.desugar.jar"
    288 
    289     # Make desugared JAR.
    290     desugar --input "$name.before-desugar.jar" --output "$dx_input"
    291   else
    292     dx_input="${name}"
    293   fi
    294 
    295   # Make dex file from desugared JAR.
    296   ${DX} -JXmx256m ${DX_VM_FLAGS} --debug --dex --dump-to=${name}.lst --output=${name}.dex --dump-width=1000 ${DX_FLAGS} "${dx_input}"
    297 }
    298 
    299 # Merge all the dex files in $1..$N into $1. Skip non-existing files, but at least 1 file must exist.
    300 function make_dexmerge() {
    301   # Dex file that acts as the destination.
    302   local dst_file="$1"
    303 
    304   # Dex files that act as the source.
    305   local dex_files_to_merge=()
    306 
    307   # Skip any non-existing files.
    308   while [[ $# -gt 0 ]]; do
    309     if [[ -e "$1" ]]; then
    310       dex_files_to_merge+=("$1")
    311     fi
    312     shift
    313   done
    314 
    315   # Should have at least 1 dex_files_to_merge here, otherwise dxmerger will print the help.
    316   ${DXMERGER} "$dst_file" "${dex_files_to_merge[@]}"
    317 }
    318 
    319 # Print the directory name only if it exists.
    320 function maybe_dir() {
    321   local dirname="$1"
    322   if [[ -d "$dirname" ]]; then
    323     echo "$dirname"
    324   fi
    325 }
    326 
    327 if [ -e classes.dex ]; then
    328   zip $TEST_NAME.jar classes.dex
    329   exit 0
    330 fi
    331 
    332 if [ ${HAS_SRC_DEX2OAT_UNRESOLVED} = "true" ]; then
    333   mkdir classes
    334   mkdir classes-ex
    335   ${JAVAC} ${JAVAC_ARGS} -implicit:none -sourcepath src-dex2oat-unresolved -d classes `find src -name '*.java'`
    336   ${JAVAC} ${JAVAC_ARGS} -implicit:none -sourcepath src -d classes-ex `find src-dex2oat-unresolved -name '*.java'`
    337   if [ ${USE_JACK} = "true" ]; then
    338     jar cf classes.jill.jar -C classes .
    339     jar cf classes-ex.jill.jar -C classes-ex .
    340 
    341     ${JACK} --import classes-ex.jill.jar --output-dex .
    342     zip ${TEST_NAME}-ex.jar classes.dex
    343     ${JACK} --import classes.jill.jar --output-dex .
    344   else
    345     if [ ${NEED_DEX} = "true" ]; then
    346       make_dex classes-ex
    347       mv classes-ex.dex classes.dex   # rename it so it shows up as "classes.dex" in the zip file.
    348       zip ${TEST_NAME}-ex.jar classes.dex
    349       make_dex classes
    350     fi
    351   fi
    352 else
    353   if [ ${USE_JACK} = "true" ]; then
    354     # Jack toolchain
    355     if [[ "$HAS_SRC" == true || "$HAS_SRC_ART" == true ]]; then
    356       if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
    357         # Compile src and src-multidex in the same .jack file. We will apply multidex partitioning
    358         # when creating the output .dex file.
    359         ${JACK} ${JACK_ARGS} --output-jack src.jack $(maybe_dir src) src-multidex $(maybe_dir src-art)
    360         jack_extra_args="${jack_extra_args} -D jack.dex.output.policy=minimal-multidex"
    361         jack_extra_args="${jack_extra_args} -D jack.preprocessor=true"
    362         jack_extra_args="${jack_extra_args} -D jack.preprocessor.file=multidex.jpp"
    363       else
    364         ${JACK} ${JACK_ARGS} --output-jack src.jack $(maybe_dir src) $(maybe_dir src-art)
    365       fi
    366       jack_extra_args="${jack_extra_args} --import src.jack"
    367     fi
    368 
    369     if [ "${HAS_SRC2}" = "true" ]; then
    370       ${JACK} ${JACK_ARGS} --output-jack src2.jack src2
    371       # In case of duplicate classes, we want to take into account the classes from src2. Therefore
    372       # we apply the 'keep-first' policy and import src2.jack file *before* the src.jack file.
    373       jack_extra_args="${jack_extra_args} -D jack.import.type.policy=keep-first"
    374       jack_extra_args="--import src2.jack ${jack_extra_args}"
    375     fi
    376 
    377     # Compile jack files into a DEX file.
    378     if [ "${HAS_SRC}" = "true" ] || [ "${HAS_SRC2}" = "true" ] || [ "${HAS_SRC_ART}" = "true" ]; then
    379       ${JACK} ${JACK_ARGS} ${jack_extra_args} --output-dex .
    380     fi
    381   else
    382     # Legacy toolchain with javac+dx
    383     if [ "${HAS_SRC}" = "true" ]; then
    384       mkdir classes
    385       ${JAVAC} ${JAVAC_ARGS} -implicit:none -classpath src-multidex -d classes `find src -name '*.java'`
    386     fi
    387 
    388     if [ "${HAS_SRC_ART}" = "true" ]; then
    389       mkdir -p classes
    390       javac_with_bootclasspath ${JAVAC_ARGS} -implicit:none -classpath src-multidex -d classes `find src-art -name '*.java'`
    391     fi
    392 
    393     if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
    394       mkdir classes2
    395       ${JAVAC} ${JAVAC_ARGS} -implicit:none -classpath src -d classes2 `find src-multidex -name '*.java'`
    396       if [ ${NEED_DEX} = "true" ]; then
    397         make_dex classes2
    398       fi
    399     fi
    400 
    401     if [ "${HAS_SRC2}" = "true" ]; then
    402       mkdir -p classes
    403       ${JAVAC} ${JAVAC_ARGS} -d classes `find src2 -name '*.java'`
    404     fi
    405 
    406     if [[ "${HAS_SRC}" == "true" || "${HAS_SRC2}" == "true" || "${HAS_SRC_ART}" == "true" ]]; then
    407       if [ ${NEED_DEX} = "true" ]; then
    408         make_dex classes
    409       fi
    410     fi
    411   fi
    412 fi
    413 
    414 if [[ "${HAS_JASMIN}" == true ]]; then
    415   # Compile Jasmin classes as if they were part of the classes.dex file.
    416   make_jasmin jasmin_classes $(find 'jasmin' -name '*.j')
    417   if [[ "${NEED_DEX}" == "true" ]]; then
    418     # Disable desugar because it won't handle intentional linkage errors.
    419     USE_DESUGAR=false make_dex jasmin_classes
    420     make_dexmerge classes.dex jasmin_classes.dex
    421   else
    422     # Move jasmin classes into classes directory so that they are picked up with -cp classes.
    423     mkdir -p classes
    424     mv jasmin_classes/* classes
    425   fi
    426 fi
    427 
    428 if [ "${HAS_SMALI}" = "true" -a ${NEED_DEX} = "true" ]; then
    429   # Compile Smali classes
    430   ${SMALI} -JXmx512m assemble ${SMALI_ARGS} --output smali_classes.dex `find smali -name '*.smali'`
    431 
    432   # Merge smali files into classes.dex, this takes priority over any jasmin files.
    433   make_dexmerge classes.dex smali_classes.dex
    434 fi
    435 
    436 # Compile Jasmin classes in jasmin-multidex as if they were part of the classes2.jar
    437 if [[ "$HAS_JASMIN_MULTIDEX" == true ]]; then
    438   make_jasmin jasmin_classes2 $(find 'jasmin-multidex' -name '*.j')
    439 
    440   if [[ "${NEED_DEX}" == "true" ]]; then
    441     # Disable desugar because it won't handle intentional linkage errors.
    442     USE_DESUGAR=false make_dex jasmin_classes2
    443 
    444     # Merge jasmin_classes2.dex into classes2.dex
    445     make_dexmerge classes2.dex jasmin_classes2.dex
    446   else
    447     # Move jasmin classes into classes2 directory so that they are picked up with -cp classes2.
    448     mkdir -p classes2
    449     mv jasmin_classes2/* classes2
    450   fi
    451 fi
    452 
    453 if [ "${HAS_SMALI_MULTIDEX}" = "true" -a ${NEED_DEX} = "true" ]; then
    454   # Compile Smali classes
    455   ${SMALI} -JXmx512m assemble ${SMALI_ARGS} --output smali_classes2.dex `find smali-multidex -name '*.smali'`
    456 
    457   # Merge smali_classes2.dex into classes2.dex
    458   make_dexmerge classes2.dex smali_classes2.dex
    459 fi
    460 
    461 
    462 if [ ${HAS_SRC_EX} = "true" ]; then
    463   if [ ${USE_JACK} = "true" ]; then
    464       # Rename previous "classes.dex" so it is not overwritten.
    465       mv classes.dex classes-1.dex
    466       #TODO find another way to append src.jack to the jack classpath
    467       ${JACK}:src.jack ${JACK_ARGS} --output-dex . src-ex
    468       zip $TEST_NAME-ex.jar classes.dex
    469       # Restore previous "classes.dex" so it can be zipped.
    470       mv classes-1.dex classes.dex
    471   else
    472     # Build src-ex into classes-ex.
    473     # Includes 'src', 'src-art' source when compiling classes-ex, but exclude their .class files.
    474     if [[ "${HAS_SRC}" == "true" ]]; then
    475       mkdir -p classes-tmp-for-ex
    476       ${JAVAC} ${JAVAC_ARGS} -d classes-tmp-for-ex `find src -name '*.java'`
    477       src_tmp_for_ex="-cp classes-tmp-for-ex"
    478     fi
    479     if [[ "${HAS_SRC_ART}" == "true" ]]; then
    480       mkdir -p classes-tmp-for-ex
    481       javac_with_bootclasspath ${JAVAC_ARGS} -d classes-tmp-for-ex `find src-art -name '*.java'`
    482       src_tmp_for_ex="-cp classes-tmp-for-ex"
    483     fi
    484     mkdir classes-ex
    485     ${JAVAC} ${JAVAC_ARGS} -d classes-ex $src_tmp_for_ex `find src-ex -name '*.java'`
    486     if [ ${NEED_DEX} = "true" ]; then
    487       make_dex classes-ex
    488 
    489       # quick shuffle so that the stored name is "classes.dex"
    490       mv classes.dex classes-1.dex
    491       mv classes-ex.dex classes.dex
    492       zip $TEST_NAME-ex.jar classes.dex
    493       mv classes.dex classes-ex.dex
    494       mv classes-1.dex classes.dex
    495     fi
    496   fi
    497 fi
    498 
    499 # Create a single dex jar with two dex files for multidex.
    500 if [ ${NEED_DEX} = "true" ]; then
    501   if [ ${HAS_SRC_MULTIDEX} = "true" ] || [ ${HAS_JASMIN_MULTIDEX} = "true" ] || [ ${HAS_SMALI_MULTIDEX} = "true" ]; then
    502     zip $TEST_NAME.jar classes.dex classes2.dex
    503   else
    504     zip $TEST_NAME.jar classes.dex
    505   fi
    506 fi
    507