IBM Skip to main content
Search for:   within 
      Search help  
     IBM home  |  Products & services  |  Support & downloads   |  My account

developerWorks > Java technology | Linux | Open source projects
developerWorks
Create native, cross-platform GUI applications, revisited
Discusscode175 KBe-mail it!
Contents:
Setting up your development environment
Building the SWT
Building sample applications
Native builds in Eclipse
Looking forward
Resources
About the author
Rate this article
Related content:
Create native, cross-platform GUI applications
Weighing in on Java native compilation
Using the Eclipse GUI outside the Eclipse Workbench, Part 1
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)
An updated look at GCJ and the SWT

Level: Intermediate

Kirk Vogen (mailto:kcvogen@yahoo.com?cc=jaloi@us.ibm.com&subject=Create native, cross-platform GUI applications, revisited)
Senior I/T Specialist, IBM
13 May 2003

Just over a year ago, Java developer Kirk Vogen explored combining the GNU Compiler for Java, Linux, and the Standard Widget Toolkit (SWT) to create native, cross-platform Java applications. In this article, Kirk revisits the topic and covers support for Windows, GNOME, and SWT 2.0. This time he uses Ant to illustrate automated builds of your native applications, then shows you how to bring it all into the Eclipse IDE. Share your thoughts on this article with the author and other readers in the accompanying discussion forum. (You can also click Discuss at the top or bottom of the article to access the forum.)

Note: Kirk Vogen has changed jobs, but is still available to answer questions on this topic either in the accompanying discussion forum or at his personal email address: kcvogen@yahoo.com.

When we last discussed the GNU Compiler for Java (GCJ) and the Eclipse Standard Widget Toolkit (SWT), we had a solution for creating natively compiled Java applications with a look and feel of the native operating system. The solution used SWT 1.0 and GCJ under Linux. Since then, support for GNOME under Linux as well as Windows support has been added. This article takes an updated look at GCJ and SWT. We'll explore how to build SWT so that you can use it in your applications. We'll also work through several examples that illustrate how to use SWT in applications and the accompanying build process. Finally, we will explore how to use the build process within the Eclipse IDE. If you need background on what we've already covered, see Resources for a review of GCJ, SWT, and the rationale for it all.

Setting up your development environment
Before moving into the fun stuff, you'll need to set up your development environment. You'll need the following packages:

  • Ant 1.5.0 or higher. A Java-based build tool (see Resources for more information on Ant).

  • GCJ 3.2 or higher. You can obtain GCJ in several ways. Most of the current versions of Linux distributions come with GCJ. Both RedHat 8.0 and Mandrake 9.0 come with GCJ 3.2. For Windows, see the sidebar Installing GCJ 3.2 on Windows for installation instructions. If you are running a version of Linux/UNIX without GCJ, see Resources for instructions on compiling GCJ in your environment.

  • The patch utility. The build process uses the Ant <patch> task to run a few patches. As such, your system needs to have the patch utility installed. Most Linux systems come with a patch utility out of the box. Windows, however, does not. A Windows version of the patch utility has been included in this article's source code (see Resources). The file is contained in the Utilities\win32 directory. Place the patch.exe file in a directory that is in your system PATH.

  • Eclipse 2.0.2. This is only necessary if you want to run builds within the Eclipse IDE (as discussed later in Native builds in Eclipse).

Installing GCJ 3.2 on Windows
Follow these instructions to install GCJ 3.2 on your environment.

Make sure that your PATH environment variable can access all of the applications listed earlier. This will ensure that Ant buildfiles can run the utilities when needed.

Building the SWT
Now that you have a development environment set up, let's explore building SWT into a library. This process involves compiling the SWT source into native object code and packaging it together into a library. You can then use the library to link into your applications.

Before continuing further, download and extract the article's source code. The source code contains several items, including a build script for building SWT into a library, several sample applications, and the SWT source code from Eclipse 2.0.2.

There are a few things to keep in mind when building SWT: the target operating system, the target window system, and the type of library you would like to use. SWT is currently supported on the AIX, HP/UX, Linux, Solaris, and Windows operating systems. It is also supported on MacOS and QNX (though the scope of this article does not include those). In addition to the operating system, you need to determine your target window system, which will be important later on when we run the buildfile. If your operating system is Linux, your window system options are GNOME or Motif. If you are on another UNIX variant (such as AIX, HP/UX, or Solaris), your window system option is currently only Motif. If your operating system is Windows, your window system option is just that -- Windows. Currently there is not support for KDE due to apparent licensing issues with the Qt toolkit it uses. Applications compiled using another window system will run in KDE, but they will not use KDE's native widgets.

In addition to the operating system and window system, you need to decide which library type to build. You have two options: a static library or a shared library. With a static library, SWT is linked into your application at compile time. With a shared library, SWT is linked into your application at run time. As its name indicates, the shared object has the main advantage of being sharable. Applications can all use the same object dynamically at run time. As a result, executable sizes will be much smaller. Under Windows you can use only static libraries; GCJ does not support the loading of Java DLLs (DLLs being the Windows equivalents of shared libraries).

The buildfile
The buildfile is a bit too long to include here, but basically it:

  • Retrieves the SWT source code for the particular operating system and windowing system.

  • Applies a few patches to the SWT code. A few of the SWT files would not compile with GCJ due to small compiler errors -- for example, GCJ had trouble with some event listeners implemented with inner classes. In these cases, small patches were made to the source to fix the errors while keeping the code functionally equivalent. Because GCJ is still evolving, these bugs should eventually go away.

  • Compiles the code to native object code.

  • Packages the object code into either a static or shared library.

To run the buildfile, navigate to the Library directory of the source included with the article. You'll need to configure a few properties. First, to set the target operating system, use the os property. To configure the window system, use the window_system property. Finally, to control the library type, call either the static-library or shared-library targets. By default, the buildfile calls the static-library target and sets the operating system to Linux and the window system to GNOME. For a complete explanation of the configuration options, navigate to the Library directory at the command prompt and type ant help.

Let's examine several common examples for building SWT:

  • To create a static library for GNOME under Linux, simply type ant. By default, the buildfile calls the static-library target, so nothing additional is needed at the command prompt.

  • To create a shared library for GNOME under Linux, type ant shared-library.

  • To create a shared library for Motif under Linux, type ant -Dwindow_system=motif shared-library.

  • To create a static library for Windows, type ant -Dos=win32 -Dwindow_system=win32. Remember that shared libraries are currently not supported under Windows.

Listing 1 shows the output from a Linux/GNOME shared library build.

Listing 1. Output from a Linux/GNOME shared library build

[Library]$ant shared-library
Buildfile: build.xml

get-swt-source:

properties:

init:

ws/gtk/swtsrc.zip:
      [zip] Building zip: /home/jdoe/Java/SWT/Eclipse_2.0.2_SWT_
            Source/plugins/org.eclipse.swt.gtk/ws/gtk/swtsrc.zip
    [unzip] Expanding: /home/jdoe/Java/SWT/Eclipse_2.0.2_SWT_Source/
            plugins/org.eclipse.swt.gtk/ws/gtk/swtsrc.zip into
            /home/jdoe/Java/SWT/Library

get-pi-source:

properties:

init:

ws/gtk/swt-pisrc.zip:
    [unzip] Expanding: /home/jdoe/Java/SWT/Eclipse_2.0.2_SWT_Source/
            plugins/org.eclipse.swt.gtk/ws/gtk/swt-pisrc.zip into
            /home/jdoe/Java/SWT/Library

patch:
    [patch] patching file GtkSelectionData.java
    [patch] patching file GtkTargetEntry.java
    [patch] patching file TableCursor.java
     [copy] Copying 4 files to /home/jdoe/Java/SWT/Library/org/
            eclipse/swt/custom

compile:
    [javac] Compiling 4 source files
     [echo] Compiling SWT with GCJ

init:

shared-up-to-date:

shared-library:

BUILD SUCCESSFUL
Total time: 1 minute 18 seconds
[Library]$

If you have trouble building under Windows and you have Cygwin installed, see the sidebar Notes about Cygwin and GCJ.

Notes about Cygwin and GCJ
Newer versions of Cygwin come with GCJ. However, I've experienced some issues when following the build process discussed earlier with machines in which Cygwin is installed. If you have Cygwin installed, you can alleviate any possible issues by temporarily removing c:\cygwin\bin from your system PATH. With Cygwin in your PATH, you may see errors like this:


Public class `ACC'
must be defined in a file
called `ACC.java'

Building sample applications
Now that you have an SWT library, you are ready to start building applications that use it. The source zip file included with this article (see Resources) has several sample applications. Each sample application includes a generic buildfile that you can use as a starting point for your projects. The buildfile:

  • Compiles any resources that your project may have (bitmaps, GIFs, properties files)

  • Compiles your source files to native object code

  • Links in SWT either statically or through a shared library

  • Creates an executable

  • Provides the ability to package your application into a JAR file (if you want to deploy your application to a JVM for testing or other purposes, you can easily do it with the buildfile)

The buildfile has only one setting for you to configure: the type of library you will be using. By default the buildfile assumes that you are using a static library. If you want to use a shared library, simply set the link property equal to dynamic (for instance, ant -Dlink=dynamic). As with the other buildfile, type ant help for a further description of the configuration options.

Let's try out the buildfile with the ControlExample sample application. This application demonstrates the many SWT widgets. It is similar to the SwingSet application that is a popular demo application for Swing. To build the application, navigate to the directory where you extracted the source files included with this article, then navigate to the ControlExample directory. Type ant (again, note that for a shared library, you'd type ant -Dlink=dynamic). Assuming you have already created your SWT library (in the ../Library directory), the buildfile should run without error.

After the buildfile is finished, you can run the application -- well, almost. First, you'll need to provide access to some libraries needed for SWT. These libraries are mainly the SWT JNI libraries. This step is also necessary when you run an SWT application in a JVM. In the directory where you extracted the article source code, navigate to the Eclipse_2.0.2_SWT_Source directory, then follow the directions for your target operating system.

  • For Windows, copy the plugins\org.eclipse.swt.win32\os\win32\x86\swt-win32-2052.dll file to a directory in your PATH (for instance, c:\WINNT\system32). Alternatively, you can modify your path to point to this directory (for instance, PATH=C:\MyExtractDir\Eclipse_2.0.2_SWT_Source\plugins\org.eclipse.swt.win32\os\win32\x86\;%PATH%).

  • For Linux/GNOME, copy the files plugins/org.eclipse.swt.gtk/os/linux/x86/libswt-gtk-2052.so and plugins/org.eclipse.swt.gtk/os/linux/x86/libswt-pi-gtk-2052.so to a directory where your system libraries reside (for instance, /usr/lib). If you are using a shared library, you will also need to copy the shared library to your system path (for instance, ~/MyExtractDir/Library/lib-org-eclipse-swt.so). Alternatively, you can temporarily set the environment variable LD_LIBRARY_PATH to point to the directories where these files reside. For example, in the bash shell:
    
    export LD_LIBRARY_PATH=~/MyExtractDir/Library:
    ~/MyExtractDir/Eclipse_2.0.2_SWT_Source/plugins/
    org.eclipse.swt.gtk/os/linux/x86:$LD_LIBRARY_PATH
    


  • For Linux/Motif, copy plugins/org.eclipse.swt.motif/os/linux/x86/libswt-motif-2052.so to a directory where your system libraries reside (for instance, /usr/lib). Also copy libXm.so.2 to that same directory. If you are using a shared library, you will also need to copy the shared library to your system path as well (for instance, ~/MyExtractDir/Library/lib-org-eclipse-swt.so). Alternatively, you can temporarily set the LD_LIBRARY_PATH environment variable to point to the directories where these files reside. For example, in the bash shell:
    
    export LD_LIBRARY_PATH=~/MyExtractDir/Library:
    ~/MyExtractDir/Eclipse_2.0.2_SWT_Source:
    ~/MyExtractDir/Eclipse_2.0.2_SWT_Source/plugins/
    org.eclipse.swt.motif/os/linux/x86:$LD_LIBRARY_PATH
    


    Note that if you get an error message regarding fonts, try using the export LANG=en_US.iso88591 command.

After you have all your files set, try running the application. You should see something similar to Figure 1.

Figure 1. The ControlExample application
Figure 1. The ControlExample application

If you have trouble getting the application to run, there are a few items to examine. In Linux, if your application has trouble finding your shared library, you will get a message similar to this:


./AddressBook: error while loading shared libraries: lib-org-eclipse-swt.so:
cannot open shared object file: No such file or directory

If your application cannot find one of the JNI shared libraries, you will get a message similar to this:


Exception in thread "main"

In either case, verify that the necessary libraries have been copied to the system library directory (for instance, /usr/lib).

In Windows, if your application cannot find a JNI DLL, nothing will happen -- you won't get any output and the application will not be displayed. To force some debugging output, first delete the line <arg value="-mwindows"/> from the build.xml buildfile. Rerun the build by first typing ant clean (to start from scratch), then type ant.

Now when you run the application, it will display error output in the command prompt similar to the following:


Exception in thread "main" java.lang.UnsatisfiedLinkError:
swt-win32-2052: file not found

If you get this error message, verify that the swt-win32-2052.dll file is in a directory in your system PATH.

Before we move on, check out the other applications included with this article. Among others, there is a small text editor example and an example that illustrates hover help. To build those applications, follow the same process as the ControlExample application.

Native builds in Eclipse
Finally, let's take a look at using all this in the Eclipse IDE. Combining an IDE with the native compilation abilities of GCJ results in a convenient and powerful development environment. You can take advantage of handy Eclipse features such as code completion and a debugger, yet still be able to compile natively.

To set it up, first make sure that you have Eclipse 2.0.2 installed (other 2.x versions may also work). Next, start Eclipse. By default, Eclipse comes with Ant 1.4. Because the buildfile requires Ant 1.5, you'll need to upgrade it to Ant 1.5. This is actually a very simple process. Select Windows > Preferences, then navigate to External Tools. Expand External Tools and select Ant. You should see something like Figure 2.

Figure 2. Ant classpath before modification
Figure 2. Ant classpath before modification

Select the two ant JAR files (ant.jar and jakarta-ant-1.4.1-optional.jar) and click Remove. Next, click Add Jar. Navigate to the lib directory of your Ant installation directory. Select ant.jar and click Open. Again, click Add Jar, this time selecting optional.jar. When you are all done, you will have something like Figure 3.

Figure 3. Ant classpath with Ant 1.5 JARs
Figure 3. Ant classpath with Ant 1.5 JARs

Now you'll need to create a project for the sample application. Select File > New > Project. In the resulting dialog, select Java in the left pane and Java Project in the right pane. Click Next, give the project a name, then click Finish.

Once you've created the project, import one of the sample applications. In this case, let's use the TextEditor sample. Complete the following steps:

  1. At the command prompt, navigate to the directory where you extracted this article's source code. When there, navigate to the TextEditor application and type ant clean to clean up the .o and .class files. We don't really want to import these files into our Eclipse workspace.

  2. Click on your newly created project, then select File > Import.

  3. In the resulting dialog, select File System, then click Next.

  4. Click the Browse button, then navigate to the directory where you extracted this article's source code. When there, navigate to the TextEditor application, then click OK.

  5. Make sure you click the box in the left pane next to TextEditor. This will ensure that all source code, resources, and the buildfile are imported. Click Finish. Your screen should look similar to Figure 4.

Figure 4. Code import
Figure 4. Code import

Now that you are set up, we can try a native compilation. To do so, right-click on build.xml in Eclipse and select Run Ant. A dialog similar to Figure 5 should display.

Figure 5. Ant Run dialog
Figure 5. Ant Run dialog

In the Arguments field, we will need to supply values for three properties: the link type (only if you are doing a dynamic link), the location of the SWT JAR file (so that the compiler has a reference to the SWT classes), and the location of your SWT library (that you compiled earlier). For example:


-Dlink=dynamic -Dlibrary_dir=/home/jdoe/MyExtractDir/Library/
-Dswt.jar=/usr/local/eclipse/plugins/org.eclipse.swt.gtk_2.0.2/ws/gtk/swt.jar

In Linux, beware that you cannot use the tilde character in the Arguments field. For some reason, it generates errors. Use fully qualified path names (such as /home/jdoe/MyExtractDir... instead of ~/MyExtractDir... or ~jdoe/MyExtractDir...).

Once you have filled out the Arguments field, click Finish and let the build run. If you receive any errors, they are most likely the result of path issues. Double-check your settings in the Arguments field to ensure that they reference valid paths.

Looking forward
Although I did not test under AIX, HP/UX, or Solaris, the process described should still work. Also, if you have a Macintosh, an interesting project would be to install GCJ and Ant and run the build process. On MacOS, the source code is a little bit behind that of the other operating systems. As such, you may have to come up with some small patches if you get any compilation errors.

Another cool thing to try would be cross-compilation. If you get everything set up properly, you could have one computer that could create SWT applications for a variety of target operating systems. All you need is to set up a GCJ cross-compiler for your various target operating systems. Explore the GCJ/GCC Web site for information on cross-compilation (see Resources). Keep in mind that building a cross-compiler can be challenging, but should be possible with sufficient documentation and help from other users.

I would like to thank the GCJ developers. A lot of headway has been made in the past year with GCJ (especially with Windows). Without their talent and dedication, we wouldn't have such an interesting and unique product.

Resources

About the author
authorKirk Vogen is a Java enthusiast with a passion for programming. He specializes in building e-commerce applications using WebSphere within IBM Global Services. He can be reached at kcvogen@yahoo.com.


Discusscode175 KBe-mail it!

What do you think of this document?
Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Send us your comments or click Discuss to share your comments with others.



developerWorks > Java technology | Linux | Open source projects
developerWorks
  About IBM  |  Privacy  |  Terms of use  |  Contact