Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I dump a static executable with Common Lisp?

I am using SBCL, although I have seen other implementations have similar functionality. I can dump an executable that does not require the Lisp implementation to be installed, but does rely on the standard C library. How can I make the dumped image be statically linked (i.e. have no dependencies whatsoever)?

When I am done using an image, I can call

(save-lisp-and-die "image-name" :executable t)

this will leave a file called image-name in my directory that I can then call with ./image-name. I will be dropped into a repl and everything I had done before saving-lisp-an-dying will still be there. My problem is that when I move this file to another machine, I cannot run it. Either I get the 'file not found' error, or I am told that the wrong version of GLIBC is installed. Running file on the image reveals it was dynamically linked. Is there a way to dump a statically linked image that I can just copy to any machine with a Linux kernel?

like image 587
Roxy Avatar asked Sep 14 '25 09:09

Roxy


2 Answers

A good complementary tool to save-lisp-and-die is Deploy.

What kind of "file not found" message did you have? Deploy helps to ship foreign libraries dependencies alongside your binary, such as libssl.so or libmagic.so, so they don't need to be that exact version on the target OS, or there at all.

To use it, you tweak your .asd declaration and use:

:defsystem-depends-on (:deploy)  ;; (ql:quickload "deploy") before
:build-operation "deploy-op"     ;; instead of "program-op"
:build-pathname "my-application-name"  ;; doesn't change
:entry-point "my-package:my-start-function"  ;; doesn't change

and you build your binary with (asdf:make :my-app) like usual.

Deploy creates a bin/ directory with your binary and the dependencies. This is what you have to ship now.

It should be possible to package everything in one executable archive, but I didn't get to it yet.


More info: https://lispcookbook.github.io/cl-cookbook/scripting.html#with-deploy---ship-foreign-libraries-dependencies

We actually don't mess with libssl, so we tell Deploy to ignore it:

#+linux (deploy:define-library cl+ssl::libssl :dont-deploy T)
#+linux (deploy:define-library cl+ssl::libcrypto :dont-deploy T)

Use (push :deploy-console *features*) to silence Deploy at start-up.

like image 155
Ehvince Avatar answered Sep 17 '25 02:09

Ehvince


Generate a dynamically linked executable with

(save-lisp-and-die "image-name" :executable t)

Then use one of the differents ways to generate a statically linked executable from a dynamically linked executable.

I've tried with packelf.sh, it works great !

like image 28
Jérôme Radix Avatar answered Sep 17 '25 04:09

Jérôme Radix