[prev] [up] [next]

How to Create & Add Binary Classes/Libraries

Notice:
Most of this document has become obsolete by the availability if the package-builder. This tools allows for a very convenient build-process for both standalone executables and binary class libraries.

Contents

Introduction

The most interesting feature distinguishing Smalltalk/X from other smalltalk implementations is the ability to create native object files and (possibly shared) libraries from smalltalk classes.

These class libraries may contain embedded C-code; either for performance reasons or to interface to other C-libraries.

This document will give you information and a step-by-step guide on how to compile your classes to machine code, how to create & package class libraries for distribution and how to include such a binary class library in your system.

Notice, that beside speed advantage and the ability to include inline C code, the semantic of binary compiled code is equivalent to that of interpreted bytecode. All language features (such as context handling, block handling, stack unwinding and exception handling) are available and perform transparent whether methods are compiled statically or interpreted (or compiled dynamically from bytecode by the JIT translator).

Compiled object files are bigger than bytecode files. Therefore, the memory requirements are bigger if machine compiled code is used - at least if a single Smalltalk/X application is running. However, on systems which support shared libraries, this code is shared amongst all those applications (which is not the case with interpreted bytecode), therefore, depending on how many such applications are executing, there may be a memory advantage - even with larger object files.
Also, it must be considered, that statically compiled machine code is located in the code segment of the program - i.e. it will only paged into the physical memory when needed and requires much less memory in the objectMemory area - therefore, even when requiring more memory, there is less memory required in many situations.

In addition, static compiled machine code is not loaded into the objectMemory, and therefore not to be considered by the garbage collector. Especially for big projects, this may reduce GC overhead considerably.

Another positive aspect of statically compiled machine code (in contrast to just-in-time compilation) is the guaranteed maximum response time, in which an invoked method is called.
If methods are compiled at execution time, chances are non-zero, that some method(s) have to be compiled on the first call, and an additional delay is introduced.
(unless you have visited all methods previously and the code cache is big enough to hold all methods
- but then, the dynamic memory requirements of a just-in-time system are in the same order as with static compilation ...).

This defined behavior is the main reason for industrial users to prefer static over dynamic compilation.

Configuration files

Stc can be used like any other (batch-) compiler by calling it directly from the UNIX/DOS command line. However, since there are many possible command line arguments and configuration settings that have to be managed, it is easier and suggested that you use Makefiles to compile classes and build systems.

The system as delivered includes shell scripts and make rules to handle different architectures and configurations. To avoid the need for rewriting all Makefiles for different architectures, all relevant Makefiles are created from prototypes; these are named "Make.proto"; one is found in every directory. (Notice: this is similar to what imake does with Imakefiles)

The configurator (called "CONFIG") reads these prototypes and creates the actual Makefiles depending on the choosen configuration.

To do so, the configurator uses so called config and rule files, which define all architecture and configuration dependent settings.

Rule files are found in the "rules" subdirectory; config files in subdirectories of "configurations".
You don't have to care for the rule files normally - they are independent of the configuration.
The config files are organized by machine architecture and configuration. They define things like C-compiler flags, include paths, classes to be included in the building process etc.

In addition, package-lists are used to control which classLibraries are to be built into the system. These are found in the "configurations/PACKS" subdirectory.
Package lists define which objects should be included, config files define how these objects are built.

The generic paths of config files looks like:

    configurations/COMMON/defines
    configurations/architecture/COMMON/defines
    configurations/architecture/configuration/defines
For example, the linux definitions for linux versions above 1.0, with C-optimizer turned on and GL-simulator classes included are taken from:
    configurations/COMMON/defines
    configurations/linux/COMMON/defines
    configurations/linux/linux1.x-opt-vgl/defines
the definitions used for a configuration without GL classes is in:
    configurations/COMMON/defines
    configurations/linux/COMMON/defines
    configurations/linux/linux1.x-opt/defines
and so on. The name of the directory has no semantic meaning - its only for human readers (I could have called them "linux-1", "linux-2" etc).
When a smalltalk is built, the name of the configuration is stamped into the executable - look at the launchers aboutBox, to see the configuration of your system.

When "Makefiles" are built, all defines are simply concatenated in the above order - this allows definitions from the COMMON config files to be redefined. "CONFIG" needs the name of the architecture, the name of a package-list and the name of the configuration to create the "Makefiles".

Once built, "Makefiles" know from which configuration they were created and know how to recreate "Makefiles".
You should therefore never copy Makefiles to other architectures, or use the same directory for multiple platforms (i.e. do not NFS-mount to another platform and make there).
Finally, do not edit the Makefiles, since they may be recreated and your changes will be lost. Only edit "Make.proto" files.

Summary:

Whats in a config file

The system as delivered is already setup correctly for your machine - therefore, you may skip reading the next chapters, unless you plan to fiddle around with the C-compilers flag settings or want to use another compiler.

Remember, that for all of the following definitions, useful defaults are setup in
"configurations/COMMON/defines" and "configurations/arch/COMMON/defines".

In normal situations, no changes are required. However, if you need anything to be changed, do so in your configuration specific config file; never in a common one.
Since later definitions overwrite previous ones, you can always change things by adding a define to the private defines file.

The following is a short extract - there are many more things that can (but are not required to) be changed:

    CC=                     defines the c-compilers name
			    (not recommended to change)

    O=.o                    extension for object files
			    (not recommended to change;
			     - usually ".o" on UNIX, ".obj" on MSDOS)


    #
    # for "make install" only:
    #
    DESTBINDIR=             where are binaries to be installed
    DESTLIBDIR=             where are libraries to be installed
    DESTINCLDIR=            where are include files to be installed
    DESTMANDIR=             where are man pages to be installed

    #
    # for additional directories and libs (see below)
    #
    OTHERLIBS=              specifies names of other (c-)libraries to be
			    included in the final link

    #
    # Xlib stuff
    #
    XINCLUDE=               path to X include files
    LIBX=                   whats the name of your X-lib
    LIBXEXT=                whats the name of your Xext-lib
    X_LIB_DIR=              path to where X-libraries are found


    #
    # stc compiler flags
    #
    STCCONFOPT=             arguments passed to stc

    #
    # c compiler flags and (preprocessor) defines
    #
    DEFS=                   addidtional defines passed to the c-compiler
    XDEFS=                  like DEFS, for XWindow-related files/classes

    OPT=                    addidtional optimizer flags passed to the c-compiler
			    (typically something like -O6 -m486 ...)

    #
    # additional individual class objects
    #
    EXTRA_CLASSES=          extra individual compiled classes to be
			    included in the final link. These are classes
			    that do not come from class libraries.

    EXTRA_OBJ=              the corresponding object file names

The common configuration files define things like relative path names (within the ST/X file hierarchy), make rules etc.
Most important (and of general interest) are the following definitions, which can be used in "Make.proto" files:
    INCLUDE=                the relative path to the include directory

    STC=                    the relative path to the stc compiler
			    (usually: $(TOP)/stc/stc, but may be redefined to refer
			     to an stc in some other directory)

    LIBBASICDIR=            the name of the directory where the basic classes
			    reside. Similar definitions are found for all the
			    other standard packages.

    BIN_O=                  the suffix of individual binary object files (cc targets)
			    (".o" with unix; different on other architectures).
			    Always use this in your "Make.proto" files
			    to remain architecture independent.

    O_EXT=                  the suffix of class library files (stx packages)
			    (".o" or ".obj" on systems
			     which do NOT support shared libraries;
			     ".so" or ".sl" on systems which do)

Whats in a package file

This section can be skipped - it is only of interest if if you want to change the set of libraries & modules which are included in the smalltalk executable.

As mentioned above, the package files (in "configurations/PACKS") control which class libraries and additional C libraries are to be built and included in the resulting executable.

The entries found there are:

    WORKSTAT1=                  name of the primary Display driver class
				(typically: XWorkstation)

    WORKSTAT2=                  name of the secondary Display driver class
				(typically: GLXWorkstation)

    EXTRA_CLASSES=              names of additional classes, which
				are to be included from individual object
				files (not class libraries)
				Typically: XWorkstation GLXWorkstat

    EXTRA_OBJ=                  names corresponding object file names
				Typically: $(LIBVIEWDIR)/XWorkstat$(BIN_O)

    OTHERLIBDIRS=               other directories, which the build process
				should visit and `make'

    CLASSLIBDIRS=               directories containing class library sources
				and `Make.proto' files to be built.

    LIBOBJS=                    names of classLibrary objects to be included
				in the link.

    LIBLIST=                    names of the packages found in above objects.
				Typically, these correspond to the file
				names, but in rare cases, these names could
				differ.
The above information may not be up to date, when you read this document.
Examine the files found in configurations/PACKS for more information.

Recompiling the system in part or fully

Although recompilation of the complete system is easily done with:
	cd TOP
	make clobber            - to clean everything
	make target             - make a target system as set by CONFIG
that takes hours on some machines. For local changes, you will get a feeling of what needs to be recompiled. For example, after adding a method to a class in "libbasic", only a recompilation of that class is required and you can skip over the full remake.
In this case, you can also type:
	cd libbasic
	make
	cd ../projects/smalltalk
	make smalltalk
which is much faster, since not all directories are visited.

However, whenever instance variables are added to classes which are subclassed somewhere else, these subclasses have to be recompiled as well (The makefile generator has added a dependency section to your Makefiles - so only subclasses will be recompiled in the full make)

When new source files (i.e. new classes) are added to a classLibrary, add its name to the "Make.proto" file (or regenerate a new one) and type:

	...
	cd theDirectoryWhereTheSourceWasAdded
	make mf
	..
	make
	...
	cd ../projects/smalltalk
	make
the difference is that "make smalltalk" only relinks the smalltalk executable, while the later "make" also scans all directories for ".st" files and creates symbolic links in the "source" subdirectory (remember: these are required for the browser to find a methods sourcecode).

To recreate the sourcelinks only, use:

	...
	cd ../projects/smalltalk
	make sourceLink
(there are corresponding rules to link the bitmap, resource and style files.

Whats in a Make.proto file

Since all architecture and configuration specific things are handled by the config files, Make.protos need not (should not) include any system dependencies.

Therefore, "Make.proto" files are rather short. They only define the name of the library to be created, the subdirectories (if any) that should be visited and the names of the object files, which make up the library.

The required defines are:

    TOP=                            defines the position relative to the TOP
				    directory (see example below)

    ALLSUBDIRS=                     names of subdirectories, where Makefiles
				    are to be created (if any).

    SUBDIRS=                        names of subdirectories (if any), which should
				    be visited during the build process.

    LIBNAME=                        name of the class library which is to be
				    created by this makefile.
				    (empty, if this is not for a classlib)

    all::                           default rule; usually, this simply calls
				    for the 'classLibRule' target, which creates
				    the required help files, object file(s) and
				    a prelinked classLibrary (possibly a shared one).
				    Additional C file targets should go here

    OBJS=                           names all object files which are to be
				    built and/or included in the classLibrary.

optional are definitions which change compilation flags:
    STCOPT=                         stc options; defaulted in COMMON/defines
				    There is usually no need to redefine this in
				    individual Make.proto files.

    STCLOCALOPT=                    stc options to be used in addition
				    to standard settings;
				    additional package or optimization
				    flags should be given here.
				    For example: 'STCLOCALOPTS=+optspace3'
optional but highly recommended rules are:
    clean:                          a rule to cleanup all intermediate files,
				    but not the library targets - so that the
				    executable can be relinked without recompilation.
				    Typically, all object files are removed here.

    clobber:                        a rule to cleanup everything
				    Ideally, the directory is left in the state it
				    had initially.
				    (Makefiles are usually kept)
				    Typically, all object files and library files
				    are removed here.

    tar:                            create a tar file containing the source files,
				    Make.proto and any additional files for source
				    code distribution.

    # BEGINMAKEDEPEND               the "make mf" rule will
    # ENDMAKEDEPEND                 insert dependency information in between
				    those. Always include those two keywords at
				    the end of your proto file.

For example, the "Make.proto" for the basic class library looks (somewhat) like:
    TOP=..                          - its directly under TOP
    SUBDIRS=                        - I have no subdirectories to make

    LIBNAME=libbasic                - thats the name of the classlibrary

    STCOPT=$(LIBBASIC_STCOPT)       - override default options
				      (LIBBASIC_STCOPT is +optinline)

    STCLOCALOPT=-P(stx:libbasic) \  - define the package of all classes
		-warnGlobalAssign \   compiled here, turn off some warnings
		+optinline2           and turn on more inlining


    all::   classListRule           - default rule: create abbrev file
				      objects, classList and a prelinked
				      class library

    OBJS=   Object.$(O) \           - names all object files which are
	    Boolean.$(O) \            to be created from corresponding .st
	    ...                       files. Notice the $(O) instead of .o;
				      This allows the same Make.proto to be
				      be used on MSDOS and Mac systems (where object
				      files are named differently).

    # BEGINMAKEDEPEND               - template for dependencies
    # ENDMAKEDEPEND

How to get an initial Make.proto file

There are two useful ways of optaining an initial Make.proto file: The stmkmp scans the current directory for smalltalk-source files (files ending in '.st') and generates a Make.proto file for them.

How to get an initial Makefile

As noted above, every Makefile as generated from a Make.proto knows how to regenerate itself and how to create Makefiles in subdirectories.
However, the very first time, the Makefile must be generated manually - either via the CONFIG script, or via the stmkmf ('st-make-makeFile') script, which is also found in the rules subdirectory.

The above mentioned stmkmp generates an initial Makefile automatically for you.

Creating binary class libraries

The following gives step-by-step information on how to add a new class library. For all of your new classes, this is the recommended way of doing things. Adding classes to existing directories may lead to problems and/or added work whenever a new ST/X release is delivered and installed: you would have to reedit all of your changed Make.proto files.

Lets assume, that your new library is to be called "libfoo" and shall contain the classes called Foo, Bar and Baz.

  1. Write the classes
    Enter, test and debug the classes in the existing environment (i.e. in the browser).

  2. Create a home for the sources
    Create a directory - a good strategy is to name the directory according the class library that is to be created. In this example, a good name would be "libfoo".

    To avoid additional work when new ST/X releases are installed, please DO NOT create this directory below the ST/X top.
    We recommend, that this directory is created beside the ST/X hierarchy, and suggest the following setup:

        someDir/stx/                        - home of stx
    	   ... libbasic                 - as delivered
    	   ... rules
    	   ...
    
        someDir//common           - your common classLibs
    
        someDir//project1         - your projects - beside stx
    	    ... project1/classLib1      - further subdivided if required
    	    ... project1/classLib2      - further subdivided if required
    
        someDir//project2         - your projects - beside stx
    	    ... project2/classLib1      - further subdivided if required
    	    ... project2/classLib2      - further subdivided if required
    

    This setup will avoid any conflict, when additional classLibraries are integrated from other vendors, or a new ST/X revision is installed. (also, note that additional addOn packages as delivered from eXept (such as ASN1, OSI etc.) will go into someDir/eXept/... and not conflict with your files.

    After all of this, lets assume that your new directory is called:

       .../yourCompanyName/project1/libfoo
    
    and it is locate beside the ST/X tree, which is:
       .../stx/...
    

  3. Create the source files
    Save the source using fileOut in the SystemBrowser.

    Notice, that by default, the browser creates the files in your startup directory (which is usually "projects/smalltalk"); so you have to manually move the files into "$TOP/libfoo" in this case.
    A better strategy is to open a project, activate it, and set its fileout-directory name to "$(TOP)/libfoo".
    Then open a browser in this project and fileOut your classes.

    You may put all of your classes into a common category - this allows easier file out. Since stc requires that each class is in a separate source file, the fileOut-category function cannot be used here (since it creates one huge file containing all classes).
    Instead, use fileOut-each, which saves each class in a separate sourcefile.


    Alternatively (if you have a SourceCodeManager configured), check the classes into the repository in the systemBrowser (possibly into a new module / module-package), open a terminal view (xterm), and check them out with the 'co' shell command.

  4. Create a Make.proto file
    You can either copy an existing "Make.proto", and change it as required, or use the "stmkmp" shell script, which automatically generates a "Make.proto" for all files ending in ".st" found in the current directory.
    (try "stmkmp --help" for its usage).

    Stmkmp can only create simple proto files for class libraries - if you need rules for additional c-libraries, you have to edit the generated file manually.

    Here is what the output of "stmkmp" could look like:

        #
        # required: where are we relative to TOP
        #
        TOP=..
    
        #
        # list subdirectories to visit during make
        #
        SUBDIRS=
    
        #
        # required: the name of the resulting class library
        #
        LIBNAME=libfoo
    
        #
        # required: the module and package definition.
        # (for package identification and repository SourceCode access)
        #
        PACKAGE=yourCompany:project/libfoo
    
        #
        # not required: the default is empty
        # but defining a package is highly recommended
        # (see the ProjectViews browse function ...)
        #
        STCLOCALOPT=-Pfoo-classes
    
        #
        # required: define whats to be done
        #
        # this says:
        #   - build all that is required for a class library
        # you can edit the Make.proto file and add additional
        # targets there.
        #
        all::  classLibRule
    
        #
        # required: what are my objects
        #
        objs::
    		Foo.$(O)        \
    		Bar.$(O)        \
    		Baz.$(O)
    
    
        #
        # recommended: cleanup rules
        #
        clean::
    	    -rm -f *.H
    
        clobber::
    	    -rm -f *.o
    
        #
        # dependency rules
        # BEGINMAKEDEPEND - do not remove
        # ENDMAKEDEPEND   - do not remove
    
    The "stmkmp" command itself is found in "rules" initially; you may want to copy it to "/usr/local/bin" for public access.

  5. Edit the generated Make.proto
    You should at least change the definitions of:

  6. Create a Makefile from the proto
    Normally, stmkmp also creates an initial "Makefile", so you are ready to enter "make" now.
    However, it fails to create the "Makefile", if it was not able to find a path to the TOP directory (because it could not find any configuration files then ...).
    If this was the case, you can use the stmkmf command, which reads configuration files from a given projects top directory name. (i.e. if you have installed ST/X somewhere else, or if you want to use configurations different from the standard ones as provided)
    Try "stmkmf --help" to get a list of options.

    If all else fails, use any other existing and valid ST/X "Makefile":

        cd libfoo
        make -f /libbasic/Makefile Makefile
    

    Option (only if you want to extent the basic smalltalk system):
    You can also arrange for your directory to be visited automatically during the normal build process, by adding the "libfoo" directory to a package file (in configurations/PACKS).
    Do this only for ST/X base package extensions - not for your own project libraries.

    To do so, take any existing package file (in "configurations/PACKS"), and add the foo library to the LIBLIST definition, the class libraries object file name to the LIBOBJS definition and finally, the directory name to the CLASSLIBDIRS definition.

    Your package file should now look like:

        ...
        #
        # to make libfoo when compiling:
        #
        CLASSLIBDIRS= $(LIBBASICDIR) ....
    		  ...
    		  
    
        #
        # to also include it when linking an executable:
        #
        LIBOBJS=      $(LIBBASIC) ...
    		  ...
    		  libfoo$(O_EXT)
    
        LIBLIST=      libbasic ...
    		  ...
    		  libfoo
    
    Then change to the top directory, and reconfigure ("CONFIG").
    Watch the output as makefiles are created:
    the added "libfoo" directory should be visited along with the other directories and a "Makefile" be generated there.

    After this, every make started in the TOP directory will always include your libfoo directory. You will never again have to do things manually there.

  7. Compile your library
    While testing, you probably do not want to start the (time consuming) global make in TOP, but instead only compile things local to libfoo.
    	cd libfoo
    	make
    
    this should (after a while) leave you with your new classLibrary libfoo in that directory.
    Depending on the architecture and/or configuration, the filename extension of the library varies; any of "libfoo.a", "libfoo.obj", "libfoo.o" or "libfoo.so" may be found there after the make. Don't care for this detail - the make rules create whatever is best for your architecture.
    (For example, on some systems archives (".a" extension) lead to very long link times - on those, classLibraries are prelinked, relocatable objects (".obj"). Some do not allow ".obj", therefore ".o" is used. Finally, some support shared libraries named ".so", ".sl" or even ".dll")
    If you plan to pass the compiled class library to others, all you have to distribute is the libfoo object just created.
    The others (those who include your binary) must change their config files too, but only have to perform the following (and final) step.

  8. Get the classes into the executable
    If you are on a system which supports dynamic loading ( SGI Indy, linux a.out or ELF, SUNOS, Solaris, Unixware SYS5.4, alpha OSF1 and WIN32 systems), you can attach this library to your running system without leaving it (use fileIn in the FileBrowser).

    Alternatively, you can add a line to the "private.rc" or "startup.rc" scripts, which loads the library at startup time:

        ...
        Smalltalk fileIn:'name-of-your-class-object-file'.
        ...
    
    there is also another (recommended) interface:
        ...
        Smalltalk fileIn:'name-of-your-class-object-file-without-suffix'.
        ...
    
    which does the same, but is portable in that it determines the required file suffix itself (".so" / ".sl" or ".dll", depending on the system)

    On all systems which do NOT support dynamic loading, you have to leave any running smalltalk, compile your classlibraries, relink the smalltalk executable and start a new (this time with those new classes being part of the built-in classes).

    Since saved snapshot images are (currently) unusable after a system rebuild, it is now time to save all your work in source form (i.e. fileOut all other classes and make certain that you can reconstruct your universe later from these and/or the changes file).

    The smalltalk executable is rebuilt with:

        cd projects/smalltalk
        make
    
    (later, you will only use "make smalltalk"; but the first time, we need the source-links to be created).
Congratulations ! you should now find your foo-classes in the system when starting the new executable. (use "smalltalk -I" to have it ignore any existing snapshot file.)

For your tests, keep the old snapshot and smalltalk executable around as "st.img.sav" and "smalltalk.sav" for a while - just in case.

Adding more classes

Once you are through the above hard work, adding more classes is easy:
    ...
    Save more classes into the libfoo directory
    ...

    cd TOP/libfoo

    ...
    add entries for the class-filenames in Make.proto
    or rerun stmkmp and re-edit LIBNAME, PACKAGE etc.
    ...

    make

    cd ../projects/smalltalk
    make
As above, a remake of the smalltalk executable itself is only required if your system does not support shared libraries.
If it does you can even switch to the new classLibrary in the running system, by: unloading any old loaded classLibrary first (using the launchers File-Modules dialog), and re-filingIn the new shared library.

WARNING:
Depending on the C-Code / C-libraries you have included, this reloading may fail occasionally, if there are leftOver references to static data or functions somewhere in the C-code.
This may even lead to a crash in some situations.

We highly recommend saving your work before any reload - over time, you will get a feeling for that ;-)

Adding more classlibraries (to the base system)

You may not want to add classes forever to that single libfoo library. At some point, it may be required to add another library. To do so, follow the above steps again, leading to entries in your config file which look like:
    OTHERLIBDIRS=libfoo libfoo2 ...

    PRIVATEOBJS=$(TOP)/libfoo/libfoo$(OBJNAME) \
		$(TOP)/wherever/libfoo2$(OBJNAME) \
		...

    PRIVATE_SO=$(TOP)/libfoo/libfoo$(SO_NAME) \
		$(TOP)/wherever/libfoo2$(SO_NAME) \
		...

    PRIVATELIBS=libfoo libfoo2 ...
If you are working in a group with others, a good strategy is to place classlibraries into a central directory, which can be used from anybode.
In this case, all users of the class library (i.e. those that do not care for how these are created) will only need the PRIVATE definitions in their config file, NOT the OTHERLIBDIRS line.

For example, if you have placed the classlibraries to "/usr/local/lib", these other config files should look like:

    PRIVATEOBJS=/usr/local/lib/libfoo$(OBJNAME) \
		/usr/local/lib/libfoo2$(OBJNAME)

    PRIVATE_SO=/usr/local/lib/libfoo$(SO_NAME) \
	       /usr/local/lib/libfoo2$(SO_NAME)

    PRIVATELIBS=libfoo libfoo2
Remember again, that after every such change, your Makefile in projects/smalltalk has to be regenerated.

Interfacing C functions

To add C functions, you have various options of where these are located (in any case you will need a smalltalk wrapper method which calls those functions - this is described in ``How to write primitives & inline C code''): Except for the first case above (putting them into the primitiveFunctions section), you will have to change your config file to have the C library included. See the next chapter on how this is done.

Adding C libraries

Additional C libraries are included in the link of the smalltalk executable by specifying them as "OTHERLIBS" in the config file. For example, if you have a C library called "libUseful.a", placed under TOP/libfoo/cStuff, the line should look like:
    OTHERLIBS=$(TOP)/libfoo/cStuff/libUseful.a
Of course, if the library is located in some standard place (i.e. in /usr/lib or /usr/local/lib), you can also write:
    OTHERLIBS=-lUseful
Read the C-compilers and linkers man pages if you need more information on this.

All OTHERLIBS are linked in the order specified; thus, if you have dependencies between your extra libraries, these may be fixed by changing the order. For example, if you have two libraries "libUseful1.a" and "libUseful2.a", of which the second needs entries in the first, you will get a link error if the config define looks like:

    OTHERLIBS=$(TOP)/libfoo/cStuff/libUseful1.a \
	      $(TOP)/libfoo/cStuff/libUseful2.a
in this case, change the order as in:
    OTHERLIBS=$(TOP)/libfoo/cStuff/libUseful2.a \
	      $(TOP)/libfoo/cStuff/libUseful1.a

An example for C Interfacing

In the following, an interface to C functions which are compiled from separate sources is shown.
For the example, we assume that a directory "libfoo" exists, and the library is to be named "libfoo" as well.
For better structuring, we place the C sources into a subdirectory of "libfoo" called "cstuff" and create a C library called "cstuff.a" there.
The C sources are in "libfoo/cstuff/module1.c":
    cFuntion1() {
	printf("here is your C function call ....\n");
    }
and "libfoo/cstuff/module2.c":
    cFuntion2(arg)
	int arg;
    {
	printf("here is your 2nd C funtion; the args value is %d\n");
    }
The interface wrapping code for smalltalk is in "libfoo/CInterface.st":
    Object subclass:#Cinterface
	   instanceVariableNames:''
	   classVariableNames:''
	   poolDictionaries:''
    !

    !Cinterface class methodsFor:'C calling'!

    cFuntion1
    %{
	cFuntion1();
    %}
    !

    cFuntion2:argument
    %{
	if (__isSmallInteger(argument)) {
	    cFuntion2( _intVal(argument) );
	}
    %}
    ! !
The "Make.proto" to compile all of these is:
    TOP=..
    LIBNAME=libfoo

    all::   CSTUFF abbrev.stc objs genClassList $(OBJTARGET)

    objs::  CInterface.$(O)

    CSTUFF::
	    (cd cstuff ; make)
The C library is built by the following rules in "cstuff/Makefile":
    all:    module1.o module2.o
	    ar rv cstuff.a module1.o module2.o
Thats it, after a "make" in libfoo, you will find "libfoo.obj" (or "libfoo.so") and "libfoo/cstuff.a" ready for linkage.

To get those into the executable, your config file should have the definitions:

    OTHERLIBDIRS=$(TOP)/libfoo

    PRIVATEOBJS=$(TOP)/libfoo/libfoo$(OBJNAME)

    PRIVATE_SO=$(TOP)/libfoo/libfoo$(SO_NAME)

    PRIVATELIBS=libfoo

    OTHERLIBS=$(TOP)/libfoo/cstuff/cstuff.a
The files of the example can be found in "doc/coding/libfoo_example".

For details on the primitive wrapper code, read ``How to write primitives & inline C code''.

Automatic building

Automatic creation and building via the project management is being prepared. However, at this time, this feature is not fully implemented and things should be done manually.

Once completed, you will be able to create per project directories, Make.protos and the sources by the click of a button.


Copyright © 1995 Claus Gittinger Development & Consulting

<cg@exept.de>

Doc $Revision: 1.22 $ $Date: 2009/11/05 14:56:10 $