PortaCL: Easing the Creation of CL Portability Libraries

Table of Contents

1 Rationale

Sometimes you want to do something based upon *features*. Often, that results in lots of reader conditionals, and a final reader conditional duplicating and negating all previous conditionals. Ew!

2 API

2.1 ASDF Components: port-file, port-module

It's not uncommon for a portability library to include something like:

(:file
  #+sbcl  "port-sbcl"
  #+clisp "port-clisp"
  #-(or sbcl clisp) (error "not supported"))
port-file and port-modules allow you to specify things more like so:
(:port-file "port-~A")
or, less positionally,
(:port-file "port-~/implementation/")

Whether such magical divinations are a good thing is left to you to decide.

port-file and port-module both also support specification of an :alternate-file, which if specified will be used in place of throwing a not-implemented error. E.g., for use if only one or two implementations need special behavior.

You can also specify :not-found-condition, the condition type which will be thrown if no applicable file is found. (e.g., you might prefer 'not-supported instead, or 'not-necessary if a missing component is okay).

2.2 Condition: not-implemented

Useful for indicating a particular thing is not implemented.

This is the default condition thrown when an implementation-specific ASDF component is not found.

2.3 Condition: not-supported

A particular thing is not implemented and won't be. E.g., because the lisp implementation lacks the necessary features.

2.4 Condition: not-necessary

If this thing is not implemented, it didn't need to be.

When specified as the :not-found-condition in a defsystem form, will cause operations on the component to be considered successful even if the component could not be found.

2.5 Function: featurep feature-expression

Given a feature expression, returns true if that expression is true.

see CLHS 24.1.2.1 for details.

2.6 Macro: define-feature-test test-name-or-names lambda-list [documentation] &body

Defines a feature test which shall return true if the given feature expressions apply.

see feature-tests.lisp for usage examples.

2.7 Macro: feature-cond ([feature-conditional] [clause]+)*

A macro version of #+foo (thing) #+bar (thing2) #-(or foo bar) (no-thing), with all the caveats and shortcomings that implies.

2.8 Macro: feature-ecase ([[feature-conditional] [clause]+]+)

feature-case, except always includes a final (error 'not-implemented).

3 Future Ideas

3.1 ASDF component enhancements

3.1.1 platform / operating system

It might be useful to also offer up the operating system for interpolation into port-files. (e.g., via ~/platform/ or ~/operating-system/).

3.1.2 shared-implementation support

It might also be useful to offer a way to specify that certain implementations should be treated just like another implementation. E.g.,

(:port-file "port-~a" :treat-as (:ecl :sbcl))
could be used by usocket, instead of futzing with :alternate-file.

3.2 Other porting styles?

Per-file implementation is not the only possible or used porting approach. Perhaps some others should also be supported?

4 Bugs

5 see also

trivial-features
smooths out the unnecessary differences between implementation *features*
alexandria
implements a #'featurep which exactly matches that used by the standard's #+/#- readmacros.
cl-syntax-sugar
Offers a feature-case reader which is almost certainly more useful than portaCL's feature-cond macro.

Date: 2009/07/20 12:30:14