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
Smalltalknamespace. To incorporate the changes in an image, runmake 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.
make (for example make NCurses.star to regenerate the .star file containing it.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.
