• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0" encoding="UTF-8"?>
2<project name="" default="debug">
3
4    <!--
5        This build file is imported by the project build file. It contains
6        all the targets and tasks necessary to build Android projects, be they
7        regular projects, library projects, or test projects.
8
9        At the beginning of the file is a list of properties that can be overridden
10        by adding them to your build.properties (properties are immutable, so their
11        first definition sticks and is never changed).
12
13        Follows:
14        - custom task definitions,
15        - more properties (do not override those unless the whole build system is modified).
16        - macros used throughout the build,
17        - base build targets,
18        - debug-specific build targets,
19        - release-specific build targets,
20        - instrument-specific build targets,
21        - test project-specific build targets,
22        - install targets,
23        - help target
24    -->
25
26    <!-- ********** Overrideable Properties ********** -->
27
28    <!-- You can override these values in your build.xml or build.properties.
29         Overriding any other properties may result in broken build. -->
30
31    <!-- Tells adb which device to target. You can change this from the command line
32         by invoking "ant -Dadb.device.arg=-d" for device "ant -Dadb.device.arg=-e" for
33         the emulator. -->
34    <property name="adb.device.arg" value="" />
35
36    <!-- fileset exclude patterns (space separated) to prevent
37         files inside src/ from being packaged. -->
38    <property name="android.package.excludes" value="" />
39
40    <!-- set some properties used for filtering/override. If those weren't defined
41         before, then this will create them with empty values, which are then ignored
42         by the custom tasks receiving them. -->
43    <property name="version.code" value="" />
44    <property name="version.name" value="" />
45    <property name="aapt.resource.filter" value="" />
46
47    <!-- compilation options -->
48    <property name="java.encoding" value="UTF-8" />
49    <property name="java.target" value="1.5" />
50    <property name="java.source" value="1.5" />
51
52    <!-- Verbosity -->
53    <property name="verbose" value="false" />
54
55    <!-- ********** Custom Tasks ********** -->
56
57    <!-- jar file from where the tasks are loaded -->
58    <path id="android.antlibs">
59        <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
60    </path>
61
62    <!-- Custom tasks -->
63    <taskdef name="setup"
64            classname="com.android.ant.NewSetupTask"
65            classpathref="android.antlibs" />
66
67    <taskdef name="aapt"
68            classname="com.android.ant.AaptExecTask"
69            classpathref="android.antlibs" />
70
71    <taskdef name="aidl"
72            classname="com.android.ant.AidlExecTask"
73            classpathref="android.antlibs" />
74
75    <taskdef name="renderscript"
76            classname="com.android.ant.RenderScriptTask"
77            classpathref="android.antlibs" />
78
79    <taskdef name="dex"
80            classname="com.android.ant.DexExecTask"
81            classpathref="android.antlibs" />
82
83    <taskdef name="apkbuilder"
84            classname="com.android.ant.ApkBuilderTask"
85            classpathref="android.antlibs" />
86
87    <taskdef name="zipalign"
88            classname="com.android.ant.ZipAlignTask"
89            classpathref="android.antlibs" />
90
91    <taskdef name="xpath"
92            classname="com.android.ant.XPathTask"
93            classpathref="android.antlibs" />
94
95    <taskdef name="if"
96            classname="com.android.ant.IfElseTask"
97            classpathref="android.antlibs" />
98
99    <!-- Emma configuration -->
100    <property name="emma.dir" value="${sdk.dir}/tools/lib" />
101    <path id="emma.lib">
102        <pathelement location="${emma.dir}/emma.jar" />
103        <pathelement location="${emma.dir}/emma_ant.jar" />
104    </path>
105    <taskdef resource="emma_ant.properties" classpathref="emma.lib" />
106    <!-- End of emma configuration -->
107
108
109    <!-- ********** Other Properties ********** -->
110    <!-- overriding these properties may break the build
111         unless the whole file is updated -->
112
113    <!-- Input directories -->
114    <property name="source.dir" value="src" />
115    <property name="source.absolute.dir" location="${source.dir}" />
116    <property name="gen.absolute.dir" location="gen" />
117    <property name="resource.absolute.dir" location="res" />
118    <property name="asset.absolute.dir" location="assets" />
119    <property name="jar.libs.dir" value="libs" />
120    <property name="jar.libs.absolute.dir" location="${jar.libs.dir}" />
121    <property name="native.libs.absolute.dir" location="libs" />
122
123    <!-- Output directories -->
124    <property name="out.dir" value="bin" />
125    <property name="out.absolute.dir" location="${out.dir}" />
126    <property name="out.classes.absolute.dir" location="${out.dir}/classes" />
127    <property name="out.res.absolute.dir" location="${out.dir}/res" />
128
129    <!-- tools location -->
130    <property name="android.tools.dir" location="${sdk.dir}/tools" />
131    <property name="android.platform.tools.dir" location="${sdk.dir}/platform-tools" />
132    <condition property="exe" value=".exe" else=""><os family="windows" /></condition>
133    <condition property="bat" value=".bat" else=""><os family="windows" /></condition>
134    <property name="adb" location="${android.platform.tools.dir}/adb${exe}" />
135    <property name="zipalign" location="${android.tools.dir}/zipalign${exe}" />
136    <property name="aidl" location="${android.platform.tools.dir}/aidl${exe}" />
137    <property name="aapt" location="${android.platform.tools.dir}/aapt${exe}" />
138    <property name="dx" location="${android.platform.tools.dir}/dx${bat}" />
139    <!-- renderscript location is set by NewSetupTask since we have a choice of
140         several executables based on minSdkVersion -->
141
142    <!-- Intermediate files -->
143    <property name="dex.file.name" value="classes.dex" />
144    <property name="intermediate.dex.file" location="${out.absolute.dir}/${dex.file.name}" />
145    <property name="resource.package.file.name" value="${ant.project.name}.ap_" />
146
147    <!-- Build property file -->
148    <property name="out.build.prop.file" location="${out.absolute.dir}/build.prop" />
149
150
151    <!-- This is needed by emma as it uses multilevel verbosity instead of simple 'true' or 'false'
152         The property 'verbosity' is not user configurable and depends exclusively on 'verbose'
153         value.-->
154    <condition property="verbosity" value="verbose" else="quiet">
155        <istrue value="${verbose}" />
156    </condition>
157
158    <!-- properties for signing in release mode -->
159    <condition property="has.keystore">
160        <and>
161            <isset property="key.store" />
162            <length string="${key.store}" when="greater" length="0" />
163            <isset property="key.alias" />
164        </and>
165    </condition>
166    <condition property="has.password">
167        <and>
168            <isset property="has.keystore" />
169            <isset property="key.store.password" />
170            <isset property="key.alias.password" />
171        </and>
172    </condition>
173
174    <!-- properties for packaging -->
175    <property name="build.packaging.nocrunch" value="true" />
176
177    <!-- ********** Macros ********** -->
178
179    <!-- macro to do a task on if project.is.library is false.
180         elseText attribute is displayed otherwise -->
181    <macrodef name="do-only-if-not-library">
182        <attribute name="elseText" />
183        <element name="task-to-do" implicit="yes" />
184        <sequential>
185        <if condition="${project.is.library}">
186            <else>
187                <task-to-do />
188            </else>
189            <then>
190                <echo>@{elseText}</echo>
191            </then>
192        </if>
193        </sequential>
194    </macrodef>
195
196    <!-- macro to do a task on if manifest.hasCode is true.
197         elseText attribute is displayed otherwise -->
198    <macrodef name="do-only-if-manifest-hasCode">
199        <attribute name="elseText" default=""/>
200        <element name="task-to-do" implicit="yes" />
201        <sequential>
202        <if condition="${manifest.hasCode}">
203            <then>
204                <task-to-do />
205            </then>
206            <else>
207                <if>
208                    <condition>
209                        <length string="@{elseText}" trim="true" when="greater" length="0" />
210                    </condition>
211                    <then>
212                        <echo>@{elseText}</echo>
213                    </then>
214                </if>
215            </else>
216        </if>
217        </sequential>
218    </macrodef>
219
220
221    <!-- Configurable macro, which allows to pass as parameters output directory,
222         output dex filename and external libraries to dex (optional) -->
223    <macrodef name="dex-helper">
224        <element name="external-libs" optional="yes" />
225        <attribute name="nolocals" default="false" />
226        <sequential>
227            <!-- sets the primary input for dex. If a pre-dex task sets it to
228                 something else this has no effect -->
229            <property name="out.dex.input.absolute.dir" value="${out.classes.absolute.dir}" />
230
231            <!-- set the secondary dx input: the project (and library) jar files
232                 If a pre-dex task sets it to something else this has no effect -->
233            <if>
234                <condition>
235                    <isreference refid="out.dex.jar.input.ref" />
236                </condition>
237                <else>
238                    <path id="out.dex.jar.input.ref">
239                        <path refid="jar.libs.ref" />
240                    </path>
241                </else>
242            </if>
243
244            <dex executable="${dx}"
245                    output="${intermediate.dex.file}"
246                    nolocals="@{nolocals}"
247                    verbose="${verbose}"
248                    previousBuildType="${build.last.target}"
249                    buildType="${build.target}">
250                <path path="${out.dex.input.absolute.dir}"/>
251                <path refid="out.dex.jar.input.ref" />
252                <external-libs />
253            </dex>
254        </sequential>
255    </macrodef>
256
257    <!-- This is macro that enable passing variable list of external jar files to ApkBuilder
258         Example of use:
259         <package-helper>
260             <extra-jars>
261                <jarfolder path="my_jars" />
262                <jarfile path="foo/bar.jar" />
263                <jarfolder path="your_jars" />
264             </extra-jars>
265         </package-helper> -->
266    <macrodef name="package-helper">
267        <element name="extra-jars" optional="yes" />
268        <sequential>
269            <apkbuilder
270                    outfolder="${out.absolute.dir}"
271                    resourcefile="${resource.package.file.name}"
272                    apkfilepath="${out.packaged.file}"
273                    debugpackaging="${build.is.packaging.debug}"
274                    debugsigning="${build.is.signing.debug}"
275                    verbose="${verbose}"
276                    hascode="${manifest.hasCode}"
277                    previousBuildType="${build.last.is.packaging.debug}/${build.last.is.signing.debug}"
278                    buildType="${build.is.packaging.debug}/${build.is.signing.debug}">
279                <dex path="${intermediate.dex.file}"/>
280                <sourcefolder path="${source.absolute.dir}"/>
281                <jarfile refid="jar.libs.ref" />
282                <nativefolder path="${native.libs.absolute.dir}" />
283                <nativefolder refid="project.libraries.libs" />
284                <extra-jars/>
285            </apkbuilder>
286        </sequential>
287    </macrodef>
288
289    <!-- This is macro which zipaligns in.package and outputs it to out.package. Used by targets
290         debug, -debug-with-emma and release.-->
291    <macrodef name="zipalign-helper">
292        <attribute name="in.package" />
293        <attribute name="out.package" />
294        <sequential>
295            <zipalign
296                    executable="${zipalign}"
297                    input="@{in.package}"
298                    output="@{out.package}"
299                    verbose="${verbose}" />
300        </sequential>
301    </macrodef>
302
303    <macrodef name="run-tests-helper">
304        <attribute name="emma.enabled" default="false" />
305        <element name="extra-instrument-args" optional="yes" />
306        <sequential>
307            <echo>Running tests ...</echo>
308            <exec executable="${adb}" failonerror="true">
309                <arg line="${adb.device.arg}" />
310                <arg value="shell" />
311                <arg value="am" />
312                <arg value="instrument" />
313                <arg value="-w" />
314                <arg value="-e" />
315                <arg value="coverage" />
316                <arg value="@{emma.enabled}" />
317                <extra-instrument-args />
318                <arg value="${manifest.package}/${test.runner}" />
319            </exec>
320        </sequential>
321    </macrodef>
322
323    <macrodef name="record-build-key">
324        <attribute name="key" default="false" />
325        <attribute name="value" default="false" />
326        <sequential>
327            <propertyfile file="${out.build.prop.file}" comment="Last build type">
328                <entry key="@{key}" value="@{value}"/>
329            </propertyfile>
330        </sequential>
331    </macrodef>
332
333    <macrodef name="record-build-info">
334        <sequential>
335            <record-build-key key="build.last.target" value="${build.target}" />
336            <record-build-key key="build.last.is.instrumented" value="${build.is.instrumented}" />
337            <record-build-key key="build.last.is.packaging.debug" value="${build.is.packaging.debug}" />
338            <record-build-key key="build.last.is.signing.debug" value="${build.is.signing.debug}" />
339        </sequential>
340    </macrodef>
341
342    <macrodef name="uninstall-helper">
343        <attribute name="app.package" default="false" />
344        <sequential>
345            <echo>Uninstalling @{app.package} from the default emulator or device...</echo>
346            <exec executable="${adb}" failonerror="true">
347                <arg line="${adb.device.arg}" />
348                <arg value="uninstall" />
349                <arg value="@{app.package}" />
350            </exec>
351        </sequential>
352    </macrodef>
353
354    <!-- ********** Build Targets ********** -->
355
356    <!-- this target simply force running -setup making
357         the project info be read. To be used as
358             ant all clean
359         to clean the main project as well as the libraries and tested project -->
360    <target name="all" depends="-setup"/>
361
362    <!-- clean target -->
363    <target name="clean" description="Removes output files created by other targets.">
364        <delete dir="${out.absolute.dir}" verbose="${verbose}" />
365        <delete dir="${gen.absolute.dir}" verbose="${verbose}" />
366
367        <!-- if we know about a tested project or libraries, we clean them too. This
368             will only work if the target 'all' was called first -->
369        <if condition="${project.is.test}">
370            <then>
371                <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
372                <subant failonerror="true">
373                    <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
374                    <target name="all" />
375                    <target name="clean" />
376                </subant>
377            </then>
378        </if>
379
380        <if>
381            <condition>
382                <isreference refid="project.libraries" />
383            </condition>
384            <then>
385                <subant
386                        buildpathref="project.libraries"
387                        antfile="build.xml"
388                        failonerror="true">
389                    <target name="all" />
390                    <target name="clean" />
391                </subant>
392            </then>
393        </if>
394    </target>
395
396    <!-- generic setup -->
397    <target name="-setup">
398        <if>
399            <condition>
400                <not><isset property="setup.done" /></not>
401            </condition>
402            <then>
403                <property name="setup.done" value="true" />
404                <echo>Gathering info for ${ant.project.name}...</echo>
405                <!-- load project properties, resolve Android target, library dependencies
406                     and set some properties with the results.
407                     All property names are passed as parameters ending in -Out -->
408                <setup
409                        projectTypeOut="android.project.type"
410                        androidJarFileOut="android.jar"
411                        androidAidlFileOut="android.aidl"
412                        renderScriptExeOut="renderscript"
413                        renderScriptIncludeDirOut="android.rs"
414                        bootclasspathrefOut="android.target.classpath"
415                        projectLibrariesRootOut="project.libraries"
416                        projectLibrariesJarsOut="project.libraries.jars"
417                        projectLibrariesResOut="project.libraries.res"
418                        projectLibrariesPackageOut="project.libraries.package"
419                        projectLibrariesLibsOut="project.libraries.libs"
420                        targetApiOut="target.api"
421                />
422
423                <!-- sets a few boolean based on android.project.type
424                     to make the if task easier -->
425                <condition property="project.is.library" else="false">
426                    <equals arg1="${android.project.type}" arg2="library" />
427                </condition>
428                <condition property="project.is.test" else="false">
429                    <equals arg1="${android.project.type}" arg2="test" />
430                </condition>
431
432                <!-- If a test project, resolve absolute path to tested project. -->
433                <if condition="${project.is.test}">
434                    <then>
435                        <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
436                    </then>
437                </if>
438            </then>
439        </if>
440    </target>
441
442    <!-- Pre build setup -->
443    <target name="-build-setup" depends="-setup">
444
445        <!-- read the previous build mode -->
446        <property file="${out.build.prop.file}" />
447        <!-- if empty the prop won't be set, so set it to the current target
448             to provide a default value equal to the current build -->
449        <property name="build.last.target" value="${build.target}" />
450        <!-- also set the default value for whether the build is instrumented -->
451        <property name="build.last.is.instrumented" value="${build.is.instrumented}" />
452        <property name="build.last.is.packaging.debug" value="${build.is.packaging.debug}" />
453        <property name="build.last.is.signing.debug" value="${build.is.signing.debug}" />
454
455        <!-- compile the libraries if any -->
456        <if>
457            <condition>
458                <isreference refid="project.libraries" />
459            </condition>
460            <then>
461                <echo>Building Libraries</echo>
462                <subant
463                        buildpathref="project.libraries"
464                        antfile="build.xml"
465                        target="${build.target}"
466                        failonerror="true"/>
467                <echo></echo>
468                <echo>############################################</echo>
469                <echo>**** Back to project ${ant.project.name} ****</echo>
470                <echo>############################################</echo>
471            </then>
472        </if>
473
474        <!-- compile the main project if this is a test project -->
475        <if condition="${project.is.test}">
476            <then>
477                <!-- figure out which target must be used to build the tested project.
478                     If emma is enabled, then use 'instrument' otherwise, use 'debug' -->
479                <condition property="tested.project.target" value="instrument" else="debug">
480                    <isset property="emma.enabled" />
481                </condition>
482
483                <echo>Building tested project at ${tested.project.absolute.dir}</echo>
484                <subant target="${tested.project.target}" failonerror="true">
485                    <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
486                </subant>
487                <echo></echo>
488                <echo>############################################</echo>
489                <echo>**** Back to project ${ant.project.name} ****</echo>
490                <echo>############################################</echo>
491            </then>
492        </if>
493
494        <!-- Value of the hasCode attribute (Application node) extracted from manifest file -->
495        <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:hasCode"
496                    output="manifest.hasCode" default="true"/>
497
498        <!-- create a path with all the jar files, from the main project and the
499             libraries -->
500        <path id="jar.libs.ref">
501            <fileset dir="${jar.libs.absolute.dir}" includes="*.jar" />
502            <path refid="project.libraries.jars" />
503        </path>
504
505        <!-- special case for instrumented: if the previous build was
506             instrumented but not this one, clear out the compiled code -->
507        <if>
508            <condition>
509                <and>
510                    <istrue value="${build.last.is.instrumented}" />
511                    <isfalse value="${build.is.instrumented}" />
512                </and>
513            </condition>
514            <then>
515                <echo>Switching from instrumented to non-instrumented build.</echo>
516                <echo>Deleting previous compilation output:</echo>
517                <delete dir="${out.classes.absolute.dir}" verbose="${verbose}" />
518            </then>
519        </if>
520
521        <echo>Creating output directories if needed...</echo>
522        <mkdir dir="${resource.absolute.dir}" />
523        <mkdir dir="${jar.libs.absolute.dir}" />
524        <mkdir dir="${out.absolute.dir}" />
525        <mkdir dir="${out.res.absolute.dir}" />
526        <do-only-if-manifest-hasCode>
527            <mkdir dir="${gen.absolute.dir}" />
528            <mkdir dir="${out.classes.absolute.dir}" />
529        </do-only-if-manifest-hasCode>
530    </target>
531
532    <!-- empty default pre-build target. Create a similar target in
533         your build.xml and it'll be called instead of this one. -->
534    <target name="-pre-build"/>
535
536    <!-- Code Generation: compile resources (aapt -> R.java), aidl, renderscript -->
537    <target name="-code-gen">
538        <do-only-if-manifest-hasCode
539                elseText="hasCode = false. Skipping aidl/renderscript/R.java">
540            <echo>----------</echo>
541            <echo>Handling aidl files...</echo>
542            <aidl executable="${aidl}" framework="${android.aidl}"
543                    genFolder="${gen.absolute.dir}">
544                <source path="${source.absolute.dir}"/>
545            </aidl>
546
547            <!-- renderscript generates resources so it must be called before aapt -->
548            <echo>----------</echo>
549            <echo>Handling RenderScript files...</echo>
550            <renderscript executable="${renderscript}"
551                    framework="${android.rs}"
552                    genFolder="${gen.absolute.dir}"
553                    resFolder="${resource.absolute.dir}/raw"
554                    targetApi="${target.api}">
555                <source path="${source.absolute.dir}"/>
556            </renderscript>
557
558            <echo>----------</echo>
559            <echo>Handling Resources...</echo>
560            <aapt executable="${aapt}"
561                    command="package"
562                    verbose="${verbose}"
563                    manifest="AndroidManifest.xml"
564                    androidjar="${android.jar}"
565                    rfolder="${gen.absolute.dir}"
566                    nonConstantId="${android.library}"
567                    projectLibrariesResName="project.libraries.res"
568                    projectLibrariesPackageName="project.libraries.package">
569                <res path="${resource.absolute.dir}" />
570            </aapt>
571        </do-only-if-manifest-hasCode>
572    </target>
573
574    <!-- empty default pre-compile target. Create a similar target in
575         your build.xml and it'll be called instead of this one. -->
576    <target name="-pre-compile"/>
577
578    <!-- Compiles this project's .java files into .class files. -->
579    <target name="-compile" depends="-build-setup, -pre-build, -code-gen, -pre-compile">
580        <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
581            <!-- If android rules are used for a test project, its classpath should include
582                 tested project's location -->
583            <condition property="extensible.classpath"
584                    value="${tested.project.absolute.dir}/bin/classes"
585                    else=".">
586                <isset property="tested.project.absolute.dir" />
587            </condition>
588            <condition property="extensible.libs.classpath"
589                    value="${tested.project.absolute.dir}/${jar.libs.dir}"
590                    else="${jar.libs.dir}">
591                <isset property="tested.project.absolute.dir" />
592            </condition>
593            <javac encoding="${java.encoding}"
594                    source="${java.source}" target="${java.target}"
595                    debug="true" extdirs=""
596                    destdir="${out.classes.absolute.dir}"
597                    bootclasspathref="android.target.classpath"
598                    verbose="${verbose}"
599                    classpath="${extensible.classpath}"
600                    classpathref="jar.libs.ref">
601                <src path="${source.absolute.dir}" />
602                <src path="${gen.absolute.dir}" />
603                <classpath>
604                    <fileset dir="${extensible.libs.classpath}" includes="*.jar" />
605                </classpath>
606            </javac>
607            <!-- if the project is a library then we generate a jar file -->
608            <if condition="${project.is.library}">
609                <then>
610                    <echo>Creating library output jar file...</echo>
611                    <property name="out.library.jar.file" location="${out.absolute.dir}/classes.jar" />
612                    <if>
613                        <condition>
614                            <length string="${android.package.excludes}" trim="true" when="greater" length="0" />
615                        </condition>
616                        <then>
617                            <echo>Custom jar packaging exclusion: ${android.package.excludes}</echo>
618                        </then>
619                    </if>
620                    <jar destfile="${out.library.jar.file}">
621                        <fileset dir="${out.classes.absolute.dir}" excludes="**/R.class **/R$*.class"/>
622                        <fileset dir="${source.absolute.dir}" excludes="**/*.java ${android.package.excludes}" />
623                    </jar>
624                </then>
625            </if>
626
627            <!-- if the project is instrumented, intrument the classes -->
628            <if condition="${build.is.instrumented}">
629                <then>
630                    <echo>Instrumenting classes from ${out.absolute.dir}/classes...</echo>
631                    <!-- It only instruments class files, not any external libs -->
632                    <emma enabled="true">
633                        <instr verbosity="${verbosity}"
634                               mode="overwrite"
635                               instrpath="${out.absolute.dir}/classes"
636                               outdir="${out.absolute.dir}/classes">
637                        </instr>
638                        <!-- TODO: exclusion filters on R*.class and allowing custom exclusion from
639                             user defined file -->
640                    </emma>
641                </then>
642            </if>
643        </do-only-if-manifest-hasCode>
644    </target>
645
646    <!-- empty default post-compile target. Create a similar target in
647         your build.xml and it'll be called instead of this one. -->
648    <target name="-post-compile"/>
649
650    <!-- Obfuscate target
651        This is only active in release builds when proguard.config is defined
652        in default.properties.
653
654        To replace Proguard with a different obfuscation engine:
655        Override the following targets in your build.xml, before the call to <setup>
656            -release-obfuscation-check
657                Check whether obfuscation should happen, and put the result in a property.
658            -debug-obfuscation-check
659                Obfuscation should not happen. Set the same property to false.
660            -obfuscate
661                check if the property set in -debug/release-obfuscation-check is set to true.
662                If true:
663                    Perform obfuscation
664                    Set property out.dex.input.absolute.dir to be the output of the obfuscation
665    -->
666    <target name="-obfuscate">
667        <if condition="${proguard.enabled}">
668            <then>
669                <property name="obfuscate.absolute.dir" location="${out.absolute.dir}/proguard" />
670                <property name="preobfuscate.jar.file" value="${obfuscate.absolute.dir}/original.jar" />
671                <property name="obfuscated.jar.file" value="${obfuscate.absolute.dir}/obfuscated.jar" />
672                <!-- input for dex will be proguard's output -->
673                <property name="out.dex.input.absolute.dir" value="${obfuscated.jar.file}" />
674
675                <!-- Add Proguard Tasks -->
676                <property name="proguard.jar" location="${android.tools.dir}/proguard/lib/proguard.jar" />
677                <taskdef name="proguard" classname="proguard.ant.ProGuardTask" classpath="${proguard.jar}" />
678
679                <!-- Set the android classpath Path object into a single property. It'll be
680                     all the jar files separated by a platform path-separator.
681                     Each path must be quoted if it contains spaces.
682                -->
683                <pathconvert property="android.libraryjars" refid="android.target.classpath">
684                    <firstmatchmapper>
685                        <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
686                        <identitymapper/>
687                    </firstmatchmapper>
688                </pathconvert>
689
690                <!-- Build a path object with all the jar files that must be obfuscated.
691                     This include the project compiled source code and any 3rd party jar
692                     files. -->
693                <path id="project.jars.ref">
694                    <pathelement location="${preobfuscate.jar.file}" />
695                    <path refid="jar.libs.ref" />
696                </path>
697                <!-- Set the project jar files Path object into a single property. It'll be
698                     all the jar files separated by a platform path-separator.
699                     Each path must be quoted if it contains spaces.
700                -->
701                <pathconvert property="project.jars" refid="project.jars.ref">
702                    <firstmatchmapper>
703                        <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
704                        <identitymapper/>
705                    </firstmatchmapper>
706                </pathconvert>
707
708                <mkdir   dir="${obfuscate.absolute.dir}" />
709                <delete file="${preobfuscate.jar.file}"/>
710                <delete file="${obfuscated.jar.file}"/>
711                <jar basedir="${out.classes.absolute.dir}"
712                    destfile="${preobfuscate.jar.file}" />
713                <proguard>
714                    @${proguard.config}
715                    -injars       ${project.jars}
716                    -outjars      "${obfuscated.jar.file}"
717                    -libraryjars  ${android.libraryjars}
718                    -dump         "${obfuscate.absolute.dir}/dump.txt"
719                    -printseeds   "${obfuscate.absolute.dir}/seeds.txt"
720                    -printusage   "${obfuscate.absolute.dir}/usage.txt"
721                    -printmapping "${obfuscate.absolute.dir}/mapping.txt"
722                </proguard>
723            </then>
724        </if>
725    </target>
726
727    <!-- Converts this project's .class files into .dex files -->
728    <target name="-dex" depends="-compile, -post-compile, -obfuscate">
729        <do-only-if-manifest-hasCode elseText="hasCode = false. Skipping...">
730            <!-- only convert to dalvik bytecode is *not* a library -->
731            <do-only-if-not-library elseText="Library project: do not convert bytecode..." >
732                <!-- special case for instrumented builds: need to use no-locals and need
733                     to pass in the emma jar. -->
734                <if condition="${build.is.instrumented}">
735                    <then>
736                        <dex-helper nolocals="true">
737                            <external-libs>
738                                <fileset file="${emma.dir}/emma_device.jar" />
739                            </external-libs>
740                        </dex-helper>
741                    </then>
742                    <else>
743                        <dex-helper />
744                    </else>
745                </if>
746            </do-only-if-not-library>
747        </do-only-if-manifest-hasCode>
748    </target>
749
750<!-- Updates the pre-processed PNG cache -->
751    <target name="-crunch">
752        <exec executable="${aapt}" taskName="crunch">
753            <arg value="crunch" />
754            <arg value="-v" />
755            <arg value="-S" />
756            <arg path="${resource.absolute.dir}" />
757            <arg value="-C" />
758            <arg path="${out.res.absolute.dir}" />
759        </exec>
760    </target>
761
762    <!-- Puts the project's resources into the output package file
763         This actually can create multiple resource package in case
764         Some custom apk with specific configuration have been
765         declared in default.properties.
766         -->
767    <target name="-package-resources" depends="-crunch">
768        <!-- only package resources if *not* a library project -->
769        <do-only-if-not-library elseText="Library project: do not package resources..." >
770            <aapt executable="${aapt}"
771                    command="package"
772                    versioncode="${version.code}"
773                    versionname="${version.name}"
774                    debug="${build.is.packaging.debug}"
775                    manifest="AndroidManifest.xml"
776                    assets="${asset.absolute.dir}"
777                    androidjar="${android.jar}"
778                    apkfolder="${out.absolute.dir}"
779                    nocrunch="${build.packaging.nocrunch}"
780                    resourcefilename="${resource.package.file.name}"
781                    resourcefilter="${aapt.resource.filter}"
782                    projectLibrariesResName="project.libraries.res"
783                    projectLibrariesPackageName="project.libraries.package"
784                    previousBuildType="${build.last.target}"
785                    buildType="${build.target}">
786                <res path="${out.res.absolute.dir}" />
787                <res path="${resource.absolute.dir}" />
788                <!-- <nocompress /> forces no compression on any files in assets or res/raw -->
789                <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
790            </aapt>
791        </do-only-if-not-library>
792    </target>
793
794    <!-- Packages the application. -->
795    <target name="-package" depends="-dex, -package-resources">
796        <!-- only package apk if *not* a library project -->
797        <do-only-if-not-library elseText="Library project: do not package apk..." >
798            <if condition="${build.is.instrumented}">
799                <then>
800                    <package-helper>
801                        <extra-jars>
802                            <!-- Injected from external file -->
803                            <jarfile path="${emma.dir}/emma_device.jar" />
804                        </extra-jars>
805                    </package-helper>
806                </then>
807                <else>
808                    <package-helper />
809                </else>
810            </if>
811        </do-only-if-not-library>
812    </target>
813
814    <target name="-set-mode-check">
815        <fail if="out.final.file"
816                message="Cannot run two different modes at the same time. If you are running more than one debug/release/instrument type targets, call them from different Ant calls." />
817    </target>
818
819    <!-- ********** Debug specific targets ********** -->
820
821    <target name="-set-debug-files" depends="-set-mode-check">
822
823        <property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-debug-unaligned.apk" />
824        <property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-debug.apk" />
825    </target>
826
827
828    <target name="-set-debug-mode">
829        <!-- record the current build target -->
830        <property name="build.target" value="debug" />
831
832        <property name="build.is.instrumented" value="false" />
833
834        <!-- whether the build is a debug build. always set. -->
835        <property name="build.is.packaging.debug" value="true" />
836
837        <!-- signing mode: debug -->
838        <property name="build.is.signing.debug" value="true" />
839
840    </target>
841
842    <target name="-debug-obfuscation-check">
843        <!-- proguard is never enabled in debug mode -->
844        <property name="proguard.enabled" value="false"/>
845    </target>
846
847    <!-- Builds debug output package -->
848    <target name="-do-debug" depends="-set-debug-mode, -debug-obfuscation-check, -package">
849        <!-- only create apk if *not* a library project -->
850        <do-only-if-not-library elseText="Library project: do not create apk..." >
851            <sequential>
852                <zipalign-helper in.package="${out.packaged.file}" out.package="${out.final.file}" />
853                <echo>Debug Package: ${out.final.file}</echo>
854            </sequential>
855        </do-only-if-not-library>
856    </target>
857
858    <!-- Builds debug output package -->
859    <target name="debug" depends="-set-debug-files, -do-debug"
860                description="Builds the application and signs it with a debug key.">
861        <record-build-info />
862    </target>
863
864
865    <!-- ********** Release specific targets ********** -->
866
867    <!-- called through target 'release'. Only executed if the keystore and
868         key alias are known but not their password. -->
869    <target name="-release-prompt-for-password" if="has.keystore" unless="has.password">
870        <!-- Gets passwords -->
871        <input
872                message="Please enter keystore password (store:${key.store}):"
873                addproperty="key.store.password" />
874        <input
875                message="Please enter password for alias '${key.alias}':"
876                addproperty="key.alias.password" />
877    </target>
878
879    <!-- called through target 'release'. Only executed if there's no
880         keystore/key alias set -->
881    <target name="-release-nosign" unless="has.keystore">
882        <!-- no release builds for library project -->
883        <do-only-if-not-library elseText="" >
884            <sequential>
885                <echo>No key.store and key.alias properties found in build.properties.</echo>
886                <echo>Please sign ${out.packaged.file} manually</echo>
887                <echo>and run zipalign from the Android SDK tools.</echo>
888            </sequential>
889        </do-only-if-not-library>
890        <record-build-info />
891    </target>
892
893    <target name="-release-obfuscation-check">
894        <condition property="proguard.enabled" value="true" else="false">
895            <and>
896                <isset property="build.is.mode.release" />
897                <isset property="proguard.config" />
898            </and>
899        </condition>
900        <if condition="${proguard.enabled}">
901            <then>
902                <!-- Secondary dx input (jar files) is empty since all the
903                     jar files will be in the obfuscated jar -->
904                <path id="out.dex.jar.input.ref" />
905            </then>
906        </if>
907    </target>
908
909    <target name="-set-release-mode" depends="-set-mode-check">
910        <property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-release-unsigned.apk" />
911        <property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-release.apk" />
912
913        <!-- record the current build target -->
914        <property name="build.target" value="release" />
915
916        <property name="build.is.instrumented" value="false" />
917
918        <!-- release mode is only valid if the manifest does not explicitly
919             set debuggable to true. default is false. -->
920        <xpath input="AndroidManifest.xml" expression="/manifest/application/@android:debuggable"
921                output="build.is.packaging.debug" default="false"/>
922
923        <!-- signing mode: release -->
924        <property name="build.is.signing.debug" value="false" />
925
926        <if condition="${build.is.packaging.debug}">
927            <then>
928                <echo>*************************************************</echo>
929                <echo>****  Android Manifest has debuggable=true   ****</echo>
930                <echo>**** Doing DEBUG packaging with RELEASE keys ****</echo>
931                <echo>*************************************************</echo>
932            </then>
933            <else>
934                <!-- property only set in release mode.
935                     Useful for if/unless attributes in target node
936                     when using Ant before 1.8 -->
937                <property name="build.is.mode.release" value="true"/>
938            </else>
939        </if>
940    </target>
941
942    <!-- This runs -package-release and -release-nosign first and then runs
943         only if release-sign is true (set in -release-check,
944         called by -release-no-sign)-->
945    <target name="release"
946                depends="-set-release-mode, -release-obfuscation-check, -package, -release-prompt-for-password, -release-nosign"
947                if="has.keystore"
948                description="Builds the application. The generated apk file must be signed before
949                            it is published.">
950
951        <!-- only create apk if *not* a library project -->
952        <do-only-if-not-library elseText="Library project: do not create apk..." >
953            <sequential>
954                <property name="out.unaligned.file" location="${out.absolute.dir}/${ant.project.name}-release-unaligned.apk" />
955
956                <!-- Signs the APK -->
957                <echo>Signing final apk...</echo>
958                <signjar
959                        jar="${out.packaged.file}"
960                        signedjar="${out.unaligned.file}"
961                        keystore="${key.store}"
962                        storepass="${key.store.password}"
963                        alias="${key.alias}"
964                        keypass="${key.alias.password}"
965                        verbose="${verbose}" />
966
967                <!-- Zip aligns the APK -->
968                <zipalign-helper in.package="${out.unaligned.file}"
969                                           out.package="${out.final.file}" />
970                <echo>Release Package: ${out.final.file}</echo>
971            </sequential>
972        </do-only-if-not-library>
973        <record-build-info />
974    </target>
975
976    <!-- ********** Instrumented specific targets ********** -->
977
978    <!-- These targets are specific for the project under test when it
979         gets compiled by the test projects in a way that will make it
980         support emma code coverage -->
981
982    <target name="-set-instrumented-mode" depends="-set-mode-check">
983        <property name="out.packaged.file" location="${out.absolute.dir}/${ant.project.name}-instrumented-unaligned.apk" />
984        <property name="out.final.file" location="${out.absolute.dir}/${ant.project.name}-instrumented.apk" />
985
986        <!-- whether the build is an instrumented build. -->
987        <property name="build.is.instrumented" value="true" />
988    </target>
989
990    <!-- Builds instrumented output package -->
991    <target name="instrument" depends="-set-instrumented-mode, -do-debug"
992                description="Builds an instrumented packaged.">
993        <!-- only create apk if *not* a library project -->
994        <do-only-if-not-library elseText="Library project: do not create apk..." >
995            <sequential>
996                <zipalign-helper in.package="${out.packaged.file}" out.package="${out.final.file}" />
997                <echo>Instrumented Package: ${out.final.file}</echo>
998            </sequential>
999        </do-only-if-not-library>
1000        <record-build-info />
1001    </target>
1002
1003    <!-- ********** Test project specific targets ********** -->
1004
1005    <!-- enable code coverage -->
1006    <target name="emma">
1007        <property name="emma.enabled" value="true" />
1008    </target>
1009
1010    <!-- fails if the project is not a test project -->
1011    <target name="-test-project-check">
1012        <!-- can't use project.is.test since the setup target is not run -->
1013        <if>
1014            <condition>
1015                <isset property="tested.project.dir" />
1016            </condition>
1017            <else>
1018                <fail message="Project is not a test project." />
1019            </else>
1020        </if>
1021    </target>
1022
1023    <!-- Installs the tested project. This make sure to install the proper package based on
1024         the value of emma.enabled -->
1025    <target name="-install-tested-project" depends="-test-project-check, -setup">
1026        <!-- figure out which tested package to install based on emma.enabled -->
1027        <condition property="tested.project.install.target" value="installi" else="installd">
1028            <isset property="emma.enabled" />
1029        </condition>
1030        <subant target="${tested.project.install.target}" failonerror="true">
1031            <fileset dir="${tested.project.absolute.dir}" includes="build.xml" />
1032        </subant>
1033    </target>
1034
1035    <target name="test" depends="-test-project-check"
1036                description="Runs tests from the package defined in test.package property">
1037
1038        <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
1039
1040        <property name="test.runner" value="android.test.InstrumentationTestRunner" />
1041
1042        <!-- Application package of the tested project extracted from its manifest file -->
1043        <xpath input="${tested.project.absolute.dir}/AndroidManifest.xml"
1044                expression="/manifest/@package" output="tested.manifest.package" />
1045
1046        <property name="emma.dump.file"
1047                value="/data/data/${tested.manifest.package}/coverage.ec" />
1048
1049        <if condition="${emma.enabled}">
1050            <then>
1051                <echo>WARNING: Code Coverage is currently only supported on the emulator and rooted devices.</echo>
1052                <run-tests-helper emma.enabled="true">
1053                    <extra-instrument-args>
1054                        <arg value="-e" />
1055                           <arg value="coverageFile" />
1056                           <arg value="${emma.dump.file}" />
1057                    </extra-instrument-args>
1058                </run-tests-helper>
1059                <echo>Downloading coverage file into project directory...</echo>
1060                <exec executable="${adb}" failonerror="true">
1061                    <arg line="${adb.device.arg}" />
1062                    <arg value="pull" />
1063                    <arg value="${emma.dump.file}" />
1064                    <arg value="coverage.ec" />
1065                </exec>
1066                <echo>Extracting coverage report...</echo>
1067                <emma>
1068                    <report sourcepath="${tested.project.absolute.dir}/${source.dir}"
1069                                      verbosity="${verbosity}">
1070                        <!-- TODO: report.dir or something like should be introduced if necessary -->
1071                        <infileset dir=".">
1072                            <include name="coverage.ec" />
1073                            <include name="coverage.em" />
1074                        </infileset>
1075                        <!-- TODO: reports in other, indicated by user formats -->
1076                        <html outfile="coverage.html" />
1077                   </report>
1078                </emma>
1079                <echo>Cleaning up temporary files...</echo>
1080                <delete file="coverage.ec" />
1081                <delete file="coverage.em" />
1082                <echo>Saving the report file in ${basedir}/coverage/coverage.html</echo>
1083            </then>
1084            <else>
1085                <run-tests-helper />
1086            </else>
1087        </if>
1088    </target>
1089
1090
1091    <!-- ********** Install/uninstall specific targets ********** -->
1092
1093    <target name="install"
1094                description="Installs the newly build package. Must be used in conjunction with a build target
1095                            (debug/release/instrument). If the application was previously installed, the application
1096                            is reinstalled if the signature matches." >
1097        <!-- only do install if *not* a library project -->
1098        <do-only-if-not-library elseText="Library project: nothing to install!" >
1099            <if>
1100                <condition>
1101                    <isset property="out.final.file" />
1102                </condition>
1103                <then>
1104                    <if>
1105                        <condition>
1106                            <resourceexists>
1107                                <file file="${out.final.file}"/>
1108                            </resourceexists>
1109                            </condition>
1110                        <then>
1111                            <echo>Installing ${out.final.file} onto default emulator or device...</echo>
1112                            <exec executable="${adb}" failonerror="true">
1113                                <arg line="${adb.device.arg}" />
1114                                <arg value="install" />
1115                                <arg value="-r" />
1116                                <arg path="${out.final.file}" />
1117                            </exec>
1118                        </then>
1119                        <else>
1120                            <fail message="File {out.final.file} does not exist." />
1121                        </else>
1122                    </if>
1123                </then>
1124                <else>
1125                    <echo>Install file not specified.</echo>
1126                    <echo></echo>
1127                    <echo>'ant install' now requires the build target to be specified as well.</echo>
1128                    <echo></echo>
1129                    <echo></echo>
1130                    <echo>    ant debug install</echo>
1131                    <echo>    ant release install</echo>
1132                    <echo>    ant instrument install</echo>
1133                    <echo>This will build the given package and install it.</echo>
1134                    <echo></echo>
1135                    <echo>Alternatively, you can use</echo>
1136                    <echo>    ant installd</echo>
1137                    <echo>    ant installr</echo>
1138                    <echo>    ant installi</echo>
1139                    <echo>    ant installt</echo>
1140                    <echo>to only install an existing package (this will not rebuild the package.)</echo>
1141                    <fail />
1142                </else>
1143            </if>
1144        </do-only-if-not-library>
1145    </target>
1146
1147    <target name="installd" depends="-set-debug-files, install"
1148            description="Installs (only) the debug package." />
1149    <target name="installr" depends="-set-release-mode, install"
1150            description="Installs (only) the release package." />
1151    <target name="installi" depends="-set-instrumented-mode, install"
1152            description="Installs (only) the instrumented package." />
1153    <target name="installt" depends="-install-tested-project, installd"
1154            description="Installs (only) the test and tested packages." />
1155
1156
1157    <!-- Uninstalls the package from the default emulator/device -->
1158    <target name="uninstall"
1159                description="Uninstalls the application from a running emulator or device.">
1160        <!-- Name of the application package extracted from manifest file -->
1161        <xpath input="AndroidManifest.xml" expression="/manifest/@package"
1162                output="manifest.package" />
1163
1164        <if>
1165            <condition>
1166                <isset property="manifest.package" />
1167            </condition>
1168            <then>
1169                <uninstall-helper app.package="${manifest.package}" />
1170            </then>
1171            <else>
1172                <echo>Could not find application package in manifest. Cannot run 'adb uninstall'.</echo>
1173            </else>
1174        </if>
1175
1176        <if condition="${project.is.test}">
1177            <then>
1178                <property name="tested.project.absolute.dir" location="${tested.project.dir}" />
1179
1180                <!-- Application package of the tested project extracted from its manifest file -->
1181                <xpath input="${tested.project.absolute.dir}/AndroidManifest.xml"
1182                    expression="/manifest/@package" output="tested.manifest.package" />
1183                <if>
1184                    <condition>
1185                        <isset property="tested.manifest.package" />
1186                    </condition>
1187                    <then>
1188                        <uninstall-helper app.package="${tested.manifest.package}" />
1189                    </then>
1190                    <else>
1191                        <echo>Could not find tested application package in manifest. Cannot run 'adb uninstall'.</echo>
1192                    </else>
1193                </if>
1194            </then>
1195        </if>
1196
1197    </target>
1198
1199
1200    <target name="help">
1201        <!-- displays starts at col 13
1202              |13                                                              80| -->
1203        <echo>Android Ant Build. Available targets:</echo>
1204        <echo>   help:      Displays this help.</echo>
1205        <echo>   clean:     Removes output files created by other targets.</echo>
1206        <echo>              The 'all' target can be used to clean dependencies</echo>
1207        <echo>              (tested projects and libraries)at the same time</echo>
1208        <echo>              using: 'ant all clean'</echo>
1209        <echo>   debug:     Builds the application and signs it with a debug key.</echo>
1210        <echo>   release:   Builds the application. The generated apk file must be</echo>
1211        <echo>              signed before it is published.</echo>
1212        <echo>   instrument:Builds an instrumented package and signs it with a</echo>
1213        <echo>              debug key.</echo>
1214        <echo>   test:      Runs the tests. Project must be a test project and</echo>
1215        <echo>              must have been built. Typical usage would be:</echo>
1216        <echo>                  ant [emma] debug installt test</echo>
1217        <echo>   emma:      Transiently enables code coverage for subsequent</echo>
1218        <echo>              targets.</echo>
1219        <echo>   install:   Installs the newly build package. Must either be used</echo>
1220        <echo>              in conjunction with a build target (debug/release/</echo>
1221        <echo>              instrument) or with the proper suffix indicating</echo>
1222        <echo>              which package to install (see below).</echo>
1223        <echo>              If the application was previously installed, the</echo>
1224        <echo>              application is reinstalled if the signature matches.</echo>
1225        <echo>   installd:  Installs (only) the debug package.</echo>
1226        <echo>   installr:  Installs (only) the release package.</echo>
1227        <echo>   installi:  Installs (only) the instrumented package.</echo>
1228        <echo>   installt:  Installs (only) the test and tested packages.</echo>
1229        <echo>   uninstall: Uninstalls the application from a running emulator or</echo>
1230        <echo>              device.</echo>
1231    </target>
1232</project>
1233