Creating and distributing packages

This wiki page is intended to become part of GNU Smalltalk. Please do not make major changes to it unless you have a proper future changes copyright assignment on file with the FSF, or you intend to file a copyright assignment or disclaimer for your changes with the FSF.

First, here is a simple case of packaging GNU Smalltalk code, and then after that, how to package code with C.

1. Creating a Package for GNU Smalltalk code

Suppose your package is contained in a single TestPack.st file:

  Object subclass: TestPack [
     TestPack class >> greet: aString [
        ('hello %1!' % {aString}) printNl
     ]
  ]

package.xml should look like this:

  <package>
     <name>TestPack</name>
     <file>TestPack.st</file>
     <filein>TestPack.st</filein>
  </package>

You can make a TestPack.star file and install it to the system-wide
package directory (usually /usr/share/smalltalk) using simply

  gst-package package.xml

but you usually need root access for that. You can also install it just
for you:

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

(-t is short for --target-directory) and use it normally:

  $ gst
  GNU Smalltalk ready
  st> PackageLoader fileInPackage: 'TestPack'
  Loading package TestPack
  PackageLoader
  st> TestPack greet: 'world'
  'hello world!'
  TestPack
  st>

If you want to distribute the .star file, just create it in the current
directory:

  gst-package -t. package.xml

Then, you or other people will be able to do any of

  gst-package TestPack.star
  gst-package -t ~/.st TestPack.star

to install it (either globally or locally).

2. Creating a package with external C code

Let's assume you want to write a C binding for GNU Smalltalk that requires a custom C module; that is, using dynamic linking to a shared library is not enough. Even the smallest package of this kind will have a smalltalk code file with C call-outs defined, and a file with C source code.

Prepare the source code

For this example we will have two files: testpack.c:

#include <stdio.h>
#include "gstpub.h"

static VMProxy *vmProxy;

void
gst_testpack_print (OOP self, const char *string)
{
   printf ("TESTPACK PRINT: [%s]\n", string);
}

void
gst_initModule (VMProxy * proxy)
{
  vmProxy = proxy;
  vmProxy->defineCFunc ("gst_testpack_print", gst_testpack_print);
}

And the smalltalk side of this binding TestPack.st:

Object subclass: TestPack [
   print: aString [
      <cCall: 'gst_testpack_print' returning: #void args: #(#self #string)>
   ]
]

After putting those files into an otherwise empty directory...

~/testpackage# ls
TestPack.st  testpack.c

... you should create package.xml which is used by gst-package and the install scripts to determine the name of your package and the files that are going to be included in the package installation. (For a more detailed explanation of the package.xml format have a look at the GNU Smalltalk manual):

package.xml should look like this:

<package>
   <name>TestPack</name>
   <file>TestPack.st</file>
   <filein>TestPack.st</filein>
   <module>testpack</module>
</package>

Creating the build environment

Now your directory should look like this:

~/testpackage# ls -l
TestPack.st
package.xml
testpack.c

What you want now are makefiles which compile and install
testpack.c as library for GNU Smalltalk and also install
TestPack.st.

To create an skeleton automake/autoconf environment run gst-package
like this:

~/testpackage# gst-package --prepare package.xml 
creating configure.ac
creating gst.in
creating Makefile.am

Now you've got the basic automake/autoconf skeleton ready for a GNU Smalltalk
module. What you need now is to tell automake/autoconf to build testpack.c
as library.
We are going to use libtool to build the library. So insert AC_PROG_LIBTOOL into configure.ac:

configure.ac should then look similar to this:

AC_PREREQ(2.59)
AC_INIT([GNU Smalltalk package TestPack], [0.0], , gst-testpack)
AC_CONFIG_SRCDIR([package.xml])

AM_INIT_AUTOMAKE

AC_PROG_LIBTOOL

AM_PATH_GST([2.95c], , [AC_MSG_ERROR([GNU Smalltalk not found])])
GST_PACKAGE_ENABLE([TestPack], [.])

AC_CONFIG_FILES([Makefile])
AC_CONFIG_FILES([gst], [chmod +x gst])
AC_OUTPUT

It doesn't matter if your configure.ac looks a bit different, different
versions of gst-package may produce different output. Just make sure
to insert the AC_PROG_LIBTOOL line there.

Next you have to insert lines into Makefile.am to tell the build scripts
which C code file to use and what library to build. On the top of the Makefile.am you will maybe find some commented out example lines.
I propose to insert these lines into Makefile.am:

gst_module_ldflags = -rpath $(gstlibdir) -module -no-undefined -export-symbols-regex gst_initModule

gstlib_LTLIBRARIES = testpack.la
testpack_la_SOURCES = testpack.c
testpack_la_LDFLAGS = $(gst_module_ldflags)

So that Makefile.am looks like this:

AUTOMAKE_OPTIONS = foreign
AM_CPPFLAGS = $(GST_CFLAGS)

gst_module_ldflags = -rpath $(gstlibdir) -module -no-undefined -export-symbols-regex gst_initModule

gstlib_LTLIBRARIES = testpack.la
testpack_la_SOURCES = testpack.c
testpack_la_LDFLAGS = $(gst_module_ldflags)

### -------------------------------------- ###
### Rules completed by GST_PACKAGE_ENABLE. ###
### -------------------------------------- ###

DISTCLEANFILES = pkgrules.tmp
all-local:
clean-local::
install-data-hook::
dist-hook::
uninstall-local::

@PACKAGE_RULES@

Creating the configure script

Next we have to call the GNU autotools to prepare the configure script for you which will then produce the Makefile:

Call autoreconf like this:

~/testpackage# autoreconf -fvi
configure.ac: installing `./install-sh'
configure.ac: installing `./missing'
Makefile.am: installing `./depcomp'

Note: If you got errors that aclocal for example couldn't find AM_PATH_GST please make sure that you installed GNU Smalltalk correctly and that aclocal can find the .m4 files that come with GNU Smalltalk. For example if you installed GNU Smalltalk to /opt/gst/ you maybe want to add /opt/gst/share/aclocal/ to /usr/share/aclocal/dirlist.

Later on, the makefile will make sure that the configure script and Makefiles are updated as necessary. You can also do this manually with aclocal, autoconf, automake.

Now you should have a configure script. Now run configure and make. Watch out for errors and solve them if you got some. Among other things, make will generate two important files: TestPack.star and testpack.so, holding respectively the Smalltalk and the C code for the module.

make install will complete the build.

Testing

Now the package TestPack should be installed and you should test it:

~/testpackage# gst
GNU Smalltalk ready

st> PackageLoader fileInPackage: 'TestPack'
"Global garbage collection... done"
Loading package TestPack
PackageLoader
st> (TestPack new) print: 'TEST'
TESTPACK PRINT: [TEST]
a TestPack
st> 

Needless to say, it is also possible and encouraged to use SUnit to build your testsuite.

Even before installation, you can use the gst script that is in the build directory, so that GNU Smalltalk looks for your module there. TODO: how to invoke gst-sunit before installation

Syndicate content

User login