从命令行编译Android项目速度缓慢

16

我正在使用如下命令在OSX上编译我的应用程序(相对简单,只有5个文件,几百行代码):

ant debug

它可以正常工作。但速度很慢:

BUILD SUCCESSFUL Total time:

26 秒

为什么会这样呢?即使我只更改一个java文件中的一行代码也要花费这么长时间。 大部分时间都花费在dex阶段(大约20秒),据我所知,这是创建Dalvik字节码的过程。 但是,我的朋友也在同一项目上工作,但在Windows上使用Eclipse编译只需要一两秒钟。 有什么办法可以加快这个过程吗?


苹果公司与Android构建时间有什么关系?顺便说一下,测试iOS非常轻松 - 从开始编译到应用程序在模拟器上运行只需要几秒钟。 - mav
你说你在OSX上运行它,而且你还说你的朋友(在Windows上)用Eclipse编译同一个项目只需要一秒钟...无论如何,你有没有尝试在Windows平台上使用ant?如果它比在eclipse中编译需要更长的时间,那么问题就出在ant上,否则...问题就出在你的电脑上。 - Selvin
我没有在Windows上尝试过。不管怎样,我知道这可能是ant的问题,因为它正在从头开始重建dex文件,而Eclipse会缓存它或其他一些东西。这就是为什么我问这个问题 - 是想知道是否有解决办法。我不想使用Eclipse,因为它很慢,而且我讨厌它的用户界面。 - mav
2个回答

13

我终于找到了解决办法!它有一点点“hack”,但它能够起作用。

首先,进入你的ANDROID-SDK/platform-tools目录,然后将dx应用程序重命名为其他名称,例如dextool,最后创建一个包含以下内容的新的dx文件:

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

将“dextool”替换为您之前选择的名称。这将在每个dex调用中添加(未记录的)-incremental属性,它会仅对在构建之间更改的类进行dex,大大减少构建时间。现在它看起来像这样:

[dx]已合并dex A(1 defs / 11.3KiB)和dex B(359 defs / 1253.2KiB)。结果为359 defs / 1519.3KiB。花费0.5秒

0.5秒而不是20秒的巨大差异!

编辑-一些注释:

  • 您必须先编译项目,然后再使用此功能,因为它使用上一个classes.dex文件
  • 如果使用其他 Android 工具链而非 ant,则可能会遇到问题

更新:

Google 发布了 SDK 工具21.0,该工具支持预先 dex,因此上述修改已过时。终于!


我真希望Google可以解决这个问题。从ant脚本构建需要的时间太长了,有点儿荒谬 - 对我来说,使用ADT进行清理和重建需要大约30秒的时间,而build.xml ant脚本则需要大约60秒的时间。 - Wayne Uroda
这实际上非常有效。我已经连续使用了几周,唯一的缺点是在堆栈跟踪中丢失行号。最好在生产环境中关闭,但在开发中可以节省很多时间。 - brk3
5
嗨@mav,你能否澄清一下SDK工具21.0是否会自动执行此操作或需要进行配置?我尝试更新到最新版本(21.1),但即使只更改一行代码,我的构建时间也没有显着缩短。我在Ubuntu上使用IntelliJ。 - Alex
@mav 我下载了最新的Android ADT...我想还有最新的SDK工具...但是我在本地使用CLI构建仍然需要30多分钟...是否有其他解决方法,因为我在ANDROID-SDK/platform-tools目录中找不到dx应用程序? - Alex Stanese
1
@AlexStanese:它在SDK/build-tools/version中。 - TWiStErRob
显示剩余2条评论

0
即使在21.1.1版本中,原始dex.bat添加了“--incremental --no-optimize”,它仍然很慢,所以我继续尝试找出一些东西,结果是:如果按大小对传递给dex的.jar文件进行排序,您将获得更好的性能。
请关注https://code.google.com/p/android/issues/detail?id=79166以获取更新,我希望他们同意并将其纳入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;

使用方法

  • 确保您的路径中有Perl
  • 将上述Perl脚本复制到ANDROID-SDK/build-tools/v.v.v/dx.pl
  • 将ANDROID-SDK/build-tools/v.v.v/中的dx重命名为:
    Unix: 将dx重命名为dx-orig
    Windows: 将dx.bat重命名为dx-orig.bat
  • 添加一个新的替换dx,调用如下:
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 $@`

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接