<ANTENNA/>

Antenna

An Ant-to-End Solution For Wireless Java

Version 0.9.14

(c) 2002-2006 Jörg Pleumann

Latest news, XX-Jul-06:
Version 0.9.14 available. Most notable new feature is WTK support up to version 2.5 (thanks to Fred Grott).

News | Overview | Download | Setup | JAD | Build | Package | MakePRC | RAPC
Run | Preverify | Obfuscate | SmartLink | Preprocess | Deploy | History | Plan

Overview

Antenna provides a set of Ant tasks suitable for developing wireless Java applications targeted at the Mobile Information Device Profile (MIDP). With Antenna, you can compile, preverify, package, obfuscate, and run your MIDP applications (aka MIDlets), manipulate Java Application Descriptor (JAD) files, as well as convert JAR files to PRC files designed to run on the MIDP for PalmOS implementations from Sun and IBM. Deployment is supported via a deployment task and a corresponding HTTP servlet for Over-the-Air (OTA) provisioning. A small preprocessor allows to generate different variants of a MIDlet from a single source.

Of course you can also do much of that with the J2ME Wireless Toolkit or other Java IDEs, but using an Ant script results in a defined and reproducable build process that is independent of a particular programming environment. See this article for an excellent introduction to Ant as well as reasons for using it.

The Antenna tasks are mostly built around functionality provided by the Wireless Toolkit and thus require this software. If you want to make use of the obfuscation task, you should have one (or both) of the free RetroGuard and ProGuard obfuscators on your harddisk. Naturally, Ant itself is also needed, where version 1.5.0 seems to be the minimum required version as reported by users. Antenna works very well in Ant-supportive IDEs like Eclipse or JEdit.

Here is a list of tasks contained in the package:

Task Purpose
WtkJad A task that is able to create new JAD files from scratch or update existing ones.
WtkBuild An extension to Ant's standard javac task that sets the appropriate bootclasspath allows for preverification.
WtkPackage An extension to Ant's standard jar task that handles the JAD file correctly and is able to include complete libraries into the resulting JAR file. It also allows for preverification and obfuscation of the generated file.
WtkMakePrc A task to convert an existing JAR/JAD into a PalmOS PRC file that can be used with MIDP for Palm OS.
WtkRun A task to run a MIDlet suite contained in a JAR/JAD file in the Wireless Toolkit's emulator.
WtkRapc A task that invokes the BlackBerry rapc compiler, and generates BlackBerry .cod files.
WtkPreverify A standalone task for preverifying a set of classes. This task is normally not needed, since the build and packaging tasks include the same functionality.
WtkObfuscate A standalone task for obfuscating a JAR file. This task is normally not needed, since the packaging task includes the same functionality.
WtkSmartLink A task for removing unnecessary classes from a JAR file.
WtkPreprocess A simple Java preprocessor, similar to the ones known from C and other languages, that allows for conditional compilation and including source files.
WtkDeploy A deployment task that allows to put a MIDlet on a remote Web server for later download.

The Antenna project is hosted on SourceForge and distributed under the GNU Lesser General Public License (LGPL). You can download the most recent version here.

Mailing List

There's also a mailing list for discussing Antenna. The list address is "antenna at pleumann dot de". Subscriptions are managed via "antenna-request at pleumann dot de". Send a mail with subject "subscribe" to become a member. Due to ever-increasing spam problems and my unwillingness to delete dozens of garbage messages per day, posting requires list membership. External postings will be rejected automatically and without moderation. I will provide a HTML list archive once I find the time.

Contact

If you find Antenna useful, you might want to send a picture postcard of your hometown or country telling me so. My surface mail address is: Jörg Pleumann, Amselstrasse 41, D-45472 Mülheim, Germany. E-mails are also fine, but don't underestimate the productivity (and ego) boost that a wall full of postcards next to my desk will cause. :)


Setup

Setting up Antenna is rather straightforward. The first thing you want to do is either put the Antenna JAR file into Ant's lib directory or your classpath. Then there's a number of properties you might want to adjust to your needs, either in each build.xml file you use or in a global file that is imported in the specific build.xml files.

Making the tasks available to Ant

To make the tasks available in your build scripts, add the following lines (assuming the JAR file is somewhere in your classpath or in Ant's lib directory):

<taskdef name="wtkjad" classname="de.pleumann.antenna.WtkJad"/>
<taskdef name="wtkbuild" classname="de.pleumann.antenna.WtkBuild"/>
<taskdef name="wtkpackage" classname="de.pleumann.antenna.WtkPackage"/>
<taskdef name="wtkmakeprc" classname="de.pleumann.antenna.WtkMakePrc"/>
<taskdef name="wtkrun" classname="de.pleumann.antenna.WtkRun"/>
<taskdef name="wtkpreverify" classname="de.pleumann.antenna.WtkPreverify"/>
<taskdef name="wtkobfuscate" classname="de.pleumann.antenna.WtkObfuscate"/>
<taskdef name="wtksmartlink" classname="de.pleumann.antenna.WtkSmartLink"/>
<taskdef name="wtkpreprocess" classname="de.pleumann.antenna.WtkPreprocess"/>
<taskdef name="wtkdeploy" classname="de.pleumann.antenna.WtkDeploy"/>
<taskdef name="wtkrapc" classname="de.pleumann.antenna.WtkRapc"/>
		
Beginning with Antenna 0.9.11, you can also use this much shorter version, which relies on existing task definitions in Antenna's JAR file. In that case, the Antenna JAR needs to be in your classpath, which is usually automatically the case when it is in Ant's lib directory.
<taskdef resource="antenna.properties"/>
		
If you don't want to put Antenna into your classpath, the following variant should also work:
<taskdef resource="antenna.properties " classpath="full name of Antenna jar file"/>
		

Selecting a WTK and APIs for a project

All Antenna tasks rely on a property "wtk.home" that points to the directory where the Wireless Toolkit has been installed. So, if your WTK resides in "c:\Java\wtk-1.0.4", you need to add the following line to your build scripts:

<property name="wtk.home" value="c:\Java\wtk-1.0.4"/>
		
Depending on the WTK version you are using, a different set of base and extension APIs is available for your MIDlets. Antenna automatically detects your WTK version and selects APIs according to the following simple rule: The default BOOTCLASSPATH consists of CLDC-1.0 and MIDP 1.0 with no extension APIs. If your want to change these settings, you can do so by using the following properties (the "WTK" column specifies WTK version required for this property to be taken into account):

Property Default Purpose WTK
wtk.cldc.version 1.0 Specifies the version of CLDC to use. 2.1+
wtk.midp.version 2.0 for WTK 2.x, 1.0 otherwise. Specifies the version of MIDP to use. 2.0+
wtk.mmapi.enabled false Enables or disables the Multimedia API (MMAPI). 2.0+
wtk.wma.enabled false Enables or disables the Wireless Messaging API (WMA). 2.0+
wtk.wma.version 1.0 Selects the supported version of the Wireless Messaging API (WMA). Currently either 1.0 (JSR-120) or 2.0 (JSR-205) is allowed. 2.3+
wtk.j2mews.enabled false Enables or disables the J2ME Web Services API (J2MEWS). 2.1+
wtk.bluetooth.enabled false Enables or disables the J2ME Bluetooth API (JSR-82). 2.2+
wtk.java3d.enabled false Enables or disables the J2ME 3D API (JSR-184). 2.2+
wtk.optionalpda.enabled false Enables or disables the J2ME optional PDA packages (JSR-75). 2.2+
wtk.locationservices.enabled false Enables or disables the J2ME location services API (JSR-179). 2.3+
wtk.contenthandler.enabled false Enables or disables the J2ME content handler API (JSR-211). 2.3+
wtk.satsa.enabled false Enables or disables the J2ME Security and Trust Services API (JSR-177). 2.3+
wtk.miapi.enabled false Enables or disables the J2ME Mobile Internationalization API (JSR-238). 2.5+
wtk.ams.enabled false Enables or disables the J2ME Advanced Multimedia Supplements API (JSR-234). 2.5+
wtk.papi.enabled false Enables or disables the J2ME Payment API (JSR-229). 2.5+
wtk.s2dvgapi.enabled false Enables or disables the J2ME Scalable 2D Vector Graphics API (JSR-226). 2.5+
wtk.sipapi.enabled false Enables or disables the J2ME Session Initiation Protocol API (JSR-180). 2.5+
wtk.midpapi Varies Sets a totally custom BOOTCLASSPATH. Use this property if the set of APIs you need is not covered by the above properties (for example because you are using the system libraries provided another vendor or you have some important additional libraries). 1.0+

Please note that the properties for selecting a CLDC and MIDP version also set the default values for the "config" and "profile" properties used in the WtkJad and WtkPackage tasks. So, if you set the versions properly at the beginning of your build.xml file, you normally don't have to deal with these values again.

Using an obfuscator

To allow obfuscation, either RetroGuard or ProGuard is required. Simply put one (or both) of the following files into the WTK's "bin" directory or make sure you have at least one of them in your CLASSPATH:

retroguard.jar
proguard.jar
		
Alternatively, you can also set the following properties to the home directories of existing installations of the obfuscators (where home means the root directory of the software, which is, for ProGuard, one level higher than the lib directory where the JAR file is located):
<property name="wtk.retrogard.home" value="your path goes here"/>
<property name="wtk.proguard.home" value="your path goes here"/>
		

If both obfuscators are available, ProGuard is preferred because it usually provides better results.

Note that if using RetroGuard and setting a BOOTCLASSPATH through the wtk.midpapi property, it might also become necessary to set the following property:

<property name="wtk.emptyapi" value="your path goes here"/>
		
This property latter points to the "emptied-out" MIDP API (normally in "wtklib/emptyapi.zip") and is used for obfuscation with RetroGuard because this tool has some problems obfuscating against the normal MIDP API. This does not apply to ProGuard.

Using the Websphere Micro Environment Toolkit for PalmOS

Starting from version 0.9.11, Antenna also supports the PRC converter from the
IBM Websphere Micro Environment Toolkit for PalmOS (WME). This converter is needed to generate PRC files for IBM J9 VM that runs on the new Tungsten devices. To use it, specify the WME's home directory as follows:
<property name="wtk.wme.home" value="your path goes here"/>
		
The current release of the WME already supports CLDC 1.1 and MIDP 2.0 plus some extension APIs. The MIDP for PalmOS from Sun, in contrast, seems to be pretty much dead. Please note that the name of this property has changed with Antenna 0.9.12 for reasons of consistency.

Using Over-the-Air provisioning

In addition to the various Ant tasks, the project also provides a simple servlet for OTA provisioning of MIDlet suites. This servlet is included in the same ZIP file as the tasks. It allows to upload MIDlet suites via the
WtkDeploy task. Once uploaded, a MIDlet suite can be downloaded by WWW and WAP clients. Lists of available suites can be retrieved in HTML and WML. The format of these lists can be modified using a template mechanism.

The following steps are necessary to run the OTA servlet:

  1. Install a servlet-capable Web server, preferredly Tomcat.
  2. Add a new Web application, for example by creating a directory "antenna" under "<tomcat>/webapps". Create a directory "WEB-INF" and a subdirectory "WEB-INF/lib" there.
  3. Copy the "web.xml" file from the "etc" directory of the Antenna source distribution (or from CVS) to "WEB-INF" and adjust it to your personal needs. Copy the "antenna-bin.jar" binary distribution file to "WEB-INF/lib".
  4. You should have a working configuration now. Test it by starting Tomcat and accessing the servlet using a Web browser or the Wireless Toolkit's OTA provisioning mechanism. If the servlet URL is "http://localhost/antenna", the HTML and WML pages are available as "http://localhost/antenna/index.html" and "http://localhost/antenna/index.wml", respectively. When only the directory is specified, the servlet tries to determine the correct version from the HTTP request headers.
  5. Test deployment by running the "deploy" sample (modify "build.xml" first).
  6. To create your own layout for the pages, copy the two files from the "res" directory of the Antenna source distribution (or from CVS) to "WEB-INF" and modify them. There's documentation inside the "index.html" file that tells you how to do this.
If you are running the OTA servlet with modified templates, it would be nice if you added a small hyperlink saying "Powered by Antenna" (pointing to the project's homepage) to the bottom of the page. Same if you modify the servlet itself.

A running version of the servlet should be available on my home machine.

Samples

There are several sample build.xml files in the "samples" subdirectory of the Antenna source distribution. These files show how to build the default demo MIDlets contained in the Wireless Toolkit and some others. Running the samples is a good way to test your setup as well as a good starting point for your own build.xml files.


JAD

The WtkJad task allows to create new JAD files from scratch or modify existing ones. In particular, it is able to update the MIDlet-Jar-URL and MIDlet-Jar-Size keys automatically if a JAR file is specified, and increase the MIDlet-Version key if automatic versioning is requested.

The task provides the following parameters:

Parameter Type Required Purpose
jadfile file yes The name of the JAD file to create or update.
jarfile file no The name of the JAR file that accompanies the JAD file. If present, the task tries to update the MIDlet-Jar-URL and MIDlet-Jar-Size attributes. Note that the "deploy" parameter also has an effect on the MIDlet-Jar-URL attribute.
manifest file no If this parameter is present, a MANIFEST file is generated, too. The contents of the manifest are taken from the JAD file, with only the following exceptions:
  • The MIDlet-Jar-Url and MIDlet-Jar-Size keys are obmitted.
  • The MicroEdition-Configuration and MicroEdition-Profile keys are added as specified in the corresponding parameters of the task, or they default to "CLDC-1.0" and "MIDP-1.0", or to what has been set using the wtk.cldc.version and wtk.midp.version properties.
Note that the MANIFEST file is always created from scratch, independent of the "update" parameter.
update boolean no If set to true, an existing JAD file is updated instead of creating a new one from scratch. In update mode, the behaviour is as follows:
  • If a JAR file is specified, the MIDlet-Jar-URL and MIDlet-Jar-Size attributes are modified. Note that the "deploy" parameter also has an effect on the MIDlet-Jar-URL attribute.
  • If one of the name, vendor or version attributes is specified, it overrides the one already present in the JAD file.
  • If at least one MIDlet is specified using the sub-element described below, the whole list of MIDlets in the existing JAD file is cleared.
  • If an attribute is specified using the sub-element described below, it overrides an existing attribute in the JAD file.
target URL no A URL to which the MIDlet suite shall be deployed at a later point. If specified, this URL will prefix the JAR file name in the MIDlet-Jar-URL. The URL must not end with a slash, because one is added automatically.
name string no The name of the MIDlet suite, that is, the value of the MIDlet-Name attribute.
vendor string no The vendor of the MIDlet suite, that is, the value of the MIDlet-Vendor attribute.
version string no The version of the MIDlet suite, that is, the value of the MIDlet-Version attribute.
autoversion boolean no If true, the task attempts to create a new version number for the MIDlet suite. If no MIDlet-Version key exists, version "1.0.0" is assigned. Otherwise, the last of the three numbers is increased by one (assuming some major.minor.micro scheme).
encoding string no Specifies the encoding to use when reading or writing the JAD and MANIFEST files. Defaults to the platform default encoding, when no specified (this might change to UTF-8 in the future).
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.

Midlet

The task allows to specify an arbitrary number of MIDlets using a nested element "midlet". This element element provides the following parameters (note that there is no means to specify a MIDlet number. The MIDlets are numbered automatically instead in the order in which they are specified):

Parameter Type Required Purpose
name string yes The MIDlet's name.
icon String no An icon for the MIDlet, specified as a path relative to the root of the JAR file.
class string yes The name of the main MIDlet class.
if String no Provides fine-grained control over the MIDlets based on properties. The MIDlet will only make it to the JAD file if the given property is defined.
unless String no Provides fine-grained control over the MIDlets based on properties. The MIDlet will only make it to the JAD file if the given property is not defined.

Attribute

The task also allows to specify an arbitrary number of attributes using a nested element "attribute". This element provides the following parameters:

Parameter Type Required Purpose
name string yes The attribute name.
value String no The attribute value. If you don't specify this parameter, the given attribute is removed from the JAD file instead.
if String no Provides fine-grained control over the attributes based on properties. The attribute will only be copied to the JAD file if the given property is defined.
unless String no Provides fine-grained control over the attributes based on properties. The attribute will only be copied to the JAD file if the given property is not defined.


Build

The WtkBuild task is an extension to Ant's standard
Javac task that primarily sets the appropriate classpath and allows for preverification.

The task sets the following parameters of the original Javac task to useful default values:

Parameter Value
target 1.1
debug true
bootclasspath ${wtk.home}/lib/midpapi.zip, or ${wtk.midpapi}, if specified

In addition to these (and other parameter supported by Ant's "Javac" task), this task provides some new parameters:

Parameter Type Required Purpose
preverify boolean no If set to "true", the resulting class files are preverified.
cldc boolean no If set to "false" then "-cldc" is not passed as a parameter to the preverifier. Defaults to "true".
nonative boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nonative" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
nofloat boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nofloat" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
nofinalize boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nofinalize" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.


Package

The WtkPackage task is an extension to Ant's standard
Jar task that handles JAD files correctly and is able to include complete libraries into the resulting JAR file. It also allows for preverification and obfuscation of the generated file.

In some more detail, the task does the following:

  1. It creates or updates a JAR from the files you specify the usual way (for the Jar task). If you specify a libclasspath, the content of these JARs will also be included.
  2. If no MANIFEST file is specified, a temporary one is generated. Its contents are taken from the JAD file, with only the following exceptions:
  3. It desired, it preverifies and/or obfuscates the new JAR file.
  4. Finally, the JAD file is updated for the new JAR file name and size. If you request automatic version numbering, the MIDlet-Version key is attempted to change.

The task provides the following parameters (in addition to those of the standard Jar task):

Parameter Type Required Purpose
jarfile file yes The name of the JAR file to create or update.
jadfile file yes The name of the JAD file that accompanies the JAR file. Note that the JAD file already has to exist. It is not created by the Ant task.
config string no The value of the MicroEdition-Configuration key to write to the MANIFEST.MF. Defaults to "CLDC-1.0" or to what has been set using the wtk.cldc.version propertiy. Only relevant if no MANIFEST is specified.
profile string no The value of the MicroEdition-Profile key to write to the MANIFEST.MF. Defaults to "MIDP-1.0" or to what has been set using the wtk.midp.version propertiy. Only relevant if no MANIFEST is specified.
autoversion boolean no If set to "true", the version number contained in the MIDlet-Version key of the JAD file is attempted to increase. The version number is assumed to follow the "major.minor.micro" scheme. The latter of the three numbers is incremented by one.
preverify boolean no If set to "true", the resulting JAR file is preverified.
cldc boolean no If set to "false" then "-cldc" is not passed as a parameter to the preverifier. Defaults to "true".
nonative boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nonative" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
nofloat boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nofloat" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
nofinalize boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nofinalize" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
obfuscate boolean no If set to "true", the resulting JAR file is obfuscated. All classes are obfuscated with only three exceptions:
  • The main MIDlet classes, denoted by the MIDlet-# keys in the JAD file.
  • Classes to be loaded by name (on a Motorola phone), denoted by an iDEN-Install-Class-# keys.
  • Classes (or parts thereof) explicitly excluded from obfuscation using the <preserve> nested element.
keepmanifestorder boolean no If set to "true", the task keeps the original order of MANIFEST.MF entries in the resulting JAR. Otherwise then entries might be rearranged by Ant (which is usually not a problem).
bootclasspath path no The bootclasspath is needed for preverification and obfuscation. It defaults to the MIDP API contained in ${wtk.home}/lib/midpapi.zip, or ${wtk.midpapi}, if specified. Only for RetroGuard, the emptied-out MIDP API is used.
classpath path no The classpath is needed for preverification and obfuscation. If you use any external libraries other than the MIDP API itself, and these libraries should not be included in the resulting JAR file (for example because they already exist on a certain phone), specify them here.
libclasspath path no The libclasspath is needed for preverification and obfuscation, and it serves to specify libraries to be included in the resulting JAR file. If you use any external libraries that should be included in the resulting JAR file, specify them here. Consider this an equivalent to the Wireless Toolkit's lib directory. Note that you also use Ant's FileSet, ZipFileSet and ZipGroupFileSet nested elements to include existing classes and resources into the JAR.
classpathref string no A reference to a classpath defined elsewhere.
bootclasspathref string no A reference to a bootclasspath defined elsewhere.
libclasspathref string no A reference to a libclasspath defined elsewhere.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.
verbose boolean no Allows to set the verbosity of the task's output.

Preserve

In addition to the various parameters, the task provides one nested element "preserve" that is used during obfuscation. The element has one parameter:

Parameter Type Required Purpose
class string yes Specifies a class to be excluded from obfuscation and/or optimization when RetroGuard or ProGuard are used.
if String no Provides fine-grained control over the classes being preserved. The class will only be preserved if the given property is defined.
unless String no Provides fine-grained control over the classes being preserved. The class will only be preserved if the given property is not defined.


MakePRC

The WtkMakePrc task converts an existing JAR/JAD file combination into a Palm OS PRC file that can be used with either MIDP for Palm OS or the Websphere Micro Environment for PalmOS 5.x upwards. It works in two possible configurations, with the "converter" attribute deciding which one is chosen:

The task provides the following parameters:

Parameter Type Required Purpose
jarfile file at least one of these The JAR file from which to read classes.
jadfile file The JAD file that contains MIDlet definitions.
prcfile file no The Palm OS PRC file to create. Defaults to the JAR file, but with the ".prc" extension.
converter string no The converter to use for generating the PRC file. Possible values are "wtk", which results in Sun's WTK converter being used, or "wme", which calls the converter from the IBM WME. Unless the property "wtk.wme.home" is defined, the WTK converter is the default option, so there's normally no need to change this property.
icon file no An icon to use for the application.
smallicon file no A small icon to use for the application.
name string no The name of the application to display on the Palm.
longname string no A longer name for the application to display on the Palm.
creator string only if type other than "Data" A 4-byte creator ID to use for the application. For non-experimental products, you need to register with PalmSource first.
type string no A type to use for the application. Defaults to "Data".
highres boolean no (WME only) Set to "true" to support High-Resolution mode (320*320, 320*480).
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.


Run

The WtkRun task starts a MIDlet suite in the Wireless Toolkit's emulator. The MIDlet suite needs to be packaged for this, that is, a JAR/JAD file pair has to exist.

The task provides the following parameters:

Parameter Type Required Purpose
jadfile file yes The JAD file that describes the MIDlet suite. The JAR file is taken from the MIDlet-Jar-URL key.
classpath string no Additional classes that are needed for execution.
classpathref string no A reference to a classpath defined elsewhere.
heapsize string no The heap space available to the MIDlet suite. May be something like "65536", "128K" or "1M". Defaults to the latter.
device string no The device (skin) to use during emulation. The Wireless Toolkit comes with the following devices pre-installed:
  • DefaultColorPhone (also default if parameter is not specified at all)
  • DefaultGreyPhone
  • MinimumPhone
  • Motorola_i85s
  • RIMJavaHandheld
  • PalmOS_Device (requires Palm OS emulator)
wait boolean no Specifies whether Ant should wait for the emulator to exit. Defaults to true. Note that this parameter also determines whether you can see the emulator's stdout/stderr streams. If Ant doesn't wait for the emulator to finish, this info goes to /dev/nul.
trace string no Specifies whether the emulator should display verbose information on the MIDlet in execution. This is basically a comma-separated list of items whose possible values seem to depend on the WTK version. Common options are:
  • class - Displays class loading information.
  • gc - Display garbage collection information.
  • all - Displays all trancing information
Please see your WTK documentation for a complete list of options. Of course this parameter only makes sense when used together with "wait=true".
debug address no Enables remote debugging support. The address of the remote debugger needs to be specified in the form <host>:<port>.

Note that you need a special kind of debugger for this to work. The one in Forte/Netbeans seems to work, while the one in Eclipse, unfortunately, doesn't. :(

if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.


Preverify

The WtkPreverify task provides a standalone preverification task. It is normally not needed, since the WtkBuild and WtkPackage tasks include the same functionality. Yet, people who don't like the "all-in-one" nature of the build and packaging tasks might prefer to apply the preverifier in a separate task.

WtkPreverify can operate either on directories or on JAR files, not both. If the input is read from a directory, the output will be written to a directory (that is, we are dealing with single class files). If the input is read from a JAR file, the output will be written to a JAR file. If, in the latter case, no output JAR is specified, the input JAR is overwritten. In addition, if a JAD file is specified, its "MIDlet-Jar-Size" key is updated.

Note: In the past, a number of users reported preverification failures. These should be fixed with Antenna 0.9.11. If you still have problems during preverification, please make sure that jar[.exe] (from the JDK) is in your path. Depending on the order and versions of JDKs and WTKs you installed, this might not be the case, making the preverify[.exe] utility from the WTK fail.

The task provides the following parameters:

Parameter Type Required Purpose
srcdir file Either of these two. The source directory, containing non-preverified classes.
jarfile file The source JAR file, containing non-preverified classes.
destdir file yes, if "srcdir" is being used The target directory to write the preverified classes to.
tojarfile file no, but can be combined with "jarfile" The target JAR file to write the preverified classes to. If not specified, the source JAR is overwritten.
jadfile file no The name of the JAD file that accompanies the JAR file. If the source JAR file is overwritten (no "tojarfile" being specified), the "MIDlet-Jar-Size" key in the JAD is updated when the task is finished.
bootclasspath path no Specifies the basic system classes that are needed by the application. Defaults to the MIDP API contained in ${wtk.home}/lib/midpapi.zip, or ${wtk.midpapi}, if specified.
classpath path no Specifies additional libraries that are needed by the application, but not part of the JAR file (for example libraries that are already available on a certain phone).
classpathref string no A reference to a classpath defined elsewhere.
bootclasspathref string no A reference to a bootclasspath defined elsewhere.
cldc boolean no If set to "false" then "-cldc" is not passed as a parameter to the preverifier. Defaults to "true".
nonative boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nonative" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
nofloat boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nofloat" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
nofinalize boolean no Can be used to allow/forbid certain langage features during preverification. If set to "true", then "-nofinalize" is passed to the preverifier. Please turn "cldc" off before. Otherwise this setting might have no effect.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.


Obfuscate

The WtkObfuscate task provides a standalone obfuscation task. It uses either ProGuard or RetroGuard, depending on which of the two it finds it the WTK's bin directory or in the CLASSPATH. ProGuard is preferred, if both are found, unless the "obfuscator" attribute is specified. The task is normally not needed, since the WtkPackage task includes the same functionality. Yet, people who don't like the "all-in-one" nature of the build and packaging tasks might prefer to apply the obfuscator in a separate task.

The task provides the following parameters:

Parameter Type Required Purpose
jarfile file yes The unobfuscated source JAR file to read classes from.
jadfile file no A JAD file that accompanies the JAR file. The task uses this file to determine the list of classes to exclude from obfuscation as follows:
  • The main MIDlet classes, denoted by the MIDlet-# keys in the JAD file are preserved.
  • Classes to be loaded by name (on a Motorola phone), denoted by an iDEN-Install-Class-# keys are preserved, too.
Additional classes to spare from obfuscation can be specified using the "preserve" nested element.

If the source JAR file is overwritten (no "tojarfile" being specified), the "MIDlet-Jar-Size" key in the JAD is updated when the task is finished.

tojarfile file no The obfuscated target JAR file to create. Defaults to the source JAR file, if not specified.
bootclasspath path no The bootclasspath is needed by the obfuscator. It defaults to the MIDP API contained in ${wtk.home}/lib/midpapi.zip, or ${wtk.midpapi}, if specified. Only for RetroGuard, the emptied-out MIDP API is used.
classpath path no The classpath is needed by the obfuscator. If you use any external libraries other than the MIDP API itself, specify them here.
classpathref string no A reference to a classpath defined elsewhere.
bootclasspathref string no A reference to a bootclasspath defined elsewhere.
obfuscator String no Allows to choose between ProGuard and RetroGuard, in case both obfuscators are present. Valid arguments are "proguard" and "retroguard". If this attribute is not specified, ProGuard is always preferred over RetroGuard.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.
verbose boolean no Allows to set the verbosity of the task's output.

Preserve

In addition to the above parameters, the task provides one nested element "preserve" that specifies classes that should be excluded from obfuscation. This is mostly the case for classes that are loaded by name while the application is running. This nested element is supported by RetroGuard as well as ProGuard, so it's "portable". If you are looking for a means to pass obfuscator-specific arguments, have a look at the "argument" nested element below.

Parameter Type Required Purpose
class string yes The fully qualified name of a class that should be neither obfuscated nor removed (if ProGuard is used and the class is not necessary).
if String no Provides fine-grained control over the classes being preserved. The class will only be preserved if the given property is defined.
unless String no Provides fine-grained control over the classes being preserved. The class will only be preserved if the given property is not defined.

Argument

The "argument" nested element allows to pass obfuscator-specific arguments. In contrast to the general parameters of the obfuscator task and the "preserve" nested element, this one is not portable. Arguments are passed to the obfuscator verbatim. Please see the RetroGuard or ProGuard documentation for a complete list of options supported.

Parameter Type Required Purpose
value string yes Specifies the argument to pass to the obfuscator.
if String no Provides fine-grained control over the arguments. The argument will only be applied if the given property is defined.
unless String no Provides fine-grained control over the arguments. The argument will only be applied if the given property is not defined.


SmartLink

The WtkSmartLink task removes unnecessary classes from a given JAR file. It can be seen as some kind of "smart linker" (hence the name), although what it does bears more resemblance to an optimization that takes place after linking. Anyway, the task removes each class that is not "necessary". A class is considered necessary if it has at least one of the the following properties:
  1. It is one the main MIDlet classes, denoted by a MIDlet-# key in the JAD file.
  2. It is a class to be loaded by name (on a Motorola phone), denoted by an iDEN-Install-Class-# key.
  3. It is explicitly excluded from smartlinking using the <preserve> nested element.
  4. It is needed (imported) by another class that is necessary.
Note that the optimization mechanism is very simple. It only builds a tree of plain class dependencies (more or less equivalent to "import" information). It does not attempt to utilize any kind of data flow analysis on methods to achieve better results. Since I was only looking for a simple (but working) means to get unneeded parts of libraries out of my JAR file, this will probably not change in the near future (unless I find some spare time).

The task provides the following parameters:

Parameter Type Required Purpose
jarfile file yes The name of the JAR file to optimize.
jadfile file yes The name of the JAD file that accompanies the JAR file. If the source JAR file is overwritten (no "tojarfile" being specified), the "MIDlet-Jar-Size" key in the JAD is updated when the task is finished.
tojarfile file no The name of the resulting, optimized JAR file. Defaults to the original JAR file, if not specified.
bootclasspath path no Specifies the basic system classes that are needed by the application. Defaults to the MIDP API contained in ${wtk.home}/lib/midpapi.zip, or ${wtk.midpapi}, if specified.
classpath path no Specifies additional libraries that are needed by the application, but not part of the JAR file (for example libraries that are already available on a certain phone).
classpathref string no A reference to a classpath defined elsewhere.
bootclasspathref string no A reference to a bootclasspath defined elsewhere.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.

Preserve

In addition to the various parameters, the task provides one nested element "preserve" that specifies classes that should be preserved in the JAR file even if the optimizing process detects them to be unnecessary. This is mostly the case for classes that are loaded by name while the application is running.

Parameter Type Required Purpose
class string yes The fully qualified name of a class that needs to be in the JAR file even if the smartlinking task thinks that it doesn't.
if String no Provides fine-grained control over the classes being preserved. The class will only be preserved if the given property is defined.
unless String no Provides fine-grained control over the classes being preserved. The class will only be preserved if the given property is not defined.


Preprocess

The WtkPreprocess task provides a simple preprocessor, similar to the ones known from C and other languages. It allows for conditional compilation and inclusion of one source file into another and is helpful when trying to maintain a single source for several devices, each having its own bugs, add-on APIs, etc.

Preprocessing source files to manage implementation differences is quite unusual in Java programming. Actually it might be considered "evil technology" by OO purists. While the latter is somewhat true - interfaces, abstract classes and loading classes by name are definitely the cleaner approach - pure OO is something you often cannot afford when developing for devices that accept only JAR files up to 30 KB. A simple interface easily costs a kilobyte or more in the JAR. Loading implementation-specific classes by name usually gets in the way of obfuscation. A conditionally compiled block, on the other hand, costs absolutely nothing (apart, maybe, from a bit of pride, in case you consider yourself an OO purist, but isn't that a small price to pay for a MIDlet that works merrily on dozens of different mobile phones?).

Please note that the task only preprocesses the source files, but doesn't compile them. So you still have to run the Java compiler on the preprocessed files afterwards. Since the preprocessor doesn't filter "inactive" conditional parts by removing them, but by commenting them out instead, line numbers for compiler errors are usually the same as for the original code (unless you are using #include).

In addition to conditional compilation the preprocessor replaces Ant-style properties in the source-code.

The task provides the following parameters:

Parameter Type Required Purpose
srcdir file yes The source directory from which Java source files are being preprocessed.
destdir file yes The destination directory to which preprocessed files are written.
newext string no Specifies a new file extension for all files that have gone through the preprocessor. Useful when you save the files to preprocess with a special extension to distinguish them from normal Java files. The new extension replaces everything from (and including) the first dot in the filename up to the end, so when you specify newext=".java", a file "MyFile.j2me.pp" becomes "MyFile.java" once it goes through the peprocessor. If you don't specify this parameter, file extensions are not changed.
indent boolean no Controls indentation of comments that the preprocessor writes into the target files. Defaults to true, which results in comments having the same indentation as the the original line. Setting it to false results in comments starting at the beginning of a line.
symbols string no A comma-separated list of identifiers that are initially defined for each file the preprocessor is invoked on.
encoding string no Specifies the encoding to use when reading or writing source files. Defaults to the platform default encoding, if not specified.
filter boolean no When set to true, the preprocessor filters all directives and "inactive" conditional parts. The resulting file contains only the actual Java source code that goes into the compiler. Defaults to false.
verbose boolean no Turn verbose output on or off.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.

The task forms an implicit FileSet, thus the usual "include", "exclude" etc. nested elements are used to specify the source files for preprocessing. The pattern "**/*.java" is included in this FileSet per default, so it is normally enough to specify the source and destination directories.

Directives

The preprocessor supports the following directives inside a Java source file. All directives must immediately follow a "//" comment that starts at the beginning of a line (whitespace is allowed left of them, but no Java code). That way, they don't interfere with normal Java compilation. Directives must not span multiple lines of code.

Directive Decription
#define <identifier> Defines an identifier, thus making its value "true" when it is referenced in further expressions.
#undefine <identifier> Undefines an identifier, thus making its value "false" when it is referenced in further expressions.
#ifdef <identifier> The following lines are compiled only if the given identifier is defined (or undefined, in the case of an "#ifndef" directive). "#else" does exactly what your think it does. Each directive must be ultimately closed by an "#endif" directive. The "#elifdef" and "#elifndef" directives help to specify longer conditional cascades without having to nest each level.

The "#if" and "#elif" directives even allow to use complex expressions. These expressions are very much like Java boolean expressions. They may consist of identifiers, parentheses and the usual "&&", "||", "^", and "!" operators.

Please note that "#ifdef" and "#ifndef" don't support complex expressions. They only expect a single argument - the symbol to be checked.

#ifndef <identifier>
#else
#endif
#elifdef <identifier>
#elifndef <identifier>
#if <expression>
#elif <expression>
#include <filename> Includes the given source file at the current position. Must be terminated by "#endinclude" for technical reasons. The filename may also be given as an Ant-style property (${name}). The property needs to be defined in your build.xml file then. Note that relative file names are interpreted as relative to the build.xml file.
#endinclude


Deploy

The WtkDeploy allows to deploy a MIDlet suite to a Web server for later download by users. Currently, a prerequisite is that the server is running the Antenna
OTA servlet. Other methods might be added at a later point.

The task provides the following parameters:

Parameter Type Required Purpose
jadfile file yes The JAD file to deploy.
jarfile file yes The JAR file to deploy.
target URL no The URL under the OTA servlet can be found. Must start with "http://". Must include a port number, if the servlet is not running on port 80. The parameter can be omitted if the deployment target has already been specified in the JAD file using the JAD task's "target" parameter.
delete boolean no If true, existing JAR and JAD files are deleted from the server instead of uploading new ones.
login string no Specifies a login. Needed if the servlet is configured to require authentication.
password string no Specifies a password. Needed if the servlet is configured to require authentication.
if String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is defined.
unless String no Provides fine-grained control over task execution based on a property definition. The task will only be executed if the given property is not defined.


RAPC

The WtkRapc task invokes the BlackBerry rapc compiler. It takes for input a list of .java files, or a JAR file, and generates a .cod file that can be loaded onto the BlackBerry handset.

This Ant task assumes the BlackBerry build tools are already installed and accessible.

Before using this task, you must define property bb.buildjars.home, which defines where to find the BlackBerry rapc compiler, for example:

    <property name="bb.buildjars.home" location="..."/>

To define the RAPC task, do as follows:

    <taskdef name="wtkrapc" classname="de.pleumann.antenna.WtkRapc" classpath="${buildjars.home}/antenna-bin-0.9.12a.jar"/>

The task provides the following parameters:

Parameter Type Required Purpose
jadfile file yes The name of the JAD file to use
source file yes List of .java files or the name of the JAR file containing the input java classes.
codename string yes The codename to for the generated .cod file.
import file yes List of import libraries, such as the BlackBerry Java APIs.
destdir file yes If specified, indicates the directory where to copy the JAD, ALX, and generated .cod file.
quiet boolean no If specified, indicates to use the -quiet argument indicating rapc to use the quiet console output mode.
midlet boolean no If specified, indicates to use the -midlet argument, indicating rapc to build a MIDlet and corresponding JAR.

Usage:

<target name="rapc" description="RIM COD Compiler" depends="jar">
    <wtkrapc jadfile="${jadfile}" source="${jarfile}" codename="${codename}" import="${bb.api.jar}" destdir="output/tocod/"/ quiet="true" midlet="false">
</target>

It is good practice to build your MIDP application using Antenna's steps WtkBuild and so on, which produces a JAR file, and input this JAR file into the RAPC step. This approach allows you to separate the generation of standard MIDlet and BlackBerry packaging.

*Note that the BlackBerry tools, such as RAPC, are only available on Microsoft Windows platforms.


History

The following table shows the release history of Antenna:

Date Version Changes
XX-Jul-06 0.9.14 Okay, it's been a while. :-) But version 0.9.14 is finally out, mostly thanks to the help of Fred Grott. News are WTK support up to version 2.5 as well as support for several other toolkits.
29-Aug-04 0.9.13 Added support for WTK 2.2 beta (patch provided by Fred Grott). Added support for BlackBerry RAPC compiler (courtesy of Enrique Ortiz). IBM PalmOS PRC converter now uses jartoprc.exe instead of jad2prc.exe (fixed by Xiaodan Zhou). Added some new options to preprocessor (as requested by Steve Oldmeadow). Possibly some other fixes by people who are not mentioned here (sorry for that).

The next release will feature an improved version of the preprocessor (sorry for still not having it integrated, Andre).

26-Jun-04 - Number of downloads has passed the mark of 10000 last night.
25-Apr-04 0.9.12 A new release, finally. Don't know why it took so long to get this one out. Biggest news is WTK 2.1 and up-to-date WME compatibility. Fixed bugs in date formatting and file sorting of OTA servlet. Manifest can now go into the JAR in raw, unchanged form. Several fixes and optimizations in the preprocessor. Working directory is not set to $jdk/bin during preverification any longer. Obfuscators don't need to be in $jdk/bin or classpath any longer. Fixed a problem with JAD loading and empty lines. Classpath for preverifier is quoted if necessary. Credits for this version go to: Darryl L. Pierce, Kjell M. Myksvoll, Glenn Engel, Gabriela Chiribau, Tore Storødegård, Csaba Kertesz, Elliot Daniel Sumner, Guy Tomer, and Michael Van Meekeren.
02-Dec-03 - Antenna has been covered in a J2ME article by (German) JavaSpektrum magazine.
08-Oct-03 0.9.11 Preprocessor correctly handles #include when a "blind part" is encountered (#775880). WtkObfuscate allows to choose between ProGuard and RetroGuard, if both are present (#780182). WtkJad allows to specifiy encoding for JAD file (#781486). All three thanks to Janusz Gregorczyk. Working directory set to "<JAVA_HOME>/bin" when calling preverifier. Might resolve strange preverification errors some users encountered (thanks to Frédéric Dubuisson). Allowed to turn off -cldc parameter during preverification (#789131) and shortened task definition to one line (both courtesy of Jim O'Leary). Fixed small problem with target attribute of WtkJad (#798831, thanks to Thiago Leão Moreira). Fixed two problems with the OTA servlet and the WAP template (both thanks to Werner Baumann). All tasks that support classpaths should also support references to classpaths now (as noted by Gyula Kun-Szabo). Added support for Websphere PRC converter and piped preverifer output to Ant console (as suggested by Michael Kroll). Encoding for preprocessor file access can be specified (patch by Yuri Magrisso). CreateXXX signatures now feature proper class of return value instead of Object (thanks to Edwin van Ouwerkerk Moria). Order of debugging parameters for emulator[.exe] changed.

Sorry to those whose additions didn't make it into the new version, but after more than two months I wanted to have this version released. I'll consider your stuff for the next version - promised.

16-Jul-03 0.9.10 I've somewhat recovered from the "lost notebook" problem. The bad news is that I lost some (non-Antenna) code due to not doing backups regularly. The good news is that I now have a new and very cool ThinkPad. :) I tried to work through the collected mails this evening, incorporated fixes and produced a new version. We also have a project logo now, thanks to Steve Oldmeadow.

Preserve element in WtkPackage now honors if/unless attributes. ProGuard now called with "-dontusemixedcaseclassnames" by default to avoid Problems under Windows (both thanks to Elmar Sonnenschein). Provided proper support for Ant's ZipFileSet et. al to fix bug #739447 (also mapped libclasspath feature on it, thus saving some code). Fixed stupid exception in preprocessor when including files. Allowed #include directive to interpret Ant-style properties (both thanks to Steve Oldmeadow, too).

15-Jun-03 - Unfortunately, my Notebook has been stolen from my Office this week. :-( In addition to a number of uncommitted Antenna fixes I lost the e-mail of a whole month. Could all the people who mailed me regarding Antenna between 10-May-03 and 10-Jun-03 please send me these mails again (possibly including responses received from me)?
27-Jun-03 - I have set up a mailing list for Antenna. The list address is "antenna at pleumann.de". Subscriptions are managed via "antenna-request at pleumann.de". Send a mail with subject "subscribe" to become a member. Due to ever-increasing spam problems and my unwillingness to delete dozens of garbage messages per day, posting requires list membership. External postings will be rejected automatically and without moderation. I will also provide a HTML list archive once I find the time.
18-Apr-03 0.9.9 Added support for "if" and "unless" parameters in all tasks and all nested elements (as suggested by Elmar Sonnenschein). Build script now compiles against current Ant version. JAD task has new parameter for specifying URL for later deployment. Various fixes and extensions to the pre- and postprocessing tasks (credits for all go to Jay Goldman). Replaced modifed MANIFEST.MF created by RetroGuard with original one to get rid of signing information (suggested by Kadocsa Tassonyi). Added deployment task and OTA servlet.

BTW: Is anyone who's better at The GIMP than me willing to provide a logo for the project? Something like an ant with mobile phone or a satellite dish on its head...? :-)

31-Mar-03 0.9.8 Fixed typo in WtkRun which hindered remote debugging (thanks to Tyler Pitchford). Changed JAD/MANIFEST handling so that the properties copied from a JAD to a MANIFEST.MF are restricted to those explicitly allowed by the MIDP 2.0 specification (patch courtesy of Richard Kunze). Introduced new Ant properties to specify default BOOTCLASSPATH for all tasks. Fixed bug in WtkJad task where MANIFEST.MF was written to same file as JAD. Added possibilities to control extension and indentation of preprocessed files (suggested by Yuri Magrisso). Dropped "defaultpackage" option in favor of a generic way to pass proprietary arguments to obfuscators (suggestion by Janusz Gregorczyk).

I also changed the CLASSPATH the preverifier is called with to cope with problems reported by several people. From now on, the emptied-out API is used only for RetroGuard. If there are still problems with preverification (or new ones, which I don't hope), please tell me!

09-Mar-03 0.9.7 Put quotes around file names passed to external Java and native tools to deal with spaces in paths (thanks to Robert Virkus, Janusz Gregorczyk, and again to Andras Salamon). Fixed naming problem in methods dealing with classpath references. Fixed problem with preverify task not deleting temporary directory. Obfuscator doesn't need to be in "${wtk.home}/bin" any longer - it can also be in CLASSPATH (suggested by Janusz Gregorczyk). Added remote debugging support to emulator task (suggested by Walter Chang), as well as trace options. Made preprocessor resistent to trailing whitespace or tabs.
12-Feb-03 0.9.6 Preverifier is now called with "-cldc" switch. Fixed a bug with copying temporary files that resulted in non-verified JARs (thanks to Doug Johnson and the students from CSE 403). Tasks now check if "wtk.home" points to proper WTK directory. Added "defaultpackage" option for ProGuard preverifier (as suggested by Andras Salamon). Post processing tasks now support "classpathref" and "bootclasspathref" attributes (via patch provided by Mat Trudel) and are able to update a JAD file automatically. Fixed several other bugs reported by users.
29-Dec-02 0.9.5 Removed some differences between documentation and implementation (aka bugs) of WtkPreprocess.
28-Dec-02 0.9.4 Added preprocessing task. Fixed a NPE problem in the SmartLink task (thanks to Chris Hyzer). Added support for showing stdout/stderr of emulated MIDlets (as suggested by Doug Johnson).
21-Dec-02 0.9.3 Added support for ProGuard obfuscator/optimizer. Used platform path separator where appropriate (thanks again to Andras). Improved error detection for external programs. Unified interface for smart linking and obfuscating.
15-Dec-02 0.9.2 Added task for smartlinking/optimizing a JAR file. And, yes, the supposed "source" ZIP file contained the classes only. :-) Thanks go to Andras Salamon for pointing this out.
07-Dec-02 0.9.1 Added tasks for JAD/MANIFEST handling and for calling the emulator. Renamed several elements, most notably WtkCompile to WtkBuild. Fixed lots of bugs and hopefully introduced not as many new ones. :-)
01-Dec-02 0.9.0 Initial public release.


Plan

The following things are considered for addition into Antenna in the future, though I can't make any promises regarding the if and when: If you want to contribute any of this (or other useful stuff) to Antenna, your patches are more than welcome.


News | Overview | Download | Setup | JAD | Build | Package | MakePRC | RAPC
Run | Preverify | Obfuscate | SmartLink | Preprocess | Deploy | History | Plan

SourceForge.net Logo