Compiling Android project from command line is slow

后端 未结 2 567
名媛妹妹
名媛妹妹 2020-12-05 11:36

I\'m compiling my (fairly simple, just 5 files with few hundred LOC) app from command line on OSX using:

ant debug

It works. But it works slowly

相关标签:
2条回答
  • 2020-12-05 11:48

    I finally found a solution for this! It's a bit of a hack, but it works.

    First, go to your ANDROID-SDK/platform-tools directory, then rename dx app to something else, like dextool, and finally create new dx file with contents:

    #!/bin/sh
    shift
    dextool --dex --incremental --no-optimize $@
    

    Replace "dextool" with the name you chose before. This will prepend (undocumented) --incremental attribute to every dex invocation, which will massively decrease build times by dexing only classes that have changed between builds. Now it looks like this:

    [dx] Merged dex A (1 defs/11,3KiB) with dex B (359 defs/1253,2KiB). Result is 359 defs/1519,3KiB. Took 0,5s

    0.5s instead of 20s is a huge difference!

    Edit - few remarks:

    • you have to compile your project at least once before using this, because it uses previous classes.dex file
    • you can run into problems when using other Android toolchains than ant

    UPDATE:

    Google released SDK Tools 21.0, which renders above tweak absolete, because it does supports pre-dexing. Finally!

    0 讨论(0)
  • 2020-12-05 12:06

    Even in 21.1.1 with the --incremental --no-optimize added in the original dex.bat it is slow, so I went on to figure something out, the result is: if you order the .jar files passed to dex by size you get better performance.

    Watch https://code.google.com/p/android/issues/detail?id=79166 for updates, I hope they agree and this goes into vNext.

    #!/usr/bin/perl
    use strict;
    use warnings;
    #use Data::Dump qw(dump);
    use List::Util qw(first), qw(sum);
    
    # size of the argument, -s for files, -s on **/*.class for folders
    sub size {
            if (-d $_) {
                    # directory size is sum of all class files in the dir recursively
                    # account for pre-dexing and compression with a 25% decrease
                    return sum(map { size($_) * 0.25 } <$_/*.class>) || 0;
            }
            return -s $_; # use built-in size operator
    }
    
    my $dx_args_with_args =
       qr/^--(output|positions|(no-)?optimize-list|dump-(to|width|method)|num-threads|main-dex-list|input-list)$/;
    my $nArgs = $#ARGV;
    # last argument like --blah, those are for dx
    my $lastArg = $nArgs - first { $ARGV[$nArgs - $_] =~ /^--/ } 0..$nArgs;
    if ($lastArg != -1 && $ARGV[$lastArg] =~ /$dx_args_with_args/) {
            $lastArg += 1;
    }
    
    my @inputs = map { $_->[1] }
                 sort { $a->[0] <=> $b->[0] }
                 map { [size(), $_] }
                 @ARGV[$lastArg + 1 .. $nArgs];
    
    print join(" ", @ARGV[0..$lastArg], @inputs);
    
    exit 0;
    

    Usage

    • have Perl on your path
    • copy the above perl script to ANDROID-SDK/build-tools/v.v.v/dx.pl
    • rename dx in ANDROID-SDK/build-tools/v.v.v/
      Unix: rename dx to dx-orig
      Windows: rename dx.bat to dx-orig.bat
    • add a new replacement dx which calls through:
    Windows: dx.bat
    @echo off
    setlocal
    set args=%*
    for /f "delims=" %%i in ('perl "%~dp0dx.pl" %args%') do set args=%%i
    call "%~dp0dx-orig.bat" %args%
    endlocal
    
    Unix: dx
    #!/bin/sh
    dx-orig `perl dx.pl $@`
    
    0 讨论(0)
提交回复
热议问题