screwlisp proposes kittens

C++ ECL Openbsd Port

After interviewing jeremy_list, I wanted to pull functions out of his habitat secure scuttlebutt client (C++), and to embed or interleave portable embeddable common lisp in lieu of nonportable haikuos features. I use openbsd, all else being equal, though I am meant to be trying dragonflybsd one of these days. So this article does that.

Doing that meaning making an openbsd native C++ ecl port for openbsd. Every operating system or linux distribution has their own analogy of doing this. At some point your lisp system needs to interface with the host operating system. Using openbsd ports(7) on openbsd means your software all hooks together properly. Since we are particularly using C++, we would like to be able to get C++ libraries from the package manager, so playing ball properly is doubly necessary.

Anyway, here’s specifically and literally what I did on openbsd. You could adopt openbsd and never look back, or it’s always kind of like this for whatever os (though openbsd/macports/freebsd/netbsd/dragonflybsd and friends particularly).

Starting point: the existing ecl port

ecl is a major ansi CL implementation, so openbsd has a maintained port of 24.5.10. ECL is fundamentally lisp-as-a-C-or-C+±lib (libecl). The existing port is for C rather than C++. Without further ado, here it is:

COMMENT =	embeddable common-lisp
CATEGORIES =	lang

V =		24.5.10
DISTNAME =	ecl-$V
SHARED_LIBS +=	ecl	9.0

REVISION =	2

HOMEPAGE =	https://common-lisp.net/project/ecl/
MAINTAINER =	Timo Myyra <timo.myyra@bittivirhe.fi>

EXTRACT_SUFX =	.tgz

# LGPLv2 or later
PERMIT_PACKAGE =	Yes

SITES =			${HOMEPAGE}static/files/release/

COMPILER =		base-clang ports-gcc
COMPILER_LANGS =	c
USE_GMAKE =		Yes
CONFIGURE_STYLE =	gnu
TEST_TARGET =		check
CONFIGURE_ENV +=	CPPFLAGS=-I${LOCALBASE}/include \
			ECLLIB_VERSION=${LIBecl_VERSION} \
			ecldir=${LOCALBASE}/lib/ecl \
			MAKEINFO=${PREFIX}/bin/gmakeinfo

CONFIGURE_ARGS +=	--enable-boehm=system \
			--enable-libatomic=system \
			--enable-gmp=system \
			--with-gmp-prefix=${LOCALBASE}

# etags gets picked up if it's installed, and dumps core while
# generating the tags. so override it for now untill etags is fixed.
CONFIGURE_ENV +=	ETAGS=/usr/bin/true

WANTLIB +=	atomic_ops c ffi gc gmp m pthread

BUILD_DEPENDS +=	print/texinfo

LIB_DEPENDS +=	devel/gmp \
		devel/boehm-gc,-main \
		devel/boehm-gc,-atomic \
		devel/libffi

TEST_DEPENDS =	${BASE_PKGPATH}
TEST_ENV =	"ECL=${WRKDIST}/build/bin/ecl" \
		"TEST_IMAGE=${WRKDIST}/build/bin/ecl"

.include <bsd.port.mk>

The --with-cxx version

Unified diff:

$ diff -u Makefile.orig Makefile
--- Makefile.orig	2025-08-01 16:33:39.163635975 +1200
+++ Makefile	2025-08-01 16:36:16.523631049 +1200
@@ -18,7 +18,7 @@
 SITES =			${HOMEPAGE}static/files/release/
 
 COMPILER =		base-clang ports-gcc
-COMPILER_LANGS =	c
+COMPILER_LANGS =	c c++
 USE_GMAKE =		Yes
 CONFIGURE_STYLE =	gnu
 TEST_TARGET =		check
@@ -29,6 +29,8 @@
 
 CONFIGURE_ARGS +=	--enable-boehm=system \
 			--enable-libatomic=system \
+			--with-cxx \
+			--disable-c99complex \
 			--enable-gmp=system \
 			--with-gmp-prefix=${LOCALBASE}

It’s a very slight adjustment. Technically I’m meant to have made a cxx flavor, though there are not flavors of ecl currently so I just left a mail with the maintainer. So our full patch-applied file is:

COMMENT =	embeddable common-lisp
CATEGORIES =	lang

V =		24.5.10
DISTNAME =	ecl-$V
SHARED_LIBS +=	ecl	9.0

REVISION =	2

HOMEPAGE =	https://common-lisp.net/project/ecl/
MAINTAINER =	Timo Myyra <timo.myyra@bittivirhe.fi>

EXTRACT_SUFX =	.tgz

# LGPLv2 or later
PERMIT_PACKAGE =	Yes

SITES =			${HOMEPAGE}static/files/release/

COMPILER =		base-clang ports-gcc
COMPILER_LANGS =	c c++
USE_GMAKE =		Yes
CONFIGURE_STYLE =	gnu
TEST_TARGET =		check
CONFIGURE_ENV +=	CPPFLAGS=-I${LOCALBASE}/include \
			ECLLIB_VERSION=${LIBecl_VERSION} \
			ecldir=${LOCALBASE}/lib/ecl \
			MAKEINFO=${PREFIX}/bin/gmakeinfo

CONFIGURE_ARGS +=	--enable-boehm=system \
			--enable-libatomic=system \
			--with-cxx \
			--disable-c99complex \
			--enable-gmp=system \
			--with-gmp-prefix=${LOCALBASE}

# etags gets picked up if it's installed, and dumps core while
# generating the tags. so override it for now untill etags is fixed.
CONFIGURE_ENV +=	ETAGS=/usr/bin/true

WANTLIB +=	atomic_ops c ffi gc gmp m pthread

BUILD_DEPENDS +=	print/texinfo

LIB_DEPENDS +=	devel/gmp \
		devel/boehm-gc,-main \
		devel/boehm-gc,-atomic \
		devel/libffi

TEST_DEPENDS =	${BASE_PKGPATH}
TEST_ENV =	"ECL=${WRKDIST}/build/bin/ecl" \
		"TEST_IMAGE=${WRKDIST}/build/bin/ecl"

.include <bsd.port.mk>

I asked jackdaniel to clarify my need for --disable-c99complex - basically the definition of _Complex is not standardised so it is not always present, as was the case here (and hence the available configure flag).

Building that on openbsd

Well, my path was

cd /usr/ports/mystuff/lang/ecl++/ i.e. where I had the above patched build.

doas make fake

this install(1)s dependencies in a fake (as such) environment to build safely in isolation. doas(1) is a less crazy notion of ‘sudo’. If you don’t have a dependency available because it is installed systemwise, the default is to recursively build ports (which you don’t want to do with texlive…). Followed by

doas make install which installs the binary in the expected /usr/local/bin/ecl and lib in /usr/local/lib/libecl.so.

I had to nuke my ~/.cache/common-lisp/ecl-24.5.10-unknown-bsd-x64/ after this (since all those were built with C libecl.

Conclusions

Well, this article ended up being just making a C++ openbsd port of ecl out of the available port until the maintainer adds a flavor or otherwise responds to my mail. I was quite satisfied how easy this was to do with ecl in particular and openbsd in general.

Now I can use embeddable common lisp’s ffi:c-progn freely with openbsd port C++ libraries and particular project sources like jeremy_list’s habitat.

Our C++ ecl port is also part of my insane fairy godmother idea of turning the ubiquitous C++ programs of modernity into embeddable common lisp swank servers that can be slime-connected to.

As to what we could possibly want from an operating system as lispusers: basically we want to be able to build and drag in prebuilt (carefully signed (signify(1)ed)) ports we are likely to want. Building should be both safe, well-integrated and easy to pick up, all of which openbsd satisfies. We would also like operating-system features like networking and threading to be proactively safe for normal consumption, which is an openbsd hallmark. In particular we have access to openbsd’s nonportable and openbsd-led operating system security tools and libraries.

Fin.

Hope I helped someone start using C++ embeddable common lisp and working with their OS’s ports. Talk on the Mastodon as always please.

screwlisp proposes kittens