Using "csm" To Build Eggs
The csm build system is able to build eggs (extension libraries for the CHICKEN Scheme system) by itself in recent versions (0.93 or newer), which reduces the need to declare dependencies in egg specifications and makes the development cycle for eggs somewhat simpler.
To be able to use csm, you will need CHICKEN 6.0.1pre1 or later, which adds support for toplevel custom-build clauses in the .egg file that delegate the actual build process completely to a user-supplied shell script.
Let's imagine we have the following files:
csm-example.egg csm-example/bar.scm csm-example/foo.scm csm-example/baz.scm build main.scm tests/run.scm
We want to build the egg csm-example, which contains three components, all dynamically loadable libraries holding a module of code. We have chosen to organize the modules into a subdirectory, a convention that csm supports, so the modules (csm-example foo) ... reside in the csm-example subdrectory as files foo.scm ..., one file per module.
It is not strictly necessary to do it this way, you can also just put your modules into the toplevel directory and have a "flat" module naming convention, it is up to you. csm only scans the directory tree, parses module definitions and maps source files to modules. But pointless structural hierarchies like we use here appear more "enterprisey", thus adding points to our CV.
The files holding the code look like this:
csm-example/foo.scm: the main module
(define-library (csm-example foo)
(import (scheme base) (scheme write) (csm-example bar) (csm-example baz))
(export-all)
(begin
(define (screaming-yellow-zonkers)
(frobnicate 1)
(nail-jelly-to-tree)
(display "EAT!\n"))))
csm-example/bar.scm: a helper module
(define-library (csm-example bar)
(import (scheme base) (scheme write) (csm-example baz))
(export-all)
(begin
(define (nail-jelly-to-tree)
(frobnicate 2)
(display "nailing jelly to tree...\n"))))
csm-example/baz.scm: another support module
(define-library (csm-example baz)
(import (scheme base) (chicken base))
(export-all)
(begin
(define (frobnicate times)
(print "frobnicating " times " time"
(if (> times 1) "s" "")
" ..."))))
Take a moment to appreciate the meticulous attention to detail in frobnicate - it is things like these that make the difference between scrappy example code and the robust, future-proof software we, as professionals, take pride in.
csm-example.egg: The egg specification file
((synopsis "Example egg for building with csm")
(category misc)
(license "WTFPL")
(author "felix winkelmann")
(dependencies csm)
(custom-build "build")
(components
(extension csm-example.foo)
(extension csm-example.bar)
(extension csm-example.baz)))
We need to add csm as a dependency, naturally. Also make sure to list all modules to be installed as components of the extension type, using the alternative naming of compound modules. We also need a toplevel custom-build property that tells chicken-install to delegate the building of all components to a shell script.
build the custom build script
#!/bin/sh csm -compile-imports csm -static
Since csm does not support building dynamic and static modules at the same time, we invoke it twice to make sure we have both dynamically loadable modules and alternative files that can be used for static linking.
Running chicken-install, probably with the -test option should now build and test the egg.
Does static linking work? Let's try.
main.scm:
(import (csm-example foo)) (define (main) (screaming-yellow-zonkers)) (main)
% csc -static main.scm -o a.out % ./a.out frobnicating 1 time ... frobnicating 2 times ... nailing jelly to tree... EAT! %
We are content.