xref: /aosp_15_r20/external/robolectric/scripts/build-android.sh (revision e6ba16074e6af37d123cb567d575f496bf0a58ee)
1#!/bin/bash
2#
3# This script builds the AOSP Android jars, and installs them in your local
4# Maven repository. See: http://source.android.com/source/building.html for
5# more information on building AOSP.
6#
7# Usage:
8#   build-android.sh <android repo path> <android version> <robolectric version>
9#
10# For a tutorial check scripts/README.md
11
12set -ex
13
14function usage() {
15    echo "Usage: ${0} <android repo path> <android-version> <robolectric-sub-version> <output directory>"
16}
17
18if [[ $# -ne 4 ]]; then
19    usage
20    exit 1
21fi
22
23buildRoot=$1
24
25if [[ ! -d $buildRoot ]]; then
26    echo $buildRoot is not a directory
27    usage
28    exit 1
29fi
30
31if [[ -z "${SIGNING_PASSWORD}" ]]; then
32    echo "Please set the GPG passphrase as SIGNING_PASSWORD"
33    exit 1
34fi
35
36buildRoot=$(cd $buildRoot; pwd)
37
38ANDROID_VERSION=$2
39ROBOLECTRIC_SUB_VERSION=$3
40
41SCRIPT_DIR=$(cd $(dirname "$0"); pwd)
42
43ANDROID_SOURCES_BASE=${buildRoot}
44FRAMEWORKS_BASE_DIR=${ANDROID_SOURCES_BASE}/frameworks/base
45FRAMEWORKS_RAW_RES_DIR=${FRAMEWORKS_BASE_DIR}/core/res/
46ROBOLECTRIC_VERSION=${ANDROID_VERSION}-robolectric-${ROBOLECTRIC_SUB_VERSION}
47
48# Intermediate artifacts
49ANDROID_RES=android-res-${ANDROID_VERSION}.apk
50ANDROID_EXT=android-ext-${ANDROID_VERSION}.jar
51ANDROID_CLASSES=android-classes-${ANDROID_VERSION}.jar
52
53# API specific paths
54LIB_PHONE_NUMBERS_PKG="com/android/i18n/phonenumbers"
55LIB_PHONE_NUMBERS_PATH="external/libphonenumber/java/src"
56
57# Final artifact names
58ANDROID_ALL=android-all-${ROBOLECTRIC_VERSION}.jar
59ANDROID_ALL_POM=android-all-${ROBOLECTRIC_VERSION}.pom
60ANDROID_ALL_SRC=android-all-${ROBOLECTRIC_VERSION}-sources.jar
61ANDROID_ALL_DOC=android-all-${ROBOLECTRIC_VERSION}-javadoc.jar
62ANDROID_BUNDLE=android-all-${ROBOLECTRIC_VERSION}-bundle.jar
63
64TZDATA_ARCH="generic_x86"
65
66build_platform() {
67    NATIVE_ARTIFACTS=()
68
69    if [[ "${ANDROID_VERSION}" == "4.1.2_r1" ]]; then
70        ARTIFACTS=("core" "services" "framework" "android.policy" "ext")
71        SOURCES=(core/java graphics/java media/java location/java opengl/java policy/src sax/java services/java telephony/java wifi/java)
72    elif [[ "${ANDROID_VERSION}" == "4.2.2_r1.2" ]]; then
73        ARTIFACTS=("core" "services" "telephony-common" "framework" "android.policy" "ext")
74        SOURCES=(core/java graphics/java media/java location/java opengl/java policy/src sax/java services/java telephony/java wifi/java)
75    elif [[ "${ANDROID_VERSION}" == "4.3_r2" ]]; then
76        ARTIFACTS=("core" "services" "telephony-common" "framework" "android.policy" "ext")
77        SOURCES=(core/java graphics/java media/java location/java opengl/java policy/src sax/java services/java telephony/java wifi/java)
78    elif [[ "${ANDROID_VERSION}" == "4.4_r1" ]]; then
79        ARTIFACTS=("core" "services" "telephony-common" "framework" "framework2" "framework-base" "android.policy" "ext" "webviewchromium" "okhttp" "conscrypt")
80        SOURCES=(core/java graphics/java media/java location/java opengl/java policy/src sax/java services/java telephony/java wifi/java)
81    elif [[ "${ANDROID_VERSION}" == "5.0.2_r3" ]]; then
82        ARTIFACTS=("core-libart" "services" "telephony-common" "framework" "android.policy" "ext" "okhttp" "conscrypt")
83        SOURCES=(core/java graphics/java media/java location/java opengl/java policy/src sax/java services/java telephony/java wifi/java)
84        TZDATA_ARCH="generic"
85    elif [[ "${ANDROID_VERSION}" == "5.1.1_r9" ]]; then
86        ARTIFACTS=("core-libart" "services" "telephony-common" "framework" "android.policy" "ext" "okhttp" "conscrypt")
87        SOURCES=(core/java graphics/java media/java location/java opengl/java policy/src sax/java services/java telephony/java wifi/java)
88        TZDATA_ARCH="generic"
89    elif [[ "${ANDROID_VERSION}" == "6.0.1_r3" ]]; then
90        ARTIFACTS=("core-libart" "services" "services.accessibility" "telephony-common" "framework" "ext" "icu4j-icudata-jarjar" "okhttp" "conscrypt")
91        SOURCES=(core/java graphics/java media/java location/java opengl/java sax/java services/java telephony/java wifi/java)
92        LIB_PHONE_NUMBERS_PKG="com/google/i18n/phonenumbers"
93        LIB_PHONE_NUMBERS_PATH="external/libphonenumber/libphonenumber/src"
94        TZDATA_ARCH="generic"
95    elif [[ "${ANDROID_VERSION}" == "7.0.0_r1" ]]; then
96        ARTIFACTS=("core-libart" "services" "services.accessibility" "telephony-common" "framework" "ext" "okhttp" "conscrypt")
97        NATIVE_ARTIFACTS=("icu4j-icudata-host-jarjar" "icu4j-icutzdata-host-jarjar")
98        SOURCES=(core/java graphics/java media/java location/java opengl/java sax/java services/java telephony/java wifi/java)
99        LIB_PHONE_NUMBERS_PKG="com/google/i18n/phonenumbers"
100        LIB_PHONE_NUMBERS_PATH="external/libphonenumber/libphonenumber/src"
101    elif [[ "${ANDROID_VERSION}" == "7.1.0_r7" ]]; then
102        ARTIFACTS=("core-libart" "services" "services.accessibility" "telephony-common" "framework" "ext" "okhttp" "conscrypt")
103        NATIVE_ARTIFACTS=("icu4j-icudata-host-jarjar" "icu4j-icutzdata-host-jarjar")
104        SOURCES=(core/java graphics/java media/java location/java opengl/java sax/java services/java telephony/java wifi/java)
105        LIB_PHONE_NUMBERS_PKG="com/google/i18n/phonenumbers"
106        LIB_PHONE_NUMBERS_PATH="external/libphonenumber/libphonenumber/src"
107    elif [[ "${ANDROID_VERSION}" == "8.0.0_r4" ]]; then
108        ARTIFACTS=("robolectric_android-all")
109        NATIVE_ARTIFACTS=()
110        SOURCES=(core/java graphics/java media/java location/java opengl/java sax/java services/java telephony/java wifi/java)
111    else
112        echo "Robolectric: No match for version: ${ANDROID_VERSION}"
113        exit 1
114    fi
115
116    cd ${ANDROID_SOURCES_BASE}
117    if [ ! -d out/target/common/obj/JAVA_LIBRARIES ]; then
118      echo "Robolectric: You need to run 'sync-android.sh' first"
119      exit 1
120    fi
121}
122
123build_android_res() {
124    echo "Robolectric: Building android-res..."
125    cd ${FRAMEWORKS_BASE_DIR}/core/res; jar cf ${OUT}/${ANDROID_RES} .
126    src=${ANDROID_SOURCES_BASE}/out/target/common/obj/APPS/framework-res_intermediates/package-export.apk
127    cp $src ${OUT}/${ANDROID_RES}
128}
129
130build_android_ext() {
131    echo "Robolectric: Building android-ext..."
132    mkdir -p ${OUT}/ext-classes-modified/${LIB_PHONE_NUMBERS_PKG}
133    cd ${OUT}/ext-classes-modified; jar xf ${ANDROID_SOURCES_BASE}/out/target/common/obj/JAVA_LIBRARIES/ext_intermediates/classes.jar
134    cp -R ${ANDROID_SOURCES_BASE}/${LIB_PHONE_NUMBERS_PATH}/${LIB_PHONE_NUMBERS_PKG}/data ${OUT}/ext-classes-modified/${LIB_PHONE_NUMBERS_PKG}
135    cd ${OUT}/ext-classes-modified; jar cf ${OUT}/${ANDROID_EXT} .
136    rm -rf ${OUT}/ext-classes-modified
137}
138
139build_android_classes() {
140    echo "Robolectric: Building android-classes..."
141    mkdir ${OUT}/android-all-classes
142    for artifact in "${ARTIFACTS[@]}"; do
143        src=${ANDROID_SOURCES_BASE}/out/target/common/obj/JAVA_LIBRARIES/${artifact}_intermediates
144        cd ${OUT}/android-all-classes
145        if [[ -f ${src}/classes.jar ]]; then
146            jar xf ${src}/classes.jar
147        else
148            echo "Couldn't find ${artifact} at ${src}/classes.jar"
149            exit 1
150        fi
151    done
152
153    for artifact in "${NATIVE_ARTIFACTS[@]}"; do
154        jarPath=${ANDROID_SOURCES_BASE}/out/host/linux-x86/framework/${artifact}.jar
155        cd ${OUT}/android-all-classes
156        if [[ -f $jarPath ]]; then
157            jar xf $jarPath
158        else
159            echo "Couldn't find ${artifact} at $jarPath"
160            exit 1
161        fi
162    done
163    build_tzdata
164    build_prop
165    cd ${OUT}/android-all-classes; jar cf ${OUT}/${ANDROID_CLASSES} .
166    rm -rf ${OUT}/android-all-classes
167}
168
169build_tzdata() {
170  echo "Robolectric: Building tzdata..."
171  mkdir -p ${OUT}/android-all-classes/usr/share/zoneinfo
172  cp ${ANDROID_SOURCES_BASE}/out/target/product/${TZDATA_ARCH}/system/usr/share/zoneinfo/tzdata ${OUT}/android-all-classes/usr/share/zoneinfo
173}
174
175build_prop() {
176  cp ${ANDROID_SOURCES_BASE}/out/target/product/generic_x86/system/build.prop ${OUT}/android-all-classes
177}
178
179build_android_all_jar() {
180    echo "Robolectric: Building android-all..."
181    mkdir ${OUT}/android-all
182    cd ${OUT}/android-all; unzip ${OUT}/${ANDROID_RES}
183    # temporarily add raw resources too
184    cd ${OUT}/android-all; rsync -a ${FRAMEWORKS_RAW_RES_DIR} raw-res
185    cd ${OUT}/android-all; jar xf ${OUT}/${ANDROID_EXT}
186    cd ${OUT}/android-all; jar xf ${OUT}/${ANDROID_CLASSES}
187
188    # Remove unused files
189    rm -rf ${OUT}/android-all/Android.mk
190    rm -rf ${OUT}/android-all/raw-res/Android.mk
191    rm -rf ${OUT}/android-all/AndroidManifest.xml
192    rm -rf ${OUT}/android-all/raw-resAndroidManifest.xml
193    rm -rf ${OUT}/android-all/META-INF
194    rm -rf ${OUT}/android-all/MODULE_LICENSE_APACHE2
195    rm -rf ${OUT}/android-all/raw-res/MODULE_LICENSE_APACHE2
196    rm -rf ${OUT}/android-all/MakeJavaSymbols.sed
197    rm -rf ${OUT}/android-all/raw-res/MakeJavaSymbols.sed
198    rm -rf ${OUT}/android-all/NOTICE
199    rm -rf ${OUT}/android-all/raw-res/NOTICE
200    rm -rf ${OUT}/android-all/lint.xml
201    rm -rf ${OUT}/android-all/raw-res/lint.xml
202    rm -rf ${OUT}/android-all/java/lang
203
204    # Build the new JAR file
205    cd ${OUT}/android-all; jar cf ${OUT}/${ANDROID_ALL} .
206    rm ${OUT}/${ANDROID_RES} ${OUT}/${ANDROID_EXT} ${OUT}/${ANDROID_CLASSES}
207}
208
209cp_android_all_jar() {
210  # function to use for android versions that support building the android all
211  # jar directly
212  # This will just copy the android all jar to the final name
213  src=${ANDROID_SOURCES_BASE}/out/target/common/obj/JAVA_LIBRARIES/robolectric_android-all-stub_intermediates/classes-with-res.jar
214  cp $src ${OUT}/${ANDROID_ALL}
215}
216
217build_android_src_jar() {
218    echo "Robolectric: Building android-all-source..."
219    local src=${ANDROID_SOURCES_BASE}/frameworks/base
220    local tmp=${OUT}/sources
221    mkdir ${tmp}
222
223    for sourceSubDir in "${SOURCES[@]}"; do
224        rsync -a ${src}/${sourceSubDir}/ ${tmp}/
225    done
226    rsync -a ${ANDROID_SOURCES_BASE}/libcore/luni/src/main/java/ ${tmp}/ # this is new
227    cd ${tmp}; jar cf ${OUT}/${ANDROID_ALL_SRC} .
228    rm -rf ${tmp}
229}
230
231build_android_doc_jar() {
232    # TODO: Actually build the docs
233    echo "Robolectric: Building android-all-javadoc..."
234    mkdir ${OUT}/javadoc
235    cd ${OUT}/javadoc; jar cf ${OUT}/${ANDROID_ALL_DOC} .
236    rm -rf ${OUT}/javadoc
237}
238
239build_signed_packages() {
240    echo "Robolectric: Building android-all.pom..."
241    sed s/VERSION/${ROBOLECTRIC_VERSION}/ ${SCRIPT_DIR}/pom_template.xml | sed s/ARTIFACT_ID/android-all/ > ${OUT}/${ANDROID_ALL_POM}
242
243    echo "Robolectric: Signing files with gpg..."
244    for ext in ".jar" "-javadoc.jar" "-sources.jar" ".pom"; do
245        ( cd ${OUT} && gpg -ab --passphrase ${SIGNING_PASSWORD} android-all-${ROBOLECTRIC_VERSION}$ext )
246    done
247
248    echo "Robolectric: Creating bundle for Sonatype upload..."
249    cd ${OUT}; jar cf ${ANDROID_BUNDLE} *.jar *.pom *.asc
250}
251
252cp_android_all_jar() {
253  # function to use for android versions that support building the android all
254  # jar directly
255  # This will just copy the android all jar to the final name
256  src=${ANDROID_SOURCES_BASE}/out/target/common/obj/JAVA_LIBRARIES/robolectric_android-all-stub_intermediates/classes-with-res.jar
257  cp $src ${OUT}/${ANDROID_ALL}
258}
259
260mavenize() {
261    local FILE_NAME_BASE=android-all-${ROBOLECTRIC_VERSION}
262    mvn install:install-file \
263      -Dfile=${OUT}/${FILE_NAME_BASE}.jar \
264      -DgroupId=org.robolectric \
265      -DartifactId=android-all \
266      -Dversion=${ROBOLECTRIC_VERSION} \
267      -Dpackaging=jar
268
269    mvn install:install-file \
270      -Dfile=${OUT}/${FILE_NAME_BASE}-sources.jar \
271      -DgroupId=org.robolectric \
272      -DartifactId=android-all \
273      -Dversion=${ROBOLECTRIC_VERSION} \
274      -Dpackaging=jar \
275      -Dclassifier=sources
276
277    mvn install:install-file \
278      -Dfile=${OUT}/${FILE_NAME_BASE}-javadoc.jar \
279      -DgroupId=org.robolectric \
280      -DartifactId=android-all \
281      -Dversion=${ROBOLECTRIC_VERSION} \
282      -Dpackaging=jar \
283      -Dclassifier=javadoc
284}
285
286if [[ ! -d "${4}" ]]; then
287  echo "$4 is not a directory"
288  exit 1
289fi
290
291OUT=${4}/${ANDROID_VERSION}
292mkdir -p ${OUT}
293
294build_platform
295if [[ "${ANDROID_VERSION}" == "8.0.0_r4" ]]; then
296  cp_android_all_jar
297else
298  build_android_res
299  build_android_ext
300  build_android_classes
301  build_android_all_jar
302fi
303
304build_android_src_jar
305build_android_doc_jar
306build_signed_packages
307mavenize
308
309echo "DONE!!"
310echo "Your artifacts are located here: ${OUT}"
311