如何看待android jack server新的编译工具链Jack

Android-&系统编译与开发(11)
本篇文章翻译自
Jack工具链
Jack是一个Android工具链,用于将Java源码编译成Android dex字节码。它替换了之前的Android工具链,即由javac, ProGrard, jarjar和dx多个工具组成的集合。
Jack工具链带来了以下优势:
AOSP中可以找到;欢迎合作伙伴贡献。
加快编译速度
Jack对降低编译时间有具体的支持:pre-dexing,增量编译和Jack编译服务器。
处理压缩,混淆,重新打包和多dex
不再需要使用像ProGuard之类单独的包。
图1. Java概览
.jack库格式
Jack拥有它自己的文件格式.jack,它包含了针对库的预编译dex代码,可以允许快速编译(pre-dex)。
图2. Jack库文件内容
Jill工具可以将现有的.jar库文件转换成库格式,如下图所示。
图3. 导入现有的.jar库的工作流
编译Android时使用Jack
为了使用Jack,你无需做任何不同的事情 - 只管使用标准的makefile命令来编译你的整体项目。Jack是M版本默认的Android编译工具链。
第一次使用Jack时,它会在你的电脑上启动一个本地Jack编译服务器:
这个服务器带来了内在的加速,因为它避免了在每一次编译时启动一个新的JRE JVM主机,加载Jack代码,初始化Jack和准备JIT。同时在小型的编译中它也提供了很好的编译时间(例如,增量模式)。
这个服务器也是控制并行Jack编译数量的一个短期解决方案,因此可以避免你的电脑过载(内存和磁盘问题),因为它限制了并行编译的数量。
在没有编译一段空闲时间之后,Jack服务器会关闭自己。它在本地接口使用了两个TCP端口,因此对外并不可用。通过编辑$HOME/.jack文件可以修改所有的这些参数(并行编译的数量,超时时间,端口号,等等)。
$HOME/.jack文件
$HOME/.jack文件包含了Jack服务器的变量设置,这些设置以bash的语法的形式。
这里是可用的设置与它们的定义与默认值:
SERVER=true
启用Jack服务器特性。
SERVER_PORT_SERVICE=8072 设置编译目的的TCP端口。
SERVER_PORT_ADMIN=8073 设置管理母的的TCP端口。
SERVER_COUNT=1 目前不使用。
SERVER_NB_COMPILE=4 允许最大的并行编译数量。
SERVER_TIMEOUT=60 无编译时服务器关闭自身前等待的时间(单位为秒)
SERVER_LOG=${SERVER_LOG:=$SERVER_DIR/jack-$SERVER_PORT_SERVICE.log} 服务器日志写入的文件。默认情况下,该变量可以被环境变量覆盖。
JACK_VM_COMMAND=${JACK_VM_COMMAND:=java} 主机上启动JVM的默认命令。默认情况下,该变量可以被环境变量覆盖。
[非翻译]目前的默认设置已经不是上面的值,所以这里的默认值仅供参考。
而且$HOME/.jack文件也找不到,只能找到$HOME/.jack-settings文件。
Jack故障处理
如果编译时电脑无响应或以“Out of memory error”的错误编译失败
你可以通过编辑$HOME/.jack文件将SERVER_NB_COMPILE改为一个较低的值来降低Jack同时进行的编译数量来改进这个状况。
[非翻译]这个解决方案在实际当中并不能解决问题,具体解决方案参考我前边的文章 。
如果以“Cannot launch background server”的错误编译失败
最可能的原因是TCP端口已经被使用。尝试编辑$HOME/.jack文件(SERVER_PORT_SERVICE和SERVER_PORT_ADMIN变量)来修复。
如果问题没有解决,情上报并且附上你的编译日志和Jack服务器日志(查看下方’查找Jack日志’了解从哪里找到服务器日志文件)。为了移除这个状况,编辑$HOME/.jack文件将SERVER改为false来禁用Jack编译服务器。不幸的是,这将会显著降低编译速度并且强制你启动make -j(make的选项-l)。
如果编译被卡住没有任何进展
请上报给我们并且提供以下附加信息(尽可能):
卡住所在的命令行
命令行的输出
执行jack-admin server-stat的结果
$HOME/.jack文件
服务器状态为dumped时的服务器日志内容。为了获取这些
通过运行jack-admin list-server找出Jack后台服务器
发送kill -3命令到该服务器,将它的状态导出到日志文件
查看下面的找出Jack日志,来定位服务器日志文件
执行ls -lR $TMPDIR/jack-$USER命令的结果
运行ps j -U $USER命令的结果
你可以通过杀掉Jack后台服务器(使用jack-admin kill-server)来解除目前的情况,然后删除你的临时目录(/tmp或者$TMPDIR)下的jack-$USER内的临时文件夹。
如果遇到其它错误
要上报bugs或者请求特性,请使用我们的公共问题跟踪器,在
上可用。使用或者模板。请将Jack的日志附到bug上报。
查找Jack日志
如果你使用dist target运行make命令,Jack的日志文件在$ANDROID_BUILD_TOP/out/dist/logs/jack-server.log
否则你可以通过运行jack-admin server-log命令来查找
如果是可再生Jack失败,你可以通过设置一个变量得到更为详细的日志,如下所示:
$ export ANDROID_JACK_EXTRA_ARGS="--verbose debug --sanity-checks on -D
sched.runner=single-threaded"
然后使用标准的makefile命令来编译整个项目或者你的项目并且附上它的标准输出和错误。
移除详细的编译日志可以使用:
$ unset ANDROID_JACK_EXTRA_ARGS
Jack的局限性
使用Jack的特性
Jack支持Java 1.7并且继承了如下所述的额外特性。
当生成Jack库文件时,作为pre-dex,库文件的.dex被生成和存储在.jack库文件的内部。当编译时,Jack从每个库中复用这些pre-dex。
所有的库都进行了pre-dexed。
图4. 带有pre-dex的Jack库
目前,如果在编译时使用了压缩/混淆/重新打包,那么Jack不能复用pre-dex的库。
增量编译指的是从上次编译后,只有触摸过的部分和它们的依赖会被重新编译。当修改只发生在一小部分时,增量编译要比全部编译快很多。
当遗留的压缩,混淆,重新打包或者多dex启用时,增量编译会关闭。
启用增量编译
目前,增量编译没有默认开启。在你想要增量编译的项目的Android.mk文件中加入下面的代码:
LOCAL_JACK_ENABLED := incremental
注意:使用Jack第一次编译你的项目时,如果某些依赖没有构建,使用mma命令构建它们,然后你就可以使用标准的构建命令。
压缩和混淆
Jack支持压缩和混淆并且可以使用混淆配置文件来开启压缩和混淆特性。这里是支持和忽略的选项:
支持的通用选项
通用选项包括以下:
-basedirectory
// 只支持1个输出jar
-libraryjars
-keepclassmembers
-keepclasseswithmembers
-keepnames
-keepclassmembernames
-keepclasseswithmembernames
-printseeds
支持的压缩选项
压缩选项包括以下:
-dontshrink
支持的混淆选项
混淆选项包括以下:
-dontobfuscate
-printmapping
-applymapping
-obfuscationdictionary
-classobfuscationdictionary
-packageobfuscationdictionary
-useuniqueclassmembernames
-dontusemixedcaseclassnames
-keeppackagenames
-flattenpackagehierarchy
-repackageclasses
-keepattributes
-adaptclassstrings
忽略的选项
忽略的选项包含以下:
-dontoptimize
// Jack不优化
-dontpreverify
// Jack不预先验证
-skipnonpubliclibraryclasses
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-keepdirectories
-forceprocessing
-printusage
-whyareyoukeeping
-optimizations
-optimizationpasses
-assumeonsideeffects
-allowaccessmodification
-mergeinterfacesaggressively
-overloadaggressively
-microedition
-ignorewarnings
-printconfiguration
其它选项将会产生错误。
Jack使用jarjar的配置文件来进行重新打包。
Jack与”rule”规则类型兼容,但是不兼容”zap”或”keep”规则类型。如果你需要”zap”或”keep”规则类型,请发送一份特性请求并且附上在你的app里要如何使用这些特性的描述。
由于dex文件对于方法的上限是65K,所以超过65K方法的app必须要分成多个dex文件(有关多dex的更多信息参考 )。
Jack提供原生与遗留的多dex的支持。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:13806次
积分:1145
积分:1145
排名:千里之外
原创:48篇
(1)(8)(4)(2)(3)(3)(2)(1)(2)(12)(6)(2)(1)(4)(12)(1)(2)(1)如何看待Android新的编译工具链Jack_百度知道android-ndk-r8d使用独立编译工具链(官方文档中文版)
使用ANDROID作为一个独立的编译器工具链
======================================================
该文档解释了如何做:
1/选择你的工具链:
----------------------------
做任何东西之前,你需要决定是否你的独立的工具链是基于arm的设备,基于x86的,或基于mips的哪一个。
每个架构对应一个不同的工具链的名字。例如:
arm-linux-androideabi-4.6&& =&
targeting ARM-based Android devices
x86-4.6&&&&&&&&&&&&&&&&&&&&
=& targeting x86-based Android devices
mipsel-linux-android-4.6&&&
=& targeting MIPS-based Android devices
2/选择目录切换为sysroot:
--------------------------
第二件事你需要知道的是,你需要知道安卓原生API的级别。每一个都提供了一个不同的各种api,
这是记录在doc/STABLE-APIS.html和对应 $NDK/platforms的子目录中
定义'sysroot'包含目标系统头文件和库。通常,如下:
SYSROOT=$NDK/platforms/android-/arch-/
是API 级别 号,是架构(支持arm,x86,mips)。
例如:如果目标android是2.2,如下:
SYSROOT=$NDK/platforms/android-8/arch-arm
重要:注意X86和MIPS架构只在android-9或更新支持。
3/调用编译器(最困难一步)
----------------------------------------
使用--sysroot选项来指出系统文件位置在哪。例如:
&&& export
CC="$NDK/toolchains//prebuilt//bin/gcc --sysroot=$SYSROOT"
&&& $CC -o foo.o
&是工具链的名字,是系统主机标志,是工具链特定前缀,例如在linux下使用NDK
r5工具链,如下:
&&& export
CC="$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc
--sysroot=$SYSROOT"
可见,这是很繁琐,但是有效!
重要事项:
直接使用NDK的工具链(非独立版工具链)有严重的限制:
&&& 你不能使用任何C++
STL(STLport或GNU libstdc++)。也没有异常和运行时类型检查。
4/调用编译器(最简单一步):
----------------------------------------
NDK允许您创建一个“定制”工具链安装。例如,参考下面的命令:
& $NDK/build/tools/make-standalone-toolchain.sh
--platform=android-5 --install-dir=/tmp/my-android-toolchain
这将简历一个路径/tmp/my-android-toolchain,包含复制的 android-5/arch-arm sysroot
工具链 文件。
注意默认使用ARM GCC 4.6 工具链。使用'--arch=x86'设定x86 GCC
4.6,或'--arch=mips'设定MIPS GCC 4.6,或者'--toolchain='来设。例如
--toolchain=x86-4.4.3&&&&&&&&&&&&&&&&&
# select x86 GCC 4.4.3 compiler
--toolchain=arm-linux-androideabi-4.7& # select
ARM GCC 4.7 compiler
--toolchain=mipsel-linux-android-4.6&&
# select MIPS GCC 4.6 compiler, same as --arch=mips
&'--llvm-version=3.1'可以复制clang/llvm
3.1或使用--toolchain with '-clang3.1'后缀,例如:
--toolchain=arm-linux-androideabi-clang3.1& # same
as --arch=arm --llvm-version=3.1
稍后可用类似如下(导入环境变量):
PATH=/tmp/my-android-toolchain/bin:$PATH
CC=arm-linux-androideabi-gcc&& #
or export CC=clang
CXX=arm-linux-androideabi-g++& # or export
CXX=clang++
注意未使用--install-dir,make-standalone-toolchain.sh会打包在/tmp/ndk/.tar.bz2。
使你可以很容易重新发布文件。
另一个很便利的地方:独立工具链包含GNU libstdc++(支持异常和RTTI机制),只要你链接到它。
--help查看更多选项和信息。
重要:工具链的二进制文件不依赖或包含特定于主机的路径,
&  换句话说,他们可以安装在任何位置,甚至如果你需要移动。
注意:你仍然可以使用--sysroot选项在新的工具链,但它现在只是可选的!
5/关于Clang
---------------------
Clang/clang++使用同样的编译器,链接器,头文件,库文件和GNU libstdc++在独立的包中。
Clang/clang++是个脚本,创建时使用-target指定到特定架构。
例如:在ARM独立包,clang是个单行:
&& `dirname $0`/clang31 -target
armv5te-none-linux-androideabi "$@"
clang++是另一行:
&& `dirname $0`/clang++31 -target
armv5te-none-linux-androideabi "$@"
注意arm,使用-march=armv7-a -mthumb clang将改变-target
& 1/ With "-march=armv7-a", -target becomes
armv7-none-linux-androideabi
& 2/ With "-mthumb", -target becomes
thumb-none-linux-androideabi
& 3/ With both, -target becomes
thumbv7-none-linux-androideabi
你可以重写-target。
做额外的工作替换gcc/g++在Makefile里。怀疑时,使用下面检查:
& 1/ Add option "-v" to dump commands compiler
driver issues
& 打印命令编译器驱动问题
& 2/ Add option "-###" to dump command line
options, including those
implicitly predefined.
打印选项命令行,包含隐式预定义的
& 3/ Use "-x c /dev/null -dM -E" to dump
predefined preprocessor definitions
& 打印预定义的预处理器定义
& 4/ Add option "-save-temps" and compare the
preprocessed files *.i or *.ii
& 比较预处理文件
especially the GCC compatibility section.
6/应用二进制接口兼容性:
---------------------
ARM工具链生成的代码应该默认兼容官方Android
'armeabi'的应用二进制接口(参照/CPU-ARCH-ABIS.html)
推荐使用-mthumb 编译器标识来强制生成16位Thumb-1指令(默认是32位ARM的指令)
如果你的目标是'armeabi-v7a'的应用二进制接口,你需要确保使用如下标志:
& CFLAGS='-march=armv7-a -mfloat-abi=softfp
-mfpu=vfpv3-d16'
注意:第一个标志启用Thumb-2指令,第二个启用H/W浮点处理器指令功能,
确保用核心寄存器传递浮点参数,它对于ABI兼容性来说是关键。不要分开使用这些开关!
如果你想使用Neon指令(ARM的单指令多数据技术),你需要再增多一个编译器开关:
& CFLAGS='-march=armv7-a -mfloat-abi=softfp
-mfpu=neon'
Note that this forces the use of VFPv3-D32, as per the ARM
specification.
注意它强制使用VFPv3-D32(注:VFPv3是vector floating point v3的缩写,
即向量浮点第三版,D32应该是指32个双精度浮点寄存器),根据ARM规范。
Also, make sure the following two flags are provided to
还有,确保下链接器使用以下两个标志。
& LDFLAGS='-march=armv7-a
-Wl,--fix-cortex-a8'
注意:第一个标志连接器选择特别为armv7-a设计的libgcc.a libgcov.a和crt*.o。
第二个标志是绕过一些Cortex-A8 CPU bug的实现所需。
如果上面的东西对你不起作用,最好不要使用独立工具链,还是坚持使用NDK构建系统,
它将为你处理所有细节。
当目标是x86 ABI或MIPS ABI时,你不需要使用人任何特殊编译器标志。
7/ 警告和限制:
--------------------------
7.1/Windows支持:
- - - - - - - - - - -
Windows二进制文件不依赖于Cygwin。好消息是它们会跑得更快,
而坏消息是它们不理解Cygwin的目录格式,像/cygdrive/c/foo/bar(但可以理解C:/foo/bar)
NDK构建系统确保从Cygwin中传递的所有路径被自动翻译,为你处理其它威胁。
如果你拥有一个定制构建系统,你可能需要自己处理问题。
注意:现在没计划支持Cygwin / MSys,但欢迎贡献。详细请联系android-ndk论坛
7.2/wchar_t支持:
- - - - - - - - - - -
正如文档所写的,Android平台在Android 2.3之前没有真正支持wchar_t。
用实际的术语说,这意味着:
如果你的目标平台是android-9或更高,wchar_t的大小是4字节,则在C库中大多数
宽字符函数可用(例外的是多字节的编码解码函数和wsprintf/wsscanf)
如果你的目标是较早的API级别,wchar_t的大小将是1字节,任何宽字符函数都不可工作。
我们建议所有开发者避免对wchar_t类型的依赖,而是转向更好的表示。
在Android中提供的支持只出现在帮助你迁移现存代码的地方。
7.3/ 异常、运行时类型识别和STL(标准模板库):
- - - - - - - - - - - - - - -
工具链二进制文件默认支持C++异常和RTTI(运行时类型识别)。
它们默认是打开的,所以如果你想在构建使用它们的代码时关闭它们,
请使用-fno-exceptions和-fno-rtti(例如,为了生成更小的机器代码)。
注意:你将需要显式地用libsupc++链接,如果你使用这些特性。
为了做到这点,当链接二进制文件时使用-lsupc++,
像这样:(注:这里要小心,是libsupc++不是libstdc++!)
arm-linux-androideabi-g++ .... -lsupc++
7.4/ C++ STL 支持:
- - - - - - - - - - -
工具链还带有一个可用的GNU libstdc++实现,它提供一个工作的C++标准模板库实现。
你将需要显式地用-lstdc++链接以使用它。
& * 使用-lstdc++
来链接静态库版本。这确保了所需C++STL代码包含进你的最终二进制文件。
这是一个生成单独共享库或执行文件的办法。
&&& This is the
recommended way to do it.
这是推荐的方式。
使用-lgnustl_shared来链接静态库版本。如果你有几个相关的需要运行时在同样的地址空间
的共享库或执行文件,这是必须的。
(一些全局变量需要唯一的定义,不适用于每一个可执行文件链接静态的libstdc++)
如果你使用此选项,你需要确保libgnustl_shared.so拷贝到你设备上以便载入。文件在:
$TOOLCHAIN/arm-linux-androideabi/lib/& for ARM
toolchains.
$TOOLCHAIN/i686-linux-android/lib/&&&&
for x86 ones.
$TOOLCHAIN/mipsel-linux-android/lib/&&
for MIPS toolchains.
&&& 重要:GNU
libstdc++ 授权在GPLv3,有一个例外,查看如下URL来详细描述:
如果你不能干遵守它的要求,你不能发布这个共享库,不能使用在你的工程中。
共享版GNU libstdc++不被叫做libstdc++.so的原因是这将会在运行时和最小C++运行时库
(/system/lib/libstdc++.so)冲突。这强制了一个GNU ELF库的新名字。对于静态库这不是个问题
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。如何看待Android新的编译工具链Jack_百度知道

我要回帖

更多关于 关闭 jack 编译 的文章

 

随机推荐