Rover12421's Blog

The End.

Build ShakaAapt

为了提高ShakaApktool的兼容性,需要订制一个aapt,我称它为ShakaAapt.这篇文章主要是记录ShakaAapt的编译过程,以及搭建ShakaAapt的修改环境.

为了编译aapt你需要下载一份Android源码.最好是最新的.你可以完整编译Android源码来得到aapt.但是这不是我的目的.我的目的是用最少的依赖来编译我的ShakaAapt,以减少编译时间,加快以后修改代码测试速度.

Linux/Windows版本的ShakaAapt都在ubunut下编译.Mac Os的版本我在虚拟机上安装的YOSEMITE上编译.

先来假设几个条件 :

  • $RootDir/ : 整个环境的根目录
  • $RootDir/android-last/ : 最新版本的android源码目录.repo下载的源码就是这个目录.
  • $RootDir/ShakaAapt/ : ShakaAapt相关源文件,配置文件,等等.
  • $RootDir/ShakaAaptBin/ : 用来存放编译好的ShakaAapt二进制文件,也就是用到ShakaApktool里面的文件

Ubuntu下编译Linux和windows版本

参考https://source.android.com/source/initializing.html安装必要的依赖.

准备ShakaAapt相关文件.在linux上使用软链接的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
cd $RootDir/ShakaAapt/
ln -s ../android-last/build
mkdir development
mkdir external
mkdir frameworks
ln -s ../android-last/libcore
ln -s ../android-last/libnativehelper/
ln -s ../android-last/Makefile
ln -s ../android-last/prebuilts
mkdir sdk
mkdir system
cd development
../../android-last/development/build
cd ../external
ln -s ../../android-last/external/compiler-rt
ln -s ../../android-last/external/expat
ln -s ../../android-last/external/libcxx
ln -s ../../android-last/external/libcxxabi
ln -s ../../android-last/external/libpng
ln -s ../../android-last/external/zlib
cd ../frameworks
mkdir base
mkdir native
cd base
mkdir include
mkdir libs
mkdir tools
cd include
ln -s ../../../../android-last/frameworks/base/include/androidfw
cd ../libs
ln -s ../../../../android-last/frameworks/base/libs/androidfw
cd ../tools
ln -s ../../../../android-last/frameworks/base/tools/aapt
cd ../../native
ln -s ../../../android-last/frameworks/native/include
cd ../../sdk
ln -s ../../android-last/sdk/build
cd ../system
ln -s ../../android-last/system/core
cd ../..

看看完整的目录树:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$RootDir/ShakaAapt>  tree -L 4
.
├── build -> ../android-last/build
├── development
│   └── build -> ../../android-last/development/build
├── external
│   ├── compiler-rt -> ../../android-last/external/compiler-rt
│   ├── expat -> ../../android-last/external/expat
│   ├── libcxx -> ../../android-last/external/libcxx
│   ├── libcxxabi -> ../../android-last/external/libcxxabi
│   ├── libpng -> ../../android-last/external/libpng
│   └── zlib -> ../../android-last/external/zlib
├── frameworks
│   ├── base
│   │   ├── include
│   │   │   └── androidfw -> ../../../../android-last/frameworks/base/include/androidfw
│   │   ├── libs
│   │   │   └── androidfw -> ../../../../android-last/frameworks/base/libs/androidfw
│   │   └── tools
│   │       └── aapt -> ../../../../android-last/frameworks/base/tools/aapt
│   └── native
│       └── include -> ../../../android-last/frameworks/native/include
├── libcore -> ../android-last/libcore
├── libnativehelper -> ../android-last/libnativehelper/
├── Makefile -> ../android-last/Makefile
├── prebuilts -> ../android-last/prebuilts
├── sdk
│   └── build -> ../../android-last/sdk/build
└── system
    └── core -> ../../android-last/system/core

比起完整的Android代码,这个代码量是不是很少了啊.

下面是编译脚本的编写.看文件名就知道是干嘛的,就不做太多的解释了.

  • $RootDir/build_ShakaAapt_linux-x86.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#! /bin/bash

cd ShakaAapt
export USE_CCACHE=1
export CCACHE_DIR=$(pwd)/.ccache
prebuilts/misc/linux-x86/ccache/ccache -M 50G
. build/envsetup.sh
lunch sdk-eng
OUT_DIR=out-x86 make LOCAL_MULTILIB=32 aapt -j4
strip out-x86/host/linux-x86/bin/aapt
strip out-x86/host/linux-x86/lib/libc++.so
mkdir -p ../ShakaAaptBin/linux-x86/bin
mkdir -p ../ShakaAaptBin/linux-x86/lib
cp out-x86/host/linux-x86/bin/aapt ../ShakaAaptBin/linux-x86/bin/aapt
cp out-x86/host/linux-x86/lib/libc++.so ../ShakaAaptBin/linux-x86/lib/libc++.so
  • $RootDir/build_ShakaAapt_linux-x86_64.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#! /bin/bash

cd ShakaAapt
export USE_CCACHE=1
export CCACHE_DIR=$(pwd)/.ccache
prebuilts/misc/linux-x86/ccache/ccache -M 50G
. build/envsetup.sh
lunch sdk-eng
OUT_DIR=out-x86_64 make LOCAL_MULTILIB=64 aapt -j4
strip out-x86_64/host/linux-x86/bin/aapt
strip out-x86_64/host/linux-x86/lib64/libc++.so
mkdir -p ../ShakaAaptBin/linux-x86_64/bin
mkdir -p ../ShakaAaptBin/linux-x86_64/lib64
cp out-x86_64/host/linux-x86/bin/aapt ../ShakaAaptBin/linux-x86_64/bin/aapt
cp out-x86_64/host/linux-x86/lib64/libc++.so ../ShakaAaptBin/linux-x86_64/lib64/libc++.so
  • $RootDir/build_ShakaAapt_windows-x86.sh
1
2
3
4
5
6
7
8
9
10
11
12
#! /bin/bash

cd ShakaAapt
export USE_CCACHE=1
export CCACHE_DIR=$(pwd)/.ccache
prebuilts/misc/linux-x86/ccache/ccache -M 50G
. build/envsetup.sh
lunch sdk-eng
USE_MINGW=1 OUT_DIR=out-x86 LOCAL_MULTILIB=32 make aapt
strip out-x86/host/windows-x86/bin/aapt.exe
mkdir -p ../ShakaAaptBin/windows-x86/bin
cp out-x86/host/windows-x86/bin/aapt.exe ../ShakaAaptBin/windows-x86/bin/aapt.exe

这里用ccache来加快编译速度.如果你不想要ccache,可以把相关位置去掉.也就是下面3行

1
2
3
export USE_CCACHE=1
export CCACHE_DIR=$(pwd)/.ccache
prebuilts/misc/linux-x86/ccache/ccache -M 50G

更多关于ccache请查看:https://source.android.com/source/building-running.html#using-ccache

脚本编写好了,需要编译那个平台的aapt就执行对应平台的脚本.

注意,编译windows平台,需要另外安装一些依赖包:

sudo apt-get install mingw32 tofrodos

windows版本,目前还不支持64bit的编译.不用纠结这个了,现在sdk中的全是x86的.

虚拟机中编译MacOs版本

首先是环境设定,Mac Os默然的文件系统是不区分大小写的,但是Android源码是要求区分大小写的.

可以参考https://source.android.com/source/initializing.html#setting-up-a-mac-os-x-build-environment来创建一块区分大小写的磁盘镜像,然后把源码拷贝到这个磁盘镜像中.

我用的是虚拟机,所以我选择了添加一块区分大小写敏感的硬盘.这里就不详细解说了.

同样的,我不需要全部的源码,下面是我写的一个编译ShakaAapt所需全部源码的同步脚本

注意,接下来的$RootDir全是MacOs上的根目录了.

  • $RootDir/rsync_ShakaApktool.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#! /bin/bash

SRCROOT="/Volumes/VMware Shared Folders/Develop/android/source/android-last"
DESROOT="/Volumes/OSXShareDisk/Develop/android/source/ShakaAapt"

rsync -aP "$SRCROOT/Makefile" "$DESROOT/Makefile"
array=( \
  build libnativehelper prebuilts \
  development/build \
  frameworks/base/include \
  frameworks/base/tools/aapt \
  frameworks/base/libs/androidfw \
  frameworks/native/include \
  external/compiler-rt \
  external/expat \
  external/libcxx \
  external/libcxxabi \
  external/libpng \
  external/zlib \
  sdk/build \
  system/core \
  )

for var in ${array[@]};do
echo $var
mkdir -p "$DESROOT/$var/"
rsync -aP --delete \
   --exclude .git \
  "$SRCROOT/$var/" "$DESROOT/$var/"
done

$SRCROOT : 从目录名称上可以看出,这个目录是共享Ubuntu的目录,这个目录就是Ubuntu上存放Android源码的目录.

DESROOT : 是挂着的另外一块区分大小写的MacOs分区.

目录结果和Ubuntu上是相同的.从上面的脚本可以看出,我这里的$RootDir目录实际是/Volumes/OSXShareDisk/Develop/android/source

如果源码没更新,只修改了部分aapt的源码,再次同步也可以只同步aapt相关的源码就行了,加快同步速度.

  • $RootDir/rsync_ShakaApktool_only_aapt.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#! /bin/bash

SRCROOT="/Volumes/VMware Shared Folders/Develop/android/source/android-last"
DESROOT="/Volumes/OSXShareDisk/Develop/android/source/ShakaAapt"

rsync -aP "$SRCROOT/Makefile" "$DESROOT/Makefile"
array=( \
  frameworks/base/tools/aapt \
  )

for var in ${array[@]};do
echo $var
mkdir -p "$DESROOT/$var/"
rsync -aP --delete \
   --exclude .git \
  "$SRCROOT/$var/" "$DESROOT/$var/"
done

源码同步过后,就是编译了,一样的,先写编译脚本,避免每次都执行一堆命令.

  • $RootDir/build_ShakaAapt_maxos-x86.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
#! /bin/bash

cd ShakaAapt
export USE_CCACHE=1
export CCACHE_DIR=$(pwd)/.ccache
prebuilts/misc/darwin-x86/ccache/ccache -M 50G
. build/envsetup.sh
lunch sdk-eng
OUT_DIR=out-x86 make LOCAL_MULTILIB=32 aapt -j4
mkdir -p "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86/bin"
mkdir -p lib "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86/lib"
cp out-x86/host/darwin-x86/bin/aapt "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86/bin/aapt"
cp out-x86/host/darwin-x86/lib/libc++.dylib "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86/lib/libc++.dylib"
    • $RootDir/build_ShakaAapt_maxos-x86_64.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
#! /bin/bash

cd ShakaAapt
export USE_CCACHE=1
export CCACHE_DIR=$(pwd)/.ccache
prebuilts/misc/darwin-x86/ccache/ccache -M 50G
. build/envsetup.sh
lunch sdk-eng
OUT_DIR=out-x86_64 make LOCAL_MULTILIB=64 aapt -j4
mkdir -p "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86_64/bin"
mkdir -p "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86_64/lib64/"
cp out-x86_64/host/darwin-x86/bin/aapt "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86_64/bin/aapt"
cp out-x86_64/host/darwin-x86/lib64/libc++.dylib "/Volumes/VMware Shared Folders/Develop/android/source/ShakaAaptBin/darwin-x86_64/lib64/libc++.dylib"

执行相应的脚本就可以编译了.

使用Clion查看修改aapt源码的配置

我觉得用Clion来查看修改aapt的源码还是很爽的.

先创建一个项目,然后在项目目录下用软链接链接源码,windows平台没有软链接,建议在用Linux/Unix平台下使用.

1
2
3
4
5
6
7
8
cd $ClionProject
ln -s $RootDir/android-last/frameworks/base/tools/aapt
mkdir include
mkdir libs
cd include
ln -s $RootDir/android-last/frameworks/base/include/androidfw
cd ../libs
ln -s $RootDir/android-last/frameworks/base/libs/androidfw

看下目录树:

1
2
3
4
5
6
7
8
$ClionProject>  tree -L 2
.
├── aapt -> $RootDir/android-last/frameworks/base/tools/aapt
├── CMakeLists.txt
├── include
│   └── androidfw -> $RootDir/android-last/frameworks/base/include/androidfw
└── libs
    └── androidfw -> $RootDir/android-last/frameworks/base/libs/androidfw

修改CMakeLists.txt文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
cmake_minimum_required(VERSION 3.2)
project(ShakaAapt)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(AAPTROOT aapt)
set(aaptMain ${AAPTROOT}/Main.cpp)
set(aaptSources
    ${AAPTROOT}/AaptAssets.cpp
    ${AAPTROOT}/AaptConfig.cpp
    ${AAPTROOT}/AaptUtil.cpp
    ${AAPTROOT}/AaptXml.cpp
    ${AAPTROOT}/ApkBuilder.cpp
    ${AAPTROOT}/Command.cpp
    ${AAPTROOT}/CrunchCache.cpp
    ${AAPTROOT}/FileFinder.cpp
    ${AAPTROOT}/Images.cpp
    ${AAPTROOT}/Package.cpp
    ${AAPTROOT}/pseudolocalize.cpp
    ${AAPTROOT}/Resource.cpp
    ${AAPTROOT}/ResourceFilter.cpp
    ${AAPTROOT}/ResourceIdCache.cpp
    ${AAPTROOT}/ResourceTable.cpp
    ${AAPTROOT}/SourcePos.cpp
    ${AAPTROOT}/StringPool.cpp
    ${AAPTROOT}/WorkQueue.cpp
    ${AAPTROOT}/XMLNode.cpp
    ${AAPTROOT}/ZipEntry.cpp
    ${AAPTROOT}/ZipFile.cpp
)

set(LIB_androidfw_ROOT libs/androidfw)
set(LIB_androidfw_commonSources
    ${LIB_androidfw_ROOT}/Asset.cpp
    ${LIB_androidfw_ROOT}/AssetDir.cpp
    ${LIB_androidfw_ROOT}/AssetManager.cpp
    ${LIB_androidfw_ROOT}/misc.cpp
    ${LIB_androidfw_ROOT}/ObbFile.cpp
    ${LIB_androidfw_ROOT}/ResourceTypes.cpp
    ${LIB_androidfw_ROOT}/StreamingZipInflater.cpp
    ${LIB_androidfw_ROOT}/TypeWrappers.cpp
    ${LIB_androidfw_ROOT}/ZipFileRO.cpp
    ${LIB_androidfw_ROOT}/ZipUtils.cpp)

set(SOURCE_FILES ${SOURCE_FILES}
    ${aaptMain}
    ${aaptSources}
    ${LIB_androidfw_commonSources}
)

include_directories(${AAPTROOT})
include_directories(include)

#set(SOURCE_FILES main.cpp)
add_executable(ShakaAapt ${SOURCE_FILES})

现在就可以很舒服的修改aapt源码了,虽然很多引用没有,但是aapt相关部分源码已经可以正常跳转,查找引用了.这就足够了,反正也不是在clion中编译.当然要是你有强迫症,请自行补全其他引用.

Comments