|
|
|
Contents: |
|
|
|
Related content: |
|
|
|
Subscriptions: |
|
|
| An updated look at GCJ and the SWT
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).
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
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
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
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:
- 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.
- Click on your newly created project, then select File >
Import.
- In the resulting dialog, select File System, then click
Next.
- 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.
- 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
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
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 Kirk 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. |
|
|