Thursday, July 03, 2008

building j2me project with preprocessor blocks in eclipse

Do i sound bit thrilled , hell i am. I was trying to build my j2me code in eclipse with preprocessor support for last one week and , cant really tell you that i dint left a single stone upturned but still was not able to solve this mystery.
But now the big day is here and i have solved this mystery of the millienium( god i like this stuff).

Anyways am trying to get serious here and will be letting you all people know how i did it.

The thing which i was trying to do was , i had a simple code which you can say i had a helloworld program in j2me build perfectly fine in eclipse using the eclipseme plugin, which itself was using wtk kit which i had got already installed on my machine.

Now what i wanted to do was add some preprocessor tags to it and make conditional several builds for different different condition sets in a single build process.

For all those who are new to preprocessing , you can understand it well if you have done a bit of C programming.

What a preprocessor does is that it analysis your code before building , and in return genrates a code according to the conditions defined in it. lets take a example.

This is my hellowrld.java file .
public class hello extends MIDlet {


protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub

}

protected void pauseApp() {
// TODO Auto-generated method stub

}

protected void startApp() throws MIDletStateChangeException {
// TODO Auto-generated method stub


System.out.println("BT is supported");
System.out.println("GP is supported");
System.out.println("WMA is supported");
System.out.println("S60 is supported");


}

}

As you can see its a very simple midlet which does nothing , just prints out four statements on your console.

Now what i wanted to make seperate build of this code according to the following conditions.

1. BT and GP supported (BT means bluetooth and GP means GPRS)
2. WMA and S60 supported.

I could have done that with conditional if else block and have the code copy and pasted in them but I also wanted to reduce the jar size. That is i wanted my jar to contain only those things which are required. For that we can use preprocessor tags which processes the code before building and comments out anything which does not matches its prescribed criterias. so i put some preprocessor tags in it, and now my code looks like this.

public class hello extends MIDlet {


protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub

}

protected void pauseApp() {
// TODO Auto-generated method stub

}

protected void startApp() throws MIDletStateChangeException {
// TODO Auto-generated method stub


//#ifdef BT

System.out.println("BT is supported");
//#else

System.out.println("BT is not supported");
//#endif
//#ifdef GP
System.out.println("GP is supported");

//#else
System.out.println("GP is not supported");
//#endif

//#ifdef WMA

System.out.println("WMA is supported");
//#else

System.out.println("WMA is not supported");
//#endif
//#ifdef S60
System.out.println("S60 is supported");

//#else
System.out.println("S60 is not supported");
//#endif

}

}

the
"//# if" is known as a preprocessor. it gets processed before the code is build and compiled.

//#ifdef BT

System.out.println("BT is supported");
//#else

System.out.println("BT is not supported");
//#endif


This block means that if the BT is defined then build the if block else comment out the if block and build the else block.

Now this BT can be defined in two ways.

We can put a "// # define BT" at the very beginning of the code like this :

//# DEFINE BT
public class hello extends MIDlet {
we can also assign some value to it and it will work. so lets first put it that way only. the code will look like this :

//#define BT
//#define GP
//#define WMA

public class hello extends MIDlet {


protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub

}

protected void pauseApp() {
// TODO Auto-generated method stub

}

protected void startApp() throws MIDletStateChangeException {
// TODO Auto-generated method stub


//#ifdef BT

System.out.println("BT is supported");
//#else

System.out.println("BT is not supported");
//#endif
//#ifdef GP
System.out.println("GP is supported");

//#else
System.out.println("GP is not supported");
//#endif

//#ifdef WMA

System.out.println("WMA is supported");
//#else

System.out.println("WMA is not supported");
//#endif
//#ifdef S60
System.out.println("S60 is supported");

//#else
System.out.println("S60 is not supported");
//#endif

}

}

and after u have build it if you go to your project folder , you can see the processed code in the ".processed folder". The processed code will look like this :

//#define BT
//#define GP
//#define WMA

public class hello extends MIDlet {


protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub

}

protected void pauseApp() {
// TODO Auto-generated method stub

}

protected void startApp() throws MIDletStateChangeException {
// TODO Auto-generated method stub


//#ifdef BT

System.out.println("BT is supported");
//#else
//@
//@ System.out.println("BT is not supported");
//#endif
//#ifdef GP
System.out.println("GP is supported");

//#else
//@ System.out.println("GP is not supported");
//#endif

//#ifdef WMA

System.out.println("WMA is supported");
//#else
//@
//@ System.out.println("WMA is not supported");
//#endif
//#ifdef S60
//@ System.out.println("S60 is supported");
//@
//#else
System.out.println("S60 is not supported");
//#endif

}

}

You can see that in this processed code everyting is commented out which is not needed or has not been defined. The @ symbol lines are never processed so they never goes into the final build and keeps the jar file light . thats the main crux of using preprocessors. If everything goes fine you will be seeing this output on your console :

Running with storage root DefaultGrayPhone
BT is supported
GP is supported
WMA is supported
S60 is not supported
Execution completed.
703621 bytecodes executed
8 thread switches
740 classes in the system (including system classes)
3601 dynamic objects allocated (100244 bytes)
2 garbage collections (86440 bytes collected)

So much for this preprocessors, so finally we have got it running but this happens to be very crude method and if we happen to be defining preprocessors on the go then we are doomed for it.

The better way to do it is using build.xml and antenna. I will be telling you about it in next post.

2 comments:

Anonymous said...

Thanks for writing this.

Anonymous said...

Amiable dispatch and this fill someone in on helped me alot in my college assignement. Say thank you you on your information.

follow me