Home | History | Annotate | Download | only in command
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.dx.command;
     18 
     19 import com.android.dx.Version;
     20 
     21 /**
     22  * Main class for dx. It recognizes enough options to be able to dispatch
     23  * to the right "actual" main.
     24  */
     25 public class Main {
     26     private static String USAGE_MESSAGE =
     27         "usage:\n" +
     28         "  dx --dex [--debug] [--verbose] [--positions=<style>] " +
     29         "[--no-locals]\n" +
     30         "  [--no-optimize] [--statistics] [--[no-]optimize-list=<file>] " +
     31         "[--no-strict]\n" +
     32         "  [--keep-classes] [--output=<file>] [--dump-to=<file>] " +
     33         "[--dump-width=<n>]\n" +
     34         "  [--dump-method=<name>[*]] [--verbose-dump] [--no-files] " +
     35         "[--core-library]\n" +
     36         "  [--num-threads=<n>] [--incremental] [--force-jumbo]\n" +
     37         "  [--multi-dex [--main-dex-list=<file> [--minimal-main-dex]]\n" +
     38         "  [<file>.class | <file>.{zip,jar,apk} | <directory>] ...\n" +
     39         "    Convert a set of classfiles into a dex file, optionally " +
     40         "embedded in a\n" +
     41         "    jar/zip. Output name must end with one of: .dex .jar " +
     42         ".zip .apk or be a directory.\n" +
     43         "    Positions options: none, important, lines.\n" +
     44         "    --multi-dex: allows to generate several dex files if needed. " +
     45         "This option is \n" +
     46         "    exclusive with --incremental, causes --num-threads to be ignored " +
     47         "and only\n" +
     48         "    supports folder or archive output.\n" +
     49         "    --main-dex-list=<file>: <file> is a list of class file names, " +
     50         "classes defined by\n" +
     51         "    those class files are put in classes.dex.\n" +
     52         "    --minimal-main-dex: only classes selected by --main-dex-list are " +
     53         "to be put in\n" +
     54         "    the main dex.\n" +
     55         "  dx --annotool --annotation=<class> [--element=<element types>]\n" +
     56         "  [--print=<print types>]\n" +
     57         "  dx --dump [--debug] [--strict] [--bytes] [--optimize]\n" +
     58         "  [--basic-blocks | --rop-blocks | --ssa-blocks | --dot] " +
     59         "[--ssa-step=<step>]\n" +
     60         "  [--width=<n>] [<file>.class | <file>.txt] ...\n" +
     61         "    Dump classfiles, or transformations thereof, in a " +
     62         "human-oriented format.\n" +
     63         "  dx --find-usages <file.dex> <declaring type> <member>\n" +
     64         "    Find references and declarations to a field or method.\n" +
     65         "    declaring type: a class name in internal form, like " +
     66         "Ljava/lang/Object;\n" +
     67         "    member: a field or method name, like hashCode\n" +
     68         "  dx -J<option> ... <arguments, in one of the above " +
     69         "forms>\n" +
     70         "    Pass VM-specific options to the virtual machine that " +
     71         "runs dx.\n" +
     72         "  dx --version\n" +
     73         "    Print the version of this tool (" + Version.VERSION +
     74         ").\n" +
     75         "  dx --help\n" +
     76         "    Print this message.";
     77 
     78     /**
     79      * This class is uninstantiable.
     80      */
     81     private Main() {
     82         // This space intentionally left blank.
     83     }
     84 
     85     /**
     86      * Run!
     87      */
     88     public static void main(String[] args) {
     89         boolean gotCmd = false;
     90         boolean showUsage = false;
     91 
     92         try {
     93             for (int i = 0; i < args.length; i++) {
     94                 String arg = args[i];
     95                 if (arg.equals("--") || !arg.startsWith("--")) {
     96                     gotCmd = false;
     97                     showUsage = true;
     98                     break;
     99                 }
    100 
    101                 gotCmd = true;
    102                 if (arg.equals("--dex")) {
    103                     com.android.dx.command.dexer.Main.main(without(args, i));
    104                     break;
    105                 } else if (arg.equals("--dump")) {
    106                     com.android.dx.command.dump.Main.main(without(args, i));
    107                     break;
    108                 } else if (arg.equals("--annotool")) {
    109                     com.android.dx.command.annotool.Main.main(
    110                             without(args, i));
    111                     break;
    112                 } else if (arg.equals("--find-usages")) {
    113                     com.android.dx.command.findusages.Main.main(without(args, i));
    114                     break;
    115                 } else if (arg.equals("--version")) {
    116                     version();
    117                     break;
    118                 } else if (arg.equals("--help")) {
    119                     showUsage = true;
    120                     break;
    121                 } else {
    122                     gotCmd = false;
    123                 }
    124             }
    125         } catch (UsageException ex) {
    126             showUsage = true;
    127         } catch (RuntimeException ex) {
    128             System.err.println("\nUNEXPECTED TOP-LEVEL EXCEPTION:");
    129             ex.printStackTrace();
    130             System.exit(2);
    131         } catch (Throwable ex) {
    132             System.err.println("\nUNEXPECTED TOP-LEVEL ERROR:");
    133             ex.printStackTrace();
    134             if ((ex instanceof NoClassDefFoundError)
    135                     || (ex instanceof NoSuchMethodError)) {
    136                 System.err.println(
    137                         "Note: You may be using an incompatible " +
    138                         "virtual machine or class library.\n" +
    139                         "(This program is known to be incompatible " +
    140                         "with recent releases of GCJ.)");
    141             }
    142             System.exit(3);
    143         }
    144 
    145         if (!gotCmd) {
    146             System.err.println("error: no command specified");
    147             showUsage = true;
    148         }
    149 
    150         if (showUsage) {
    151             usage();
    152             System.exit(1);
    153         }
    154     }
    155 
    156     /**
    157      * Prints the version message.
    158      */
    159     private static void version() {
    160         System.err.println("dx version " + Version.VERSION);
    161         System.exit(0);
    162     }
    163 
    164     /**
    165      * Prints the usage message.
    166      */
    167     private static void usage() {
    168         System.err.println(USAGE_MESSAGE);
    169     }
    170 
    171     /**
    172      * Returns a copy of the given args array, but without the indicated
    173      * element.
    174      *
    175      * @param orig {@code non-null;} original array
    176      * @param n which element to omit
    177      * @return {@code non-null;} new array
    178      */
    179     private static String[] without(String[] orig, int n) {
    180         int len = orig.length - 1;
    181         String[] newa = new String[len];
    182         System.arraycopy(orig, 0, newa, 0, n);
    183         System.arraycopy(orig, n + 1, newa, n, len - n);
    184         return newa;
    185     }
    186 }
    187