Set up a Java ME development environment on Mac OS X

Recently I decided to give Java ME a try. As I have a project created by other developers with NetBeans Mobility Pack, I thought I might just use the same IDE on Mac.

(Click to enlarge)

Installing NetBeans

I downloaded NetBeans 6.1 from http://download.netbeans.org/netbeans/6.1/final/. There’s no ready-built mobility pack for Mac, so I downloaded the Java SE version (coz I won’t use other features anyway, for those I use Eclipse). The installation is easy, no configurations needed. Right after I launched the program, there’re already several updates, so I just let it updated itself.

Installing Mobility Plugins and Mpowerplayer

Go to “Tools / Plugins“, select “Available Plugins” tab, find those two plugins - “Visual Mobility Designer” and “Mobility“, install them (and update them). Restart NetBeans.

Mpowerplayer is currently the only working MIDP emulator on Mac. Download it for free at http://mpowerplayer.com/?cat=6 . Extract Mpowerplayer SDK to any place you like. e.g. /Developer/mpp-sdk .

Go to “Tools / Java Platforms“, click “Add Platform..“. In the wizard select “Java ME MIDP Platform Emulator” and in the next screen choose the folder you extracted MPP SDK to. I use /Developer/mpp-sdk here. The wizard should find the platform automatically, then “Next” and that finishes this part.

(Optional) Replacing files (solves “String.equalsIgnoreCase” problem)

Now you should be ready to develop MIDP applications with NetBeans and Mpowerplayer. However, if you try to use certain methods in your application, say “String.equalsIgnoreCase”, you’ll get a “cannot find symbol” error (even if you’re using CLDC 1.1 profile, which should include this method).

A simple workaround is “toLowerCase().equals()“. However if you’re working with exisiting code (like in my case, someone created with WTK), you’ll find more missing classes and methods which have no simple workarounds.

So I decided to compile my code against Sun’s libraries. Configuring classpaths can be tricky so I just replaced the files. Here’s what I did:

  1. Download Sun Java Wireless Toolkit 2.5.2 . Remember to download the Linux version !
  2. Extract the package with unzip in a terminal, simply “unzip <the file name>” (Don’t do it in Finder, it simply doesn’t work). e.g.
    sudo mkdir /Developer/sun_wtk
    cp ./sun_java_wireless_toolkit-2_5_2-linux.bin /Developer/sun_wtk/
    cd /Developer/sun_wtk
    unzip sun_java_wireless_toolkit-2_5_2-linux.bin
  3. Now check the files you just extracted, copy all those 5 jars under “lib” directory to <mppsdk>/stubs/ and replace the ones that come with Mpowerplayer (make backup first). e.g.
    cp lib/cldcapi10.jar /Developer/mpp-sdk/stubs/cldc-1.0.jar
    cp lib/cldcapi11.jar /Developer/mpp-sdk/stubs/cldc-1.1.jar
    cp lib/midpapi10.jar /Developer/mpp-sdk/stubs/midp-1.0.jar
    cp lib/midpapi20.jar /Developer/mpp-sdk/stubs/midp-2.0.jar
    cp lib/mmapi.jar /Developer/mpp-sdk/
  4. Now you should be able to use the same APIs as you would use with WTK. Do not delete the WTK directory, there’re still many useful libraries (e.g. WMA - the javax.wireless.messaging package) and demo applications.

Some Notes

  • When opening projects created with older versions of Mobility Pack, NetBeans will ask you to convert the file format (basically changes on getter/setter to meet Java conventions). Do NOT trust the conversion, keep a copy of the original files, you’ll have to fix small errors like missing imports here and there in the new file
  • The Visual Mobility Designer is really cool but don’t overuse it. As the diagrams aren’t generated from source code directly, but stored in separated files, NetBeans won’t allow you to edit much part of the generated code, and sometimes it just gets in the way. So still use handcraft code when possible (I only use the designer for UI and layout)
  • If you compile your application against WTK libraries, you’ll have to consider license issues when publishing it.
  • You should still test your applications on emulators from official SDKs and probably on actual devices. For example I wrote a very simple Hello world application and it runs well on Mpowerplayer, but simply doesn’t work on my Sony Ericsson K770i.

Compiling 64 bit PHP on Mac OS X Leopard

My iMac ships with Leopard 10.5.2 and PHP 5.2.5 was integrated. As I was planning to build optional components into PHP, I decided to compile PHP 5.2.6 myself.

I have MySQL installed on /usr/local/mysql and to preserve the orginal settings of the preinstalled version, I used following configure options:

./configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info \
--disable-dependency-tracking --with-apxs2=/usr/sbin/apxs --with-ldap=/usr \
--with-kerberos=/usr --enable-cli --with-zlib-dir=/usr --enable-trans-sid --with-xml \
--enable-exif --enable-ftp --enable-mbstring --enable-mbregex --enable-dbx --enable-sockets \
--with-iodbc=/usr --with-curl=/usr --with-config-file-path=/etc --sysconfdir=/private/etc \
--with-mysql-sock=/var/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config \
--with-mysql=/usr --with-openssl --with-xmlrpc --with-xsl=/usr --without-pear \
--with-mysql=/usr/local/mysql

Then after building, make and install, apache failed to start as libphp5.so was in a “wrong architecture”.

Then I realized, the Apache shipped with Leopard was the 64bit version, so I have to build a 64 bit PHP.

so I added the following before configure:

MACOSX_DEPLOYMENT_TARGET=10.5
CFLAGS="-arch x86_64 -g -Os -pipe -no-cpp-precomp"
CCFLAGS="-arch x86_64 -g -Os -pipe"
CXXFLAGS="-arch x86_64 -g -Os -pipe"
LDFLAGS="-arch x86_64 -bind_at_load"
 
export CFLAGS CXXFLAGS LDFLAGS CCFLAGS MACOSX_DEPLOYMENT_TARGET

The last line seems redundant but strangely on my machine, the flags won’t work until I export them.

In order to configure a 64bit build, I have to install a 64bit version of MySQL, or you’ll fail the configure.

All files compiled successfully, but the linkage failed. The error was “Undefined symbol: _libiconv”. Well that’s a new one, didn’t see that when building the x86 version.

After googling for a while, I found the solution. Apple’s libiconv.dylib has a bug, it forgot to export _libiconv for both 64bit architectures (ppc64 and x86_64). The solution is to compile a universal binary libiconv yourself. (And do not forgot to install the header files too, or you’ll get other undefined symbol errors)

The flags of building universal binary is similar as the above ones. Just remember to put all four architectures (-arch i386 -arch x86_64 -arch pc7400 -arch ppc64) there.

Then finally I have the php built successfully and up n running.

Notes

To build a universal binary version of PHP, you need to build MySQL universal yourself as well, and all the libraries you used should be compiled as universal binary.

A universal binary looks like this :

$ file /usr/sbin/httpd
/usr/sbin/httpd: Mach-O universal binary with 4 architectures
/usr/sbin/httpd (for architecture ppc7400):	Mach-O executable ppc
/usr/sbin/httpd (for architecture ppc64):	Mach-O 64-bit executable ppc64
/usr/sbin/httpd (for architecture i386):	Mach-O executable i386
/usr/sbin/httpd (for architecture x86_64):	Mach-O 64-bit executable x86_64

- Update:
After this post I’ve been using php with Leopard for a while. I found that sometimes (probably after an OS update, but I haven’t confirmed this yet) the system restores old versions of php, which would fail to load the custom-built libiconv. So you have to run “make install” & “make install-cli” again to make the new version working again. (No recompilation, only reinstall)