Chapter 1. Building from Source Code
Prev | Part I. The Basics | Next

## Chapter 1. Building from Source Code

A few words of advice, before getting started:

- If you're planning to use FXRuby on Windows, with the Pragmatic Programmers' Ruby installer for Windows, you may wish to just download the pre-compiled binaries from the SourceForge project page for FXRuby.

- If you're planning to use FXRuby on Linux, pre-compiled binaries may also be available for your Linux distribution. I can probably provide RPMs for Red Hat Linux 8.0 (since that's what I use), but others on the ruby-talk list may be able to provide binaries for other distributions.

- If you're planning to use FXRuby on Mac OS X, you may want to consult this page from the FOX Community Wiki, in addition to the standard build instructions listed below.

## Building With raainstall on Unix/Linux

raainstall is a command-line utility developed by Tom Clarke that can help with downloading, building and installing Ruby extensions listed in the Ruby Application Archive. You can use raainstall to download, build and install FXRuby, assuming both of the following conditions are met:

- You've already downloaded, compiled and installed FOX (and FXScintilla, if you want FXScintilla support compiled into FXRuby). FXRuby depends on these packages being installed in order for it to compile properly.

- FOX (and FXScintilla, if FXScintilla support is desired) are installed under either `/usr` or `/usr/local`. These are the only two standard installation directories that FXRuby's installation script will "guess".

Assuming that both of these conditions are met, you should be able to download, build and install FXRuby by typing:

    $ raainstall --install fxruby

Note that you will probably need superuser (root) permissions to do this.

It will take quite awhile to build FXRuby, even on a fast machine, so this might be a good time to take a coffee break. If you run into problems during the compilation, please check the list of things that can go wrong for workarounds for those problems.

As a quick sanity check, to make sure that all is well, you should probably fire up `irb` and try to import FXRuby:

    $ irb
    irb(main):001:0> require 'fox'
    true
    irb(main):002:0>

If the import failed (usually with a message along the lines of "Cannot load library"), check the list of things that can go wrong for known problems. If that still doesn't solve your problem, drop me an e-mail or ask around on the Ruby newsgroup or mailing list; it's quite likely that someone else has run into this problem too. Once you do have a working FXRuby installation, you're ready to check out the example programs.

## Building From Source on Unix/Linux

These instructions assume that you've already downloaded, compiled and installed FOX. Next, you'll need to download the FXRuby source code tarball and unpack it by typing:

    $ tar xzf FXRuby-1.0.21.tar.gz

This will create a new directory called `FXRuby-1.0.21`. Change to the top-level directory and configure the build by typing:

    $ ruby install.rb config

By default, the `install.rb` script will look for the FOX include files and library in the standard `/usr/local/include/fox` and `/usr/local/lib` directories, respectively. You can override these locations by passing a few additional arguments to `install.rb` during this step, e.g.

    $ ruby install.rb config -- \
        --with-fox-include=/home/lyle/fox-1.0.34/include \
        --with-fox-lib=/home/lyle/fox-1.0.34/src/.libs

Once the build has been configured, you can start the build by typing:

    $ ruby install.rb setup

It will take quite awhile to build FXRuby, even on a fast machine, so this might be a good time to take a coffee break. If you run into problems during the compilation, please check the list of things that can go wrong for workarounds for those problems.

Once it's finished compiling, install FXRuby by typing:

    $ ruby install.rb install

As a quick sanity check, to make sure that all is well, you should probably fire up `irb` and try to import FXRuby:

    $ irb
    irb(main):001:0> require 'fox'
    true
    irb(main):002:0>

If the import failed (usually with a message along the lines of "Cannot load library"), check the list of things that can go wrong for known problems. If that still doesn't solve your problem, drop me an e-mail or ask around on the Ruby newsgroup or mailing list; it's quite likely that someone else has run into this problem too. Once you do have a working FXRuby installation, you're ready to check out the example programs.

## Building From Source on Windows (Using Visual C++)

This section describes how to compile FXRuby using Microsoft Visual C++, for use with a Ruby that was also compiled using Visual C++.

This discussion assumes that you've built Ruby using the instructions and build files distributed with the standard Ruby source code. To review, you should have started by unpacking the source code tarball, changing into the top-level source code directory (e.g. `C:\ruby-1.6.8`) and then typing:

    C:\ruby-1.6.8>win32\configure
    type 'nmake' to make ruby for mswin32.
    C:\ruby-1.6.8>nmake

After the compilation finished, you installed Ruby somewhere by typing, e.g.,

    C:\ruby-1.6.8>nmake DESTDIR=C:\ruby install

Similarly, I'm assuming that you built the FOX library using the Developer Studio project files distributed with the standard FOX source code distribution. Although it's possible to build FXRuby against either the static library build of FOX (`fox.lib`) or the DLL build (`foxdll.dll`), these instructions currently cover only the static library build. Before you get started building FXRuby itself, you'll need to rename the static FOX library from its default filename (`fox.lib`) to `foxst.lib`. The reason for this rename is a charming little quirk in Microsoft's LINK utility and the fact that the eventual output name for the FXRuby DLL is also `fox.so`; for now, just take my word for it. So if your FOX source code distribution and build are found in the `C:\fox-1.0.34` directory, you'd need to rename the file:

    C:\fox-1.0.34\lib>rename fox.lib foxst.lib

Now you can configure the FXRuby build by typing:

    C:\FXRuby-1.0.21>ruby install.rb config --make-prog=nmake -- \
        --with-fox-include=C:\fox-1.0.21\include \
        --with-fox-lib=C:\fox-1.0.21\lib

Once the build has been configured, you can start the build by typing:

    C:\FXRuby-1.0.21> ruby install.rb setup

It will take quite awhile to build FXRuby, even on a fast machine, so this might be a good time to take a coffee break. Because Visual C++ is such a strict compiler (usually a good thing), you will probably run into a few problems with non-ANSI declarations in the Ruby header files. If you do run into problems during the compilation, just check the next section for a list of things that could go wrong, and workarounds for those problems. None of them are showstoppers and none require you to restart the compile from scratch (just type ruby install.rb setup to pick up where you left off).

Once it's finished compiling, install FXRuby by typing:

    C:\FXRuby-1.0.21> ruby install.rb install

As a quick sanity check, to make sure that all is well, you should probably fire up `irb` and try to import FXRuby:

    C:\FXRuby-1.0.21> irb
    irb(main):001:0> require 'fox'
    true
    irb(main):002:0>

If the import failed (usually with a message along the lines of "Cannot load library"), check the list of things that can go wrong for known problems. If that still doesn't solve your problem, drop me an e-mail or ask around on the Ruby newsgroup or mailing list; it's quite likely that someone else has run into this problem too. Once you do have a working FXRuby installation, you're ready to check out the example programs.

## Things That Can Go Wrong

"Too many arguments to function..."

The include files for Ruby versions 1.6.7 and earlier still have several function prototypes in the older "K & R" C style, where the function's argument list is not included; for example, the function `rb_thread_wait_for()` takes a single argument of type struct timeval, but its prototype in `intern.h` is:

    void rb_thread_wait_for();

Because FXRuby is written in C++, and C++ requires strict ANSI C-style function prototypes, code that attempts to call one of these functions will fail to compile under some compilers. For example, the error message from gcc will look something like this:

    FXRbApp.cpp: In method `long int FXRbApp::onChoreThreads (FXObject *, unsigned int, void *)':
    /usr/local/lib/ruby/1.6/i686-linux/intern.h:172: too many arguments to function `void rb_thread_wait_for ()'
    FXRbApp.cpp:100: at this point in file
    make: *** [FXRbApp.o] Error 1

while the error message from Microsoft's Visual C++ compiler looks something like this:

    FXRbApp.cpp(109): error C2660: 'rb_thread_wait_for' : function does not take 1 parameters
    NMAKE : fatal error U1077: 'cl' : return code '0x2'
    Stop.

This problem with the Ruby header files has been corrected for Ruby versions 1.6.8 (and later), but if you're building for an older version of Ruby you can do one of two things to work around the problem:

- If you're using gcc version 2.95 or earlier, try modifying the compiler flags (`CFLAGS`) in the FXRuby `Makefile` to include the `-fno-strict-prototype` option; this should instruct the compiler to allow these kinds of discrepancies. Unfortunately, this flag is not supported in more recent versions of gcc.

- A more direct approach is to just fix the offending declarations in the Ruby include file(s), i.e. change the declaration for `rb_thread_wait_for()` in `intern.h` to read:

      void rb_thread_wait_for(struct timeval);

  and change the declaration for `rb_gc_mark()` in `intern.h` to read:

      void rb_gc_mark(VALUE);

"Virtual Memory Exhausted"

For FXRuby releases earlier than version 0.99.173 it was common for the compiler to run out of memory trying to compile `core_wrap.cpp`, with an error message like:

    core_wrap.cpp: In function 'void Init_core()':
    core_wrap.cpp:108596: virtual memory exhausted

This failure was due to the use of optimizations by the compiler; the FXRuby source code makes heavy use of C++ templates and some versions of gcc require a lot of memory to process these. Starting with FXRuby version 0.99.173, the `extconf.rb` script should disable compiler optimizations when it generates the FXRuby `Makefile`. If you suspect that it's not disabling optimizations (or can see this by watching the compile command lines), try modifying the compiler flags (`CFLAGS`) in the `Makefile` by hand to do so.

"Cannot load library"

On Linux and other Unix systems that support shared libraries, FOX is typically installed as a shared library named `libFOX.so`. After all of the source files for FXRuby are compiled, the last step is to link all of the FXRuby object files together with the FOX library (and possibly other system libraries) to produce a new shared library, named `fox.so`, that Ruby can import as an extension module.

There are a few things that can go wrong when you try to import this extension into Ruby. A common problem is that the operating system cannot locate the FOX shared library (`libFOX.so`) when it tries to dynamically load the FXRuby extension module; when this happens, the error message will look something like:

    $ irb
    irb(main):001:0> require 'fox'
    LoadError: libFOX-0.99.so.173: cannot open shared object file: No such file or directory - /usr/local/lib/ruby/1.6/i586-linux/fox.so
            from (irb):1:in 'require'
            from (irb):1

One workaround for this problem is to modify the `LD_LIBRARY_PATH` environment variable to include the directory where `libFOX.so` is installed. For example, if `libFOX.so` is installed in `/usr/local/lib`, try setting:

    $ export LD_LIBRARY_PATH=/usr/local/lib
    $ irb
    irb(main):001:0> require 'fox'

If this works, you can of course permanently add the `LD_LIBRARY_PATH` setting to your login file(s) so that you don't have to remember to type it each time. Another approach that should work for Linux is to modify your `/etc/ld.so.conf` file to include the installation directory (e.g. `/usr/local/lib`). If you'd like to do this instead, you'll need to (as root):

1. Edit your `/etc/ld.so.conf` file and add the directory where `libFOX.so` is installed; and,

2. At the shell prompt, type ldconfig to reload the linker configuration.

"Undefined symbol..."

Another problem that has been reported by users of both Debian GNU/Linux and NetBSD 1.5 is an error message along the lines of:

    /usr/lib/libstdc++.so.2: Undefined symbol "__vt_9exception"...

The fix for this problem is reported to be to modify the FXRuby `Makefile` and add `-lgcc` to the `LIBS` line.

Prev | Up | Next
History and Goals | Home | Chapter 2. Hello, World!