Commit b984b4f3 by Francois-Rene Rideau

4.1.3: release.

Bump ASDF dependency to 3.1.2.

Use package-inferred-system for dispatch and release.

Update release script to depend on inferior-shell 2.0.3, and
check that the manual is up-to-date.

Update manual, debian stuff.
parent 143faded
......@@ -2,9 +2,12 @@
# Generated when compiling with e.g. SLIME
TODO for cl-launch as of 4.1.2
TODO for cl-launch as of 4.1.3
* When resuming from an image then dumping another, the INCLUDE_PATH
becomes a very bad variable to look for the image.
......@@ -68,14 +68,8 @@ TODO for cl-launch as of 4.1.2
When starting cl-launch, I experience a pause of ~1s.
Half of it is loading the asdf fasl, then the upgraded asdf fasl.
The other half is scanning the source registry.
At least this scanning can be sped up, by patching ASDF
to support a source-registry cache or something.
* Improve release script to check and/or update that the date in matches the date of the commit being released,
and generate cl-launch.1 from it using something.
pandoc? Ugly. ronn? Looks OK, if we replace its first lines
by our first line.
At least this scanning can be sped up, using ASDF 3.1.4's
* Use #+sbcl (setf sb-ext:*evaluator-mode* :interpret)
and a series of (declaim (optimize (speed 0) (size 0) (debug 0)
(defsystem "cl-launch-dispatch"
:depends-on (#-asdf3.1 (:version "uiop" "3.1"))
:components ((:file "dispatch")))
#| -- shell wrapper for Common Lisp -*- Lisp -*-
license_information () {
# Please send your improvements to the author:
......@@ -88,7 +88,7 @@ PROGBASE="${0##*/}" # "$(basename "$0")"
HELP_HEADER=" $CL_LAUNCH_VERSION \"(March 2015)\" \"Francois-Rene Rideau's\" \"shell wrapper for Common Lisp\""
HELP_HEADER=" $CL_LAUNCH_VERSION \"(April 2015)\" \"Francois-Rene Rideau's\" \"shell wrapper for Common Lisp\""
print_help_header () {
ECHO "============"
......@@ -176,8 +176,8 @@ EOF
print_more_help () {
Invocation of \`cl-launch\`
Invocation of cl-launch
\`cl-launch\` will evaluate Common Lisp code or create shell scripts or
executable binaries that evaluate Common Lisp code. cl-launch follows
......@@ -194,7 +194,7 @@ Recent Linux kernels support a script interpreter itself being a script;
BSD kernels don't and require a small C program cl-shim to be compiled and
installed as /usr/bin/cl to use cl-launch this way.
To work properly, \`cl-launch\` 4.0.8 depends on \`ASDF\` 3.0.1 or later, and
To work properly, \`cl-launch\` 4.1.3 depends on \`ASDF\` 3.1.2 or later, and
on its portability layer \`UIOP\`, to manage compilation and image life cycle.
The software is specified as the evaluation of code in several phases;
......@@ -207,7 +207,7 @@ In the first phase, the Lisp image is initialized:
(option \`-I --image\`)
* loading a small header of code that provides common \`cl-launch\` functionality
* loading \`ASDF3\`.
The \`cl-launch\` header will try hard to load \`ASDF 3.0.1\` or later.
The \`cl-launch\` header will try hard to load \`ASDF 3.1.2\` or later.
If your implementation does not provide it via \`(require "asdf")\`,
you can configure your implementation's \`ASDF\` (if any) to find it.
Or you can put it in your home, under \`~/common-lip/asdf/\`
......@@ -308,8 +308,8 @@ at which point it happens when you invoke the executable output file:
if multiple are provided, the last one provided overrides previous ones.
If you want several functions to be called, you may \`DEFUN\` one that calls
them and use it as a restart, or you may use multiple init forms as below.
See also below options `-DE --dispatch-entry`, \`-sm --system-main\`,
\`-Ds --dispatch-system\` that behave as if `-E --entry` had been specified
See also below options \`-DE --dispatch-entry\`, \`-sm --system-main\`,
\`-Ds --dispatch-system\` that behave as if \`-E --entry\` had been specified
among other things.
* If neither restart nor entry function is provided, the program will exit with
status \`0\` (success). If a function was provided, the program will exit
......@@ -343,16 +343,16 @@ The following derived options work as if by a combination of simpler options:
* If option \`-DE --dispatch-entry\` is used, then the next argument must follow
the format \`NAME/ENTRY\`, where \`NAME\` is a name that the program may be
invoked as (the basename of the \`uiop:argv0\` argument), and \`ENTRY\` is
a function to be invoked as if by `--entry` when that is the case.
a function to be invoked as if by \`--entry\` when that is the case.
If the \`ENTRY\` is left out, function \`main\` in current package is used.
Support for option \`-DE --dispatch-entry\` is delegated to a dispatch library,
distributed with \`cl-launch\` but not part of \`cl-launch\` itself, by
(1) registering a dependency on the dispatch library as if by
\`--system cl-launch-dispatch\` (if not already)
\`--system cl-launch/dispatch\` (if not already)
(2) if neither \`--restart\` nor \`--entry\` was specified yet, registering a
default entry function as if by \`--entry cl-launch-dispatch:dispatch-entry\`.
default entry function as if by \`--entry cl-launch/dispatch:dispatch-entry\`.
(3) registering a build-form that registers the dispatch entry as if by
\`--eval '(cl-launch-dispatch:register-name/entry "NAME/ENTRY" :PACKAGE)'\`
\`--eval '(cl-launch/dispatch:register-name/entry "NAME/ENTRY" :PACKAGE)'\`
where \`PACKAGE\` is the current package.
See the documentation of said library for further details.
......@@ -1213,13 +1213,13 @@ set_entry () {
add_dispatch_entry () {
if [ -z "$DISPATCH_ENTRY_P" ] ; then
add_build_form "(:load-system \"cl-launch-dispatch\")"
add_build_form "(:load-system \"cl-launch/dispatch\")"
if [ -z "$RESTART" ] ; then
set_entry "cl-launch-dispatch:dispatch-entry"
set_entry "cl-launch/dispatch:dispatch-entry"
add_build_form "(:eval \"$(kwote "(cl-launch-dispatch:register-name/entry \"$(kwote "$1")\" :$2)")\")"
add_build_form "(:eval \"$(kwote "(cl-launch/dispatch:register-name/entry \"$(kwote "$1")\" :$2)")\")"
add_build_form () {
......@@ -1746,7 +1746,9 @@ print_cl_launch_asd () {
;; If the initial ASDF isn't, you're likely in trouble.
(asdf:defsystem :cl-launch
:depends-on ((:version "asdf" "3.0.1")) ; we need UIOP, included in ASDF 3 and later
:defsystem-depends-on ("asdf-package-system")
:class :package-inferred-system
:depends-on ((:version "asdf" "3.1.2")) ; we want some recent enough ASDF and UIOP
:licence "MIT"
:components ((:file "launcher")))
......@@ -2287,7 +2289,7 @@ NIL
;; only if ASDF 3 is in a predictable place under the user's homedir, thus
;; ~/common-lisp/asdf/ or ~/.local/share/common-lisp/source/asdf/ only.
(block nil
(let ((required-asdf-version "3.0.1")
(let ((required-asdf-version "3.1.2")
(verbose *load-verbose*))
(labels ((asdf-symbol (name)
(and (find-package :asdf) (find-symbol (string name) :asdf)))
......@@ -2349,8 +2351,8 @@ NIL
;; Most implementations provide ASDF, but while most of them are case-insensitive,
;; CLISP is case-sensitive, so we need to specify a lowercase string,
;; and not the keyword :asdf or symbol 'asdf.
;; Most implementations provide ASDF 3, but some of them only ASDF 2
;; and antique versions only ASDF 1.
;; Most recent implementations provide ASDF 3, but some of them only ASDF 2
;; and antique versions only of ASDF 1.
#'(lambda () (funcall 'require "asdf")))
(try-file-stage-1 "asdf" "default (visible)" (user-homedir-pathname)
"~/" '("common-lisp"))
......@@ -2412,8 +2414,8 @@ NIL
":" 't #-cl-launch ;'; cl_fragment<<'NIL'
;; Because of ASDF upgrade punting, this ASDF package may be a new one.
(eval-when (:compile-toplevel :load-toplevel :execute)
(unless (or #+asdf2 (asdf:version-satisfies (asdf:asdf-version) "3.0.1"))
(error "cl-launch requires ASDF 3.0.1 or later (3.1.1 for dumping images)")))
(unless (or #+asdf2 (asdf:version-satisfies (asdf:asdf-version) "3.1.2"))
(error "cl-launch requires ASDF 3.1.2 or later")))
":" 't #-cl-launch ;'; cl_fragment<<'NIL'
;;;; Create cl-launch with UIOP.
cl-launch (4.1.3-1) unstable; urgency=low
* New options --system-main and --dispatch-system
* updated manual and release script
-- Francois-Rene Rideau <> Wed, 22 Apr 2015 15:01:28 -0400
cl-launch (4.1.2-2) unstable; urgency=low
* Multiple entry binaries with --dispatched-entry,
......@@ -12,8 +12,8 @@ Package: cl-launch
Architecture: all
Depends: ${misc:Depends}
Suggests: cl-asdf (>= 2:3.1.4)
Recommends: sbcl (>= 1:1.1.10), cl-asdf (>= 2:3.1.1)
Breaks: cl-asdf (<< 2:3.0.1), common-lisp-controller (<= 7.2)
Recommends: sbcl (>= 1:1.2.3), cl-asdf (>= 2:3.1.2)
Breaks: cl-asdf (<< 2:3.1.1), common-lisp-controller (<= 7.2)
Description: uniform frontend to running Common Lisp code from the shell
CL-Launch will allow you to invoke Common Lisp source code from the shell
command line, from a shell script or as a Common Lisp script. It will also
......@@ -44,7 +44,7 @@ install: build
dh_installdirs -p ${debpkg} $(include_dir) $(doc-dir)
dh_install -i cl-launch usr/bin
dh_install -i launcher.lisp cl-launch.asd build.xcvb \
cl-launch-dispatch.asd dispatch.lisp ${include_dir}
dispatch.lisp ${include_dir}
dh_installman -i debian/*.1
(defpackage :cl-launch-dispatch
(defpackage :cl-launch/dispatch
(:use :uiop :cl)
(:export #:dispatch-entry #:get-entry
#:register-name/entry #:register-entry
#:dispatch-entry-error #:get-name #:basename #:all-entry-names
#:dispatcher #:not-found))
(in-package :cl-launch-dispatch)
(in-package :cl-launch/dispatch)
(defvar *default-behavior* 'dispatcher
"the default behavior if the argv0 invocation name is not recognized.")
#| -*- Lisp -*-
#!/usr/bin/cl -s inferior-shell -s optima.ppcre -E cl-launch-release::main
exec "$(dirname $0)/" \
--system inferior-shell --system optima.ppcre \
-X --package cl-launch-release --entry main -- "$0" "$@" ; exit
#!/usr/bin/cl -sm cl-launch/release
exec "$(dirname $0)/" -X --system-main cl-launch/release -- "$0" "$@" ; exit
(defpackage :cl-launch-release
(defpackage :cl-launch/release
(:use :cl :uiop :asdf :inferior-shell :optima :optima.ppcre)
;; Note: the exports are the list of available commands.
(:export #:rep #:clean
;; Note: these exports are also the list of available commands.
(:export #:rep #:clean #:manpage
#:source #:quickrelease
#:debian-package #:publish-debian-package #:debian-package-all))
(in-package :cl-launch-release)
(in-package :cl-launch/release)
(eval-when (:compile-toplevel :load-toplevel :execute)
(unless (fboundp 'argv0) (defun argv0 () "release.lisp")) ;; only in ASDF 3.1.2 or later
(flet ((check-system-version (name version)
(let ((system (find-system name)))
(unless (version-satisfies system version)
(die 2 "~A requires ~A at least ~A but only got version ~A"
(argv0) name version (component-version system))))))
(check-system-version "inferior-shell" "2.0.0"))) ;; for default run outputs
(check-system-version "asdf" "3.1.2") ;; for package-inferred-system, uiop:argv0
(check-system-version "inferior-shell" "2.0.3"))) ;; for default run outputs, on-error error.
(defvar *cl-launch-directory* ;; interactive users may want to override that.
(or (argv0) *load-pathname* (nil-pathname)) #'getcwd))))
(or (argv0) *compile-file-pathname* *load-pathname* (nil-pathname)) #'getcwd))))
(defun pn (&optional x)
(subpathname *cl-launch-directory* x))
(defun rep (argument)
;; read-eval-print, no loop.
(eval-input (strcat "(in-package :cl-launch-release) " argument)))
(eval-input (strcat "(in-package :cl-launch/release) " argument)))
(defun script-version ()
(match (read-file-line (pn "") :at 2)
......@@ -73,6 +70,7 @@ exec "$(dirname $0)/" \
(home (user-homedir-pathname))
(cl-launch-version (strcat "cl-launch-" version))
(cldir (subpathname home "files/cl-launch/")))
(with-current-directory ((pn))
(run `(pwd) :show t)
......@@ -111,14 +109,56 @@ exec "$(dirname $0)/" \
(defun source ()
(with-current-directory ()
(with-current-directory ((pn))
(run `(./ --include ,(getcwd) "-B" install_path))))
(defparameter *months* #("January" "February" "March" "April" "May" "June"
"July" "August" "September" "October" "November" "December"))
(defun get-date-from-manual ()
(with-current-directory ((pn))
(match (first (run/lines `(./ --help)))
((ppcre "\"[(]([A-Z][a-z]+) ([0-9]+)[)]\"" month year)
(if-let (pos (position month *months* :test 'equal))
(list (parse-integer year) (1+ pos))
(error "Invalid month ~a" month)))
(_ (error "Can't extract month from manual")))))
(defun get-date-from-git (&optional tag)
(with-current-directory ((pn))
(match (first (run/lines `(git log -1 "--pretty=format:%cI" ,tag)))
((ppcre "^([0-9]+)-([0-9]+)-([0-9]+)T" year month day)
(list (parse-integer year) (parse-integer month) (parse-integer day))))))
(defun check-manual-git-dates-match ()
(let ((date-from-manual (get-date-from-manual))
(date-from-git (subseq (get-date-from-git) 0 2)))
(assert (equal date-from-manual date-from-git) ()
"Manual says it's from ~{~D-~2,'0D~} but git commit is from ~{~D-~2,'0D~}"
date-from-manual date-from-git)))
(defun manpage ()
(with-current-directory ((pn))
(run `(ln -sf cl))
(run `(env ("PATH=.:" ,(getenv "PATH")) cl --more-help (>
(run `(ronn "--roff" "--manual=Shell Scripting with Common Lisp"
"--organization=Francois-Rene Rideau"
,(format nil "--date=~{~D-~2,'0D-~2,'0D~}" (get-date-from-git)) (> 2 /dev/null)))))
(defun check-manual ()
(with-current-directory ((pn))
(run `(cmp ./cl-launch.1 ./debian/cl-launch.1))))
(defun quickrelease ()
(let* ((version (script-version)) ;; no need to compare with the debian version
(link (strcat "cl-launch-" version))
(tarball (strcat link ".tar.gz")))
(with-current-directory ()
(with-current-directory ((pn))
(with-current-directory ((pn "../"))
......@@ -137,11 +177,11 @@ exec "$(dirname $0)/" \
(defun valid-commands ()
(sort (while-collecting (c) (do-external-symbols (x :cl-launch-release) (c x))) #'string<))
(sort (while-collecting (c) (do-external-symbols (x :cl-launch/release) (c x))) #'string<))
(defun main (argv)
(multiple-value-bind (command status)
(find-symbol (string-upcase (first argv)) :cl-launch-release)
(find-symbol (string-upcase (first argv)) :cl-launch/release)
(if (eq status :external)
(format t "~@[~{~S~^ ~}~%~]" (multiple-value-list (apply command (rest argv))))
(die 2 "~A ~:[requires a command~;doesn't recognize command ~:*~A~].~%Try one of: ~(~{~A~^ ~}~)~%"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment