Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I had already written large, nontrivial apps (linked in article) which required more libraries than babashka was written with, including ones I had written but also others. I therefore needed to run native-image on my own codebase, as it was not runnable from within babashka (at the time? I don't know if it is now).

Running native-image on an already established, not-written-for-it codebase is a nightmare. I just tried again some months ago on the linked code bases. native-image wouldn't budge. Kept getting hung up on I don't even know what, the errors were way too opaque or the app just misbehaved in weird ways.



Ok, that explains why babashka wasn't suitable. I still wonder, though, about the requirement to have an executable.

I still remember many years of reading comp.lang.lisp, where the #1 complaint of newcomers was that "common lisp cannot produce a native executable". I remember being somewhat amused by this, because apparently nobody expected the same thing from other languages, like, say, Python. But apparently things have changed over the years and now CL implementations can produce bundled executables while Clojure can't — how the tables have turned :-)


I think various Lisp implementations have their own way to do it, e.g save-lisp-and-die on SBCL.

But, if what you mean "executable" is "small compact executable like the one build by C/C++/Pascal, without extra Lisp runtime attached", perhaps you better look at something else, well like C.


`uiop:dump-image` lets you do it in an implementation independent way.


You just need to use a lisp implementation that has a tree-shaker if you really care about binary size for since reason


Chicken Scheme makes very nice, tidy binary executables. "Hello World" is just 27K on Ubuntu.


Gerbil scheme gives you the tiny bins and fully static binaries. No need to cargo cult portions of quicklisp with the binaries.


There is already confusion. Things are different and the same words (executable, native, image, ...) mean slightly different things.

In the CL world it is usually relatively easy to create an executable. For example in SBCL I would just run SBCL and then save an image and say that it should be an executable. That's basically it. The resulting executable

* is already native compiled, since SBCL always compiles native -> all code is AOT compiled to machine code

* includes all code and data, thus there is nothing special to do, to change code for it -> the code runs without changes

* includes all the SBCL tools (compiler, repl, disassembler, code loader, ...) thus it can be used to develop with it -> the code can be still "dynamic" for further changes

* it starts fast

Thus I don't need a special VM or special tool to create an executable and/or AOT compiled code. It's built-in in SBCL.

The first drawback: the resulting executable is as large as the original SBCL was plus any additional code.

But for many use cases that's what we want: a fast starting Lisp, which includes everything precompiled.

Now it gets messy:

In the real world (TM) things might be more complicated:

* we want the executable to be smaller

* we want to get rid of debug information

* we need to include libraries written in other languages

* we want faster / more efficient execution at runtime

* we need to deliver the Lisp code&data as a shared library

* we need an executable with tuned garbage collector or without GC

* the delivery structure can be more complex (-> macOS application bundles for multiple architectures)

* we want to deliver for platforms which provide restrictions (-> iOS/Apple for example doesn't let us include a native code compiler in the executable, if we want to ship it via the Appstore)

* we want the code&data be delivered for an embedded application

That's in the CL world usually called delivery -> creating an delivered application that can be shipped to the customer (whoever that is).

This was (and is) typically where commercial CL implementations (nowadays Allegro CL and LispWorks) have extensive tooling for. A delivered LispWorks application may start at around 7MB size, depending on the platform. But there are also special capabilities of ECL (Embeddable Common Lisp). Additionally there were (and still are) specialized CL implementations, embedded in applications or which are used as a special purpose compiler. For example some of the PTC Creo CAD systems use their own CL implementation (based on a ancestor implementation of ECL), run several million lines of Lisp code and expose it to the user as an extension language.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: