9

This is a follow-up to: BlackBerry - use own JAR file in own project & BlackBerry - Ant build script for more complex apps. This problem has now been solved below.

Aim

I want to:

  1. use Ant (bb-ant-tools) to build my library into a JAR file
  2. include that JAR file in a project
  3. use Ant to build that project into a COD that will run on the device (without external COD files).

The important part is to use Ant to do the final stage of the build.

All posts I have found for this problem use Eclipse for that final build stage (details at BlackBerry - use own JAR file in own project).


Progress

  1. I can build the library project into a JAR using Ant.
  2. In Eclipse, I can add that JAR file to a project, and build it as desired (single COD, no external dependencies). It will run on the device.
  3. In Ant, I can also make a build that relies on an extra COD library to contain the runtime code - this is close to what I need.

Problem

I can build the final project with Ant. But the resulting COD file does not include any runtime code from my library.

Many posts I have read show how this can be done using extra COD files for the library. I would like to avoid this.

How can I include a JAR into my project without external dependencies, using Ant? I believe this is possible because I can do it using Eclipse.


Workaround

My current workaround is to include my SDK / library project as source code (as per esaj's answer below), rather than as a JAR file. This has some disadvantages over the JAR approach, but I have a build that runs on the device successfully.


(I hope its OK to cross-reference this question with the following long list of links?)

StackOverflow links:

This one gives other links - quite useful:

These not so useful:

RIM:

Community
  • 1
  • 1
Richard Le Mesurier
  • 27,993
  • 19
  • 127
  • 242
  • When doing it manually in eclipse plugin, in Java build path -> the last tab is called "Order & export". If you enable the check for your library, it exports the class files to cod. – Mister Smith May 14 '12 at 14:27
  • @mistersmith: Thanks, if anyone wants to see more details on that method, I have covered it comprehensively in this answer: [BlackBerry - use own JAR file in own project](http://stackoverflow.com/a/9978353/383414) – Richard Le Mesurier May 14 '12 at 14:34

2 Answers2

4

Have you tried pointing to the library in the src section under rapc?

E.g.:

<rapc ...>
  <src>
    <fileset dir="${buildDirectory}">
      <include name="src/**/*.rrh" />
      <include name="src/**/*.rrc" />
      <include name="src/**/*.java" />
      <include name="res/**/*.*" />
      <!-- Libraries -->
      <include name="lib/**/*.*" />
    </fileset>
  </src>
</rapc>
RThomas
  • 10,229
  • 2
  • 43
  • 58
bobbydavros
  • 156
  • 1
  • Seems to run - found NullPointerException being thrown before app is initialised (code problem)... maybe this was why I thought this method wouldn't work... will add more to this after investigation. Oddly when building the app adding the library code as source code, the NullPointerException is not thrown. Something came out different here... – Richard Le Mesurier May 18 '12 at 12:23
  • A previous dev had placed some resource files into the `` folders. These were not being included by the script as written in answer above. I have updated the answer with my fix, in case it catches up anyone else (it is a bounty question after all). – Richard Le Mesurier May 23 '12 at 06:31
1

I had a similar problem last year, I had created a "framework" that was used as a base for multiple BB-applications, but run into problems with multiple CODs (I don't remember exactly what, something like the device refused to install multiple applications that had same external cods, if the external CODs weren't installed separately first, and then the applications). As the applications could be installed separately (one person might install only app A, another might install only app B, and yet another might install both A and B), the whole framework needed to be included in all the apps using it. I cooked up this Ant-script using bb-ant-tools (hopefully I didn't break anything removing some stuff specific to our apps and obfuscating package names etc):

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

<project name="${description}" default="build" basedir=".">

    <taskdef resource="bb-ant-defs.xml" classpath="lib/bb-ant-tools.jar" />

    <!-- rapc and sigtool require the jde.home property to be set -->
    <!-- NOTE: You may need to copy the signature files from Eclipse\plugins\net.rim.ejde\vmTools to the components\bin -dir 
        if the keys were installed using the Eclipse-plugin     -->
    <property name="jdehome" value="C:\BB\Eclipse\plugins\net.rim.ejde.componentpack5.0.0_5.0.0.25\components" />

    <!-- Framework source locations, these must be set correctly -->
    <property name="frameworkRes.dir" value="C:\BB\workspace\BB_Framework\res" />
    <property name="frameworkSrc.dir" value="C:\BB\workspace\BB_Framework\src\com\whatever\frame" />

    <!-- Locations for simulator, binaries, jde home, don't touch these -->
    <property name="simulator" value="${jdehome}\simulator" />
    <property name="bin" value="${jdehome}\bin" />
    <property name="jde.home" location="${jdehome}" />

    <!-- directory of simulator to copy files to -->
    <property name="simulator.home" location="${simulator}" />

    <property name="src.dir" location="src" />
    <property name="build.dir" location="build" />
    <property name="temp.dir" location="C:\tempsrc" />

    <!-- Project specific -->
    <!-- Application title -->
    <property name="app.title" value="Application Name" />
    <property name="app.version" value="1.0.0" />
    <!-- Value to prepend before frame-class packages -->
    <property name="frame.prefix" value="appname" />
    <!-- Name of the COD to produce --> 
    <property name="cod.name" value="Appname" />

    <target name="build">
        <mkdir dir="${build.dir}" />
        <delete dir="${temp.dir}" />
        <mkdir dir="${temp.dir}" />
        <mkdir dir="${temp.dir}\${frame.prefix}" />

        <copy toDir="${temp.dir}">
            <fileset dir="${src.dir}">
                <include name="**/*.java" />
            </fileset>
        </copy>

        <copy toDir="${temp.dir}\${frame.prefix}">
            <fileset dir="${frameworkSrc.dir}">
                <include name="**/*.java" />
            </fileset>
        </copy>

        <copy toDir="${temp.dir}\res">
            <fileset dir="${frameworkRes.dir}">
                <include name="**/*" />
            </fileset>
        </copy>

        <copy toDir="${temp.dir}\res">
            <fileset dir="res">
                <include name="**/*" />
            </fileset>
        </copy>

        <!-- This replaces the package names for classes copied from under framework-directory to ${frame.prefix} -directory -->    
        <replace dir="${temp.dir}" value="${frame.prefix}">
            <include name="**/*.java"/>
            <replacetoken>com.whatever.frame</replacetoken>
        </replace>

        <rapc output="${cod.name}" srcdir="${temp.dir}" destdir="${build.dir}">
            <jdp title="${app.title}" 
                version="${app.version}" 
                vendor="Your Company"
                icon="../res/img/icon.png"
            />
        </rapc>
    </target>

    <target name="sign">
        <sigtool codfile="${build.dir}/${cod.name}.cod" />
    </target>

    <target name="clean">
        <delete dir="${build.dir}" />
    </target>

    <target name="load-simulator" depends="build">
        <copy todir="${simulator.home}">
            <fileset dir="${build.dir}" includes="*.cod,*.cso,*.debug,*.jad,*.jar" />
        </copy>
    </target>

</project>

What this does, is copy all the java-files and resources from your current project and then from the framework-project to a temporary directory, replacing package names on the way for the frame-work files (as they're put into a separately named directory), this has to do with the fact that the devices also refused to install multiple applications that had same classes under same packages (namely, the framework classes, for your case this might not be necessary). After the copying and replacing is done, the application is built to target build-directory using rapc. There are separate tasks for signing, cleaning and loading the app to a simulator. Hope this helps.

esaj
  • 15,369
  • 4
  • 35
  • 52
  • So this essentially does the SDK/framework refactoring at the source code level? Do I understand correctly? – Richard Le Mesurier May 17 '12 at 14:37
  • @RichardLeMesurier: Yes, the library is copied as source files and then built alongside with the application using it. I do understand you were looking for a solution where the Ant-build compiles a separate jar from your library, but this should work unless it's absolutely necessary for the library to be in a separate jar/cod. You can still write your application code using the original packages and keeping the library and application as separate projects, and if you don't have multiple applications using the library, the renaming of packages-step shouldn't be necessary. – esaj May 17 '12 at 14:45
  • This is a very useful answer, that solves a lot of problems (although not exactly for this question). I think it will be very useful to copy it over to another question of mine at [BlackBerry: create COD from JAR source file in Ant script](http://stackoverflow.com/questions/10632262/blackberry-create-cod-from-jar-source-file-in-ant-script). If you do not want to copy it over, I will do that in a week or so. – Richard Le Mesurier May 21 '12 at 06:06
  • @RichardLeMesurier: no problem, I'll copy it over. – esaj May 21 '12 at 07:08