Revision of Hacker's guide from Sat, 01/05/2008 - 15:54

This page collects hints on how to work with the GNU Smalltalk system.

Debugging the Kernel, and building patches for it

I think I found a bug in the kernel. How do I try to fix it?

Assuming you don't have write access to /usr/share/smalltalk/kernel, or don't want to modify those files before having a definitive fix, the answer is to temporarily extend the class of concern.

A slight variation on the procedure described below is to work in the source tree itself - see the section "Developing within the main source tree" below.

Let's take as an example a problem found in CType.st of gst-2.95h, in the issue tracker as issue 148.

Step 0: Develop a test case

This is the most important step. Without a terse test case, it can be very difficult to isolate the fault.

For the chosen example, the following code, placed into testcase.st serves as our test case:

CStruct subclass: #StructB.
(CStruct subclass: #StructC) declaration: #((#b (#ptr #{StructB}))).
StructC new b elementType cObjectType printNl

The test case is run with the command

$ gst testcase.st
Object: Array new: 1 "<0x40318b40>" error: did not understand #binding
MessageNotUnderstood(Exception)>>signal
Array(Object)>>doesNotUnderstand: #binding
CType class>>cObjectType:
StructC>>b
UndefinedObject>>executeStatements

The expected output (as we imagine it, at this point) is simply

$ gst testcase.st 
StructB

Step 1: Develop your fix

After some experimentation, CType>>#storeOn: was found to be at fault. In order to experiment with a fix, it's convenient to use class extension to avoid having to touch the installed kernel files or the default image. Place the replacement method in a separate file, proposed-fix.st:

CType extend [
    storeOn: aStream [
        "Store Smalltalk code that compiles to the receiver"

        
        aStream
            nextPut: $(;
            print: self class;
            nextPutAll: ' cObjectType: ';
            print: self cObjectType;
            nextPut: $)
    ]
].

Note how the extension overrides the existing CType>>#storeOn: method. Test your fix by loading it before your testcase script:

$ gst proposed-fix.st testcase.st
StructB

Success! Now we have a working set of overrides, it's time to format them as a unified diff patch for submission in the issue tracker.

Step 2: Convert your fix into a patch

You will need two separate checkouts of the source code for the system: one untouched version, that you will use as a baseline for running diff against, and one version you will apply your changes to.

$ tar -zxvf smalltalk-2.95h.tar.gz
$ mv smalltalk-2.95h smalltalk-2.95h-orig
$ cp -R smalltalk-2.95h-orig smalltalk-2.95h-modified

Our example proposed fix replaces a method in class CType, which resides in kernel/CType.st. Edit that file in the smalltalk-2.95h-modified directory.

Once you've updated the sources, it's time to make the patch:

$ diff -ru smalltalk-2.95h-orig smalltalk-2.95h-modified > proposed-fix.patch

The proposed-fix.patch now contains a unified diff record of the changes you've made. Review the file, checking that it makes sense, includes all the changes you want, and doesn't include any unintended changes.

Step 3: Test your patch

To test your patch, make sure it applies cleanly to the distribution:

$ tar -zxvf smalltalk-2.95h.tar.gz
$ cd smalltalk-2.95h
$ patch -p1 < ../proposed-fix.patch
patching file kernel/CType.st

Now try compiling and installing the resulting source tree.

Step 4: Submit your patch

You can submit your finished patch either using the issue tracker, or by mailing the mailing list.

Make sure you include a description of the purpose of your patch, including a description of the fault and the rationale for your fix.

Aside: building images including a workaround or fix

How do I apply it to future images I generate (using ~/.st/pre.st or the ~/.st/kernel directory)?

Developing within the main source tree

How do I work within the tarball's build tree? How do I test it?

If you're making extensive changes to the system, it can be convenient to work directly on the system's source code tarball rather than using class extension as described above. One way of going about this is to configure it to install into a subdirectory of your working directory:

$ tar -zxvf smalltalk-2.95h.tar.gz
$ cd smalltalk-2.95h
$ ./configure --prefix=`pwd`/dist
$ make
$ make install

After this initial time-consuming configuration, compilation and installation, a local copy of gst is available in ./dist/bin/gst. You can now edit files in the source tree (not the ./dist directory!), and test your changes by running

$ make install
$ ./dist/bin/gst testcase.st

Each time you edit a file, you will need to rerun make install to publish your change to your experimental local installation.

How do I do the above without the install step?

You can run gst in the source or build tree without installing. Many changes can be made without running a full make. In particular, you can file in changed Smalltalk files if you are in the right namespace. Here is a short guide to changing files in different places:


kernel/*.st

Just file it in, making sure you are in the Smalltalk namespace. To incorporate the changes in an image, run make gst.im; alternatively,a script such as this will run GNU Smalltalk while loading modified kernel files automatically:

#! /bin/sh

# path to the build tree.
image=$HOME/src/smalltalk/
# path to the kernel/ directory under the source tree.
kernel=$HOME/ide/smalltalk/kernel/
ulimit -d 175000
ulimit -m 175000
ulimit -v 400000
exec $image/gst -I $image/gst.im --maybe-rebuild-image \
    --kernel-dir=$kernel -g "$@"

The ulimit -v needs may be different on your system. Mine is about 60M over what gst uses after my first file load. I use the ulimits to stop runaway allocation; you can leave them out if you don't want that or you don't know what memory limits you can live with.

packages/**/*.st

Switch to the right namespace (mentioned in a nearby package.xml) and file it in. It won't be incorporated automatically when you restart gst; you must run make (for example make NCurses.star to regenerate the .star file containing it.

libgst/*

These are C files, and changes can't be activated unless you rerun make and restart.

How do I debug changes to the C code for the distributed packages?

Some packages are split in two halves, one written in C and one written in Smalltalk. If the bug is in the C code, the only option is to develop in the source tree. To activate changes in the C code, just remake the .star file as indicated above.

An additional care is to run the tests/gst in the build tree, instead of ./gst. This will make sure that the modules' C code is loaded from the build tree rather than from a preexisting installation.

Creating new packages

How do I create new packages for GNU Smalltalk?

Creating a package that does not include C code is easy. You can create a package.xml (the contents are described in the manual), and from there create a .star archive in the current directory with this command:

gst-package --target-directory=. package.xml

Omitting the --target-directory option will install the .star file under /usr/share/smalltalk. The option can be shortened to -t.

Alternatively, you can install the package so that it is used by a single user like this:

gst-package -t ~/.st package.xml

Developing a package that also includes C code requires a little more setup; gst-package can be used to create a GNU-style source tree. For more information, see Creating and distributing packages.

Syndicate content

User login