3

I have a master build file that I use to build a series of Android projects. Each of these Android projects reference the same Android library project (I'll call it CoreLibrary). The following is my subant task.

 <target name="build" description="Builds (only) all applications">
    <subant>
        <target name="debug" />
        <fileset refid="all-applications" />
    </subant>
</target>

Question: Is there something I can do to prevent CoreLibrary from being re-built for each Android project in the all-applications fileset of my subant task? This would significantly speed up my build-time so I am hoping there is something I can do.

Justin Breitfeller
  • 13,737
  • 4
  • 39
  • 47
  • Right now, I don't think so. The next major tools release may have support for distributing library projects as JARs. In that case, you could have your Ant script build the library project and have the other projects reference the JAR, rather than the library project directly. At least, in theory. – CommonsWare Jan 11 '12 at 00:15
  • Thanks. I had hoped the new-ish build-process that prevents repeated building of libraries could somehow help here. In other words, I know that if I have Lib A and Lib B referencing Lib C, Lib C will only get built once now when building a project that references Lib A and B. I was hoping that if I could figure a way to leverage that with this problem. – Justin Breitfeller Jan 11 '12 at 16:11
  • @CommonsWare I updated an answer that you may want to look at. As far as I can tell it should work fine, but I am not sure when the `nodeps` target was added to the SDK. – Justin Breitfeller Apr 19 '12 at 17:22
  • `nodeps` would be part of the build tools, not the SDK per se. Hence, so long as it works on the current tools, everyone should be able to use it. In terms of whether `nodeps` will be supported long-term, you might want to ask that on the `adt-dev` Google Group. – CommonsWare Apr 19 '12 at 17:29
  • Good idea. They appear to use it internally when building libraries since they actually resolve libraries in dependency order and, as such, don't need dependencies to be auto resolved and built. In any case, for anyone using a master-build file, it would appear what I proposed should work. – Justin Breitfeller Apr 19 '12 at 17:34

3 Answers3

6

Actually, I just recently figured out a way to solve this problem. The basic idea is that, my ANT file finds all library projects, builds them first, and then builds the remainder of my projects with the nodeps target. This effectively prevents the situation where CoreLibrary is constantly re-compiled.

<?xml version="1.0" encoding="UTF-8"?>
<project name="MasterBuild">

 <!-- A property for the name of the file that contains 'android.library=true' (which is how we find library projects) -->
<property name="library.setting.file.name" value="project.properties" />

<filelist id="normal-projects" dir=".">
    <!-- You want to add your own projects here -->
    <file name="./MyProject/build.xml" />
    <file name="./MyProject2/build.xml" />
    <file name="./MyProject3/build.xml" />
</filelist>

<fileset id="all-libraries-properties" dir=".">
    <include name="*/${library.setting.file.name}" />
    <contains casesensitive="true" text="android.library=true" />
</fileset>

<pathconvert property="all-libraries" refid="all-libraries-properties">
    <globmapper from="*${library.setting.file.name}" to="*build.xml" />
</pathconvert>    

<target name="-set-debug-mode">
    <property name="build.target" value="debug" />
    <property name="install.target" value="installd" />
</target>

<target name="-set-release-mode">
    <property name="build.target" value="release" />
    <property name="install.target" value="installr" />
</target>

<target name="-build-dependencies" unless="built.dependencies">
    <property name="built.dependencies" value="true" />
    <subant buildpath="${all-libraries}" target="${build.target}" inheritall="false" />
</target>

<target name="-build-normal-projects" depends="-build-dependencies">
    <subant inheritall="false">
        <target name="nodeps" />
        <target name="${build.target}" />
        <resources refid="normal-projects" />
    </subant>
</target>

<target name="-install-normal-projects">
    <subant inheritall="false">
        <target name="${install.target}" />
        <resources refid="normal-projects" />
    </subant>
</target>

<target name="debug" depends="-set-debug-mode, -build-normal-projects" description="Builds (only) a debug-key signed application" />
<target name="release" depends="-set-release-mode, -build-normal-projects" description="Builds (only) a release-key signed application" />

<target name="installd" depends="-set-debug-mode, -install-normal-projects" description="Installs (only) a debug-key signed application" />
<target name="installr" depends="-set-release-mode, -install-normal-projects" description="Installs (only) a release-key signed application" />

</project>

Note This solution could be improved if I wrote a task that actually found the library dependency order so I could build libraries with the nodeps target. Additionally, there is probably a way to automatically detect "normal projects", but I haven't needed that yet. Finally, I unrolled quite a few things from my normal ANT file to bring this here so hopefully I didn't miss anything. The concept, however, is present.

Justin Breitfeller
  • 13,737
  • 4
  • 39
  • 47
1

If you use the Android Maven Plugin you can just build all the respective parts individually or as modules together and you reuse your core library as jars or as apklib (if they have resources and such). The built-in dependency mechanism of Maven will take care of integrating the different libraries.

Look at e.g. RoboGuice or ActionBarSherlock and their example apps to see how that works.

Also if you then use a repository manager and deploy the libraries there all your team members can pick up libraries from there and they could e.g. be build by the CI server.

Manfred Moser
  • 29,539
  • 13
  • 92
  • 123
  • Do you know what this plugin is actually doing behind the scenes? Currently, our team doesn't use Maven, but I would imagine they are doing something similar to what my answer is doing. – Justin Breitfeller Apr 25 '12 at 13:15
  • Yes I know. I am core contributor, author and presenter about it. It uses dependency mgt to pull in artifacts from repositories.. and can deploy to them. And it has first class support for grouping projects together and lots more. Look at the website on google code. The Android SDK will get something along these lines in one of the future versions according to Xavier. – Manfred Moser Apr 25 '12 at 16:23
  • I see. Does Maven use an entirely custom build system to compile everything together? In other words, does it just uses the raw executable tools and build everything that way (instead of ANT / eclipse)? If so, that might be problematic because I do have certain projects that I need to build in a custom manner. In any case, when I get a chance I will see what your plugin can do. – Justin Breitfeller Apr 25 '12 at 18:40
  • No .. it reuses the SDK .. just not the ant tasks but rather the exexutables or directly the jars provided with the sdk.. it works for a LOT of situations.. feel free to ask about it on the mailing list if you need more details. – Manfred Moser Apr 25 '12 at 18:42
0

If your library projects are java-only (no resources) you can allready distribute it as jar - and than manage depnedencies with ivy + ivy ant task for resolving dependiencies in build file. but they still will be build from classes to dex files.

Tomasz Gawel
  • 8,379
  • 4
  • 36
  • 61