deploy
3.0.0Tools to aid in the deployment of a fully standalone application.
Table of Contents
About Deploy
This is a system to help you easily and quickly deploy standalone common lisp applications as binaries. Specifically it is geared towards applications with foreign library dependencies that run some kind of GUI.
How To
Probably the easiest way to use Deploy is with ASDF. To integrate it, change your system definition to include the following properties:
:defsystem-depends-on (:deploy)
:build-operation "deploy-op"
:build-pathname "my-application-name"
:entry-point "my-package:my-start-function" Once you have updated your system appropriately, all you need to do is start a fresh instance of your implementation from a terminal and run the following function:
(asdf:make :my-system) This will build your system, gather the necessary information, and deploy a standalone bin folder within your project's root directory. You can then ship this folder to your users.
If you want to deploy a console application rather than a GUI application, you should use deploy-console-op instead, which will activate the proper mode on Windows, and suppress the standard startup output.
You can also leverage deploy to "just" create an image of your implementation state rather than a standalone executable. In that case, you should use the deploy-image-op.
With SBCL you can even leverage Deploy to create "shrinkwrapped" executables. These executables can statically or dynamically link C libraries and let Lisp stack frames integrate properly with foreign debuggers and profiling tools like perf. To produce a shrinkwrapped executable you must have the SBCL source tree available with which you already built your SBCL. Then you can create your executable by loading deploy and running
(deploy:shrinkwrap "my-system") It'll automatically invoke itself again to run deploy-image-op on your system, shrinkwrap that, and then compile it together with the rest of the dynamic libraries it depends on into the final executable.
Without ASDF
Deploy can also be used entirely without depending on ASDF or UIOP. After prepping everything you want, you can simply call deploy with either the name of the operation type you want to perform the usual kind of deployment, or directly with a pathname to deploy your executable to. In the latter case, it will not run any of the usual hooks and instead perform as plain of a deployment as possible.
Customising Foreign Libraries
Sometimes you might want to designate a specific library for deployment, rather than the one used during development. If this is the case, you have to help Deploy out a little by defining extra information about the library with define-library. If the foreign library is in the source tree of a lisp library, you can simply associate the CFFI library with the system that provides it, and Deploy will find it automatically:
(deploy:define-library cffi-library-symbol
:system :system-name-that-defines-the-library) For example, the cl-mpg123 system provides a single library, which we would annotate like this:
(deploy:define-library cl-mpg123-cffi:libmpg123
:system :cl-mpg123) If the file is not contained in the directory of the system that provides it, you can also designate specific source directories to scan:
(deploy:define-library cffi-library-symbol
:sources '("/some/path/where/the/library/is/stored/")) Finally, you can also specify the path directly if you want Deploy to choose a particular file, rather than trying to find one on its own:
(deploy:define-library cffi-library-symbol
:path "/some/path/to/the/file.so") Generally though these extra associations should not be necessary as Deploy will simply take the path that CFFI has already figured out to find the library.
Sometimes it might not be desired to deploy all the libraries, or reload them all upon boot. You can change this behaviour with define-library's :dont-deploy and :dont-open properties respectively.
Marking System Libraries as a Library Author
If you are a library author and want to make use of a system library, say Ole32 on Windows, or Foundation on MacOS, or FontConfig on Linux, those libraries should pretty much never be deployed. However, CFFI does not have a way to mark that status on its own, and depending on Deploy just to do that is silly.
In order to still be able to give that hint, you can add the name of your library to cl-user::*foreign-system-libraries*. Deploy will pick up on that on its own and, unless specified directly in the define-library, will make use of that. This automates the deployment exemption for users. An easy way to achieve this behaviour is:
(set 'cl-user::*foreign-system-libraries*
(union (when (boundp 'cl-user::*foreign-system-libraries*)
(symbol-value 'cl-user::*foreign-system-libraries*))
'(ole32 foundation fontconfig))) Extending Deployment and Boot Behaviour
Deploy also offers a hooks system with which you can easily extend the steps performed during deployment and during the boot process of the generated executable. With the define-hook macro you can add functions that are executed during various points of the process. Specifically, the following types are available:
:deployThese functions are responsible for copying files into the deployment target directory.:buildThese functions should prepare the system for the dump to binary. Specifically you might want to shut down existing threads, close file handles, remove unneeded baggage, and remove potentially sensitive information about your system.:bootThese functions are run right before the primary entry point is executed. Thus they are responsible for preparing the runtime to continue by restarting threads, re-opening files, and so forth.:quitThese functions are run right before the executable exits completely. They offer a last-minute opportunity to dump some information about the system, or to clean up vital resources.
If you would simply like to include a data directory to bundle with the rest, use define-resource-directory. After boot, all of the resource files will be in the directory returned by data-directory.
Deploying to an OS X App Bundle
If you would like a nicely bundled .app for OS X, you can simply change the build-operation in your ASDF system file to osx-app-deploy-op. If you would like to customise the Info.plist file that is generated for the app, you can change *info-plist-template* to point to a file that contains what you want.
Debugging a Deployed Executable
If you're having trouble with an application that's already deployed, there's a few things you can do to debug it by setting environment variables. The following are recognised by Deploy:
DEPLOY_DEBUG_BOOTif set to a non-empty value, on error the debugger is invoked rather than just exiting the application.DEPLOY_REDIRECT_OUTPUTif set to a file path, the output of all streams is redirected to this file.
Particularly on Windows and OS X debugging can be an issue, as a GUI application will not get a standard output to write to. In that case, the above redirect might help.
Support
If you'd like to support the continued development of Deploy, please consider becoming a backer on Patreon:
System Information
Definition Index
-
DEPLOY
- ORG.SHIRAKUMO.DEPLOY
No documentation provided.-
EXTERNAL SPECIAL-VARIABLE *BUILD-TIME*
If true pre-build, is set to the universal-time on build.
-
EXTERNAL SPECIAL-VARIABLE *COMPRESSION-FACTOR*
No documentation provided. -
EXTERNAL SPECIAL-VARIABLE *DATA-LOCATION*
Relative path designating the location of the resource directory. This path should be relative to the location of the executable. You may set this variable before deployment to influence where resource files are stored. See DATA-DIRECTORY
-
EXTERNAL SPECIAL-VARIABLE *SBCL-SOURCE-TREE*
Path to the SBCL source tree's root. This tree must have already been used to build the same SBCL you want to deploy with. Will try to auto-detect the path based on the logical pathname translations of SYS.
-
EXTERNAL SPECIAL-VARIABLE *SOURCE-CHECKSUM*
If true pre-build, is set to the checksum of all source files on build. See SOURCE-CHECKSUM
-
EXTERNAL SPECIAL-VARIABLE *STATUS-OUTPUT*
The output stream of status messages. You can set this to NIL if you want to suppress status messages on the console, or set them to some other stream that won't bother the user. See STATUS
-
EXTERNAL SPECIAL-VARIABLE *SYSTEM-SOURCE-DIRECTORIES*
This variable holds a list of paths to system library directories. Deploy will search through these paths to attempt to find the source of libraries if the more explicitly provided paths should fail.
-
EXTERNAL CLASS DEPLOY-CONSOLE-OP
-
EXTERNAL CLASS DEPLOY-IMAGE-OP
-
EXTERNAL CLASS DEPLOY-OP
An operation to perform a deployment. When ASDF is available, this is also an ASDF:OPERATION. When this operation is performed, the following steps are taken: 1. The :LOAD hooks are run with the appropriate arguments. 2. The output files are determined, which should be a list of two paths, the first being the executable to dump to, and the second being a directory where all the resources should be stored. 3. The list of libraries to reload on boot is computed by removing all libraries that are either marked as dont-open, or aren't yet opened from LIST-LIBRARIES. 4. The deployment directories are created. 5. The *DATA-LOCATION* path is adapted to be relative to the binary file. 6. The :DEPLOY hooks are run with the appropriate arguments. 7. The :BUILD hooks are run with the appropriate arguments. 8. The image is dumped to an executable format, using core compression if available, and using the appropriate application type. See DEPLOY See ENTRY-POINT See OUTPUT-FILE See LIST-LIBRARIES See *FOREIGN-LIBRARIES-TO-RELOAD* See *DATA-LOCATION* See RUN-HOOKS
-
EXTERNAL CLASS HOOK
This class encapsulates a hook. Hooks are functions that are run during various points of deployment and execution of the resulting executable. See HOOK-NAME See HOOK-TYPE See HOOK-FUNCTION See HOOK-PRIORITY See HOOK See REMOVE-HOOK See DEFINE-HOOK See RUN-HOOKS
-
EXTERNAL CLASS LIBRARY
Class to represent a foreign library. This is a subclass of CFFI:FOREIGN-LIBRARY with some additional slots for information necessary for the Deploy system. Upon shared-initialize, if the LIBRARY-PATH is not explicitly set, it is resolved through FIND-SOURCE- FILE. See LIBRARY-SOURCES See LIBRARY-PATH See LIBRARY-DONT-OPEN-P See LIBRARY-DONT-DEPLOY-P See FIND-SOURCE-FILE
-
EXTERNAL CLASS SHRINKWRAP-OP
No documentation provided. -
EXTERNAL FUNCTION COMMAND-LINE-ARGUMENTS
No documentation provided. -
EXTERNAL FUNCTION COPY-DIRECTORY-TREE
- SOURCE
- TARGET
- &KEY
- COPY-ROOT
- EXCLUDE
- IF-EXISTS
Copy the source directory to the target directory. If COPY-ROOT is true, the source folder itself is copied, otherwise only its contents are copied. EXCLUDE may be a function of one argument, a source path, which returns a boolean designating whether the source file should be excluded or not. See COPY-FILE
-
EXTERNAL FUNCTION COPY-FILE
- SOURCE
- TARGET
- &KEY
- IF-EXISTS
Copy the source to the target file. IF-EXISTS may be one of the following values, governing what to do if the destination file exists already: :REPLACE :SUPERSEDE :OVERWRITE --- Replaces the file regardless NIL :IGNORE --- Does nothing :ERROR --- Signals an error :UPDATE --- Replaces the file if its write date is older than the source file's See COPY-DIRECTORY-TREE -
EXTERNAL FUNCTION DATA-DIRECTORY
Return an absolute path to the resource directory. See DATA-DIRECTORY
-
EXTERNAL FUNCTION DEPLOYED-P
Returns T if the current Lisp environment has been booted from a deployed executable.
-
EXTERNAL FUNCTION ENSURE-LIBRARY
- LIBRARY
Return the corresponding LIBRARY instance, if possible. The following happens for the following type of the argument: - LIBRARY The argument is returned. - CFFI:FOREIGN-LIBRARY The object is CHANGE-CLASSd into a LIBRARY instance. - SYMBOL The library instance is retrieved by name and then passed back in. See CFFI::GET-FOREIGN-LIBRARY See LIBRARY -
EXTERNAL FUNCTION ENV-SET-P
- ENVVAR
Returns the value of the given environment variable if it is set to a non-empty value.
-
EXTERNAL FUNCTION ENVVAR
- X
Returns the value of the given environment variable. May return NIL or an empty string if the variable is unset.
-
EXTERNAL FUNCTION ENVVAR-DIRECTORIES
- VARIABLE
Returns the paths contained in the given environment variable. For Windows systems, the split character is ; otherwise it is : See ENVVAR
-
EXTERNAL FUNCTION ENVVAR-DIRECTORY
- VAR
Returns the environment variable as a pathname directory. See ENVVAR
-
EXTERNAL FUNCTION FEATUREP
- FEATURE
Returns true if the given name names a feature. See CL:*FEATURES*
-
EXTERNAL FUNCTION HOOK
- TYPE
- NAME
Accessor to the hook instance of the given type and name. See *HOOKS* See HOOK See REMOVE-HOOK
-
EXTERNAL FUNCTION (SETF HOOK)
- HOOK
- TYPE
- NAME
No documentation provided. -
EXTERNAL FUNCTION LIST-ALL-SOURCE-FILES
Returns a list of all source files of the current system state, if possible. If ASDF is available this uses the list of loaded system and their descriptions to compute the list.
-
EXTERNAL FUNCTION LIST-LIBRARIES
Return a fresh list of known foreign libraries. All the returned libraries will be of type LIBRARY. See LIBRARY See CFFI:LIST-FOREIGN-LIBRARIES See ENSURE-LIBRARY
-
EXTERNAL FUNCTION QUIT
- &OPTIONAL
- EXIT-CODE
- &REST
- ARGS
Runs the quit hooks and terminates the application. If an error occurs during the execution of a quit hook, it is ignored. See RUN-HOOKS
-
EXTERNAL FUNCTION REDIRECT-OUTPUT
- TARGET
Redirect all output to the given file. This changes *STANDARD-OUTPUT*, *ERROR-OUTPUT*, *TRACE-OUTPUT*, and *DEBUG-IO*. For the latter, only its output stream is changed. The stream to the given target file is returned.
-
EXTERNAL FUNCTION REMOVE-HOOK
- TYPE
- NAME
-
EXTERNAL FUNCTION RUN-HOOKS
- TYPE
- &REST
- ARGS
Run the hooks of the given type, supplying the given arguments. Refer to DEFINE-HOOKS for the recognised arguments for each hook type. This function simply iterates through *HOOKS*, checks the HOOK-TYPE for compliance, establishes a REPORT-ERROR restart, and then applies the HOOK-FUNCTION to the given arguments. The REPORT-ERROR restart simply prints out the error it receives and is thus useful for ignoring errors that might occur during the execution of a hook. See *HOOKS* See HOOK-FUNCTION See DEFINE-HOOK
-
EXTERNAL FUNCTION RUNTIME-DIRECTORY
Returns a pathname to the directory where the executable is being run in. See UIOP:ARGV0
-
EXTERNAL FUNCTION SHRINKWRAP
- SYSTEM
- &REST
- ARGS
- &KEY
- &ALLOW-OTHER-KEYS
Shrinkwrap the given ASDF system. This is the same as (ASDF:OOS 'DEPLOY:SHRINKWRAP-OP system args...) See SHRINKWRAP-OP
-
EXTERNAL FUNCTION SOURCE-CHECKSUM
- &OPTIONAL
- FILES
Computes a checksum of the given source files. The source files are sorted by their truenames in order to ensure consistency regardless of order. By default the output of LIST-ALL-SOURCE-FILES is used. See LIST-ALL-SOURCE-FILES See *SOURCE-CHECKSUM*
-
EXTERNAL FUNCTION STATUS
- LEVEL
- FORMAT-STRING
- &REST
- FORMAT-ARGS
Print a status message to *status-output*. The level determines the granularity of the message. Higher levels mean "more detailed". See *STATUS-OUTPUT*
-
EXTERNAL GENERIC-FUNCTION CLOSE-LIBRARY
- LIBRARY
Close/unload the library. See LIBRARY See CFFI:CLOSE-FOREIGN-LIBRARY
-
EXTERNAL GENERIC-FUNCTION DEPLOY
- OP
- &REST
- ARGS
- &KEY
- TYPE
- SYSTEM
- ENTRY-POINT
- &ALLOW-OTHER-KEYS
Performs a deployment. If the target is a pathname, a deployment is performed directly without running any hooks. If the target is a symbol, an operation object is created according to that symbol's type and the extra arguments provided. If the target is an operation object, deployment is performed according to that operation, running hooks as needed, ultimately running DEPLOY with the intended target pathname. If an ENTRY-POINT is given, that function will be invoked on boot. If a TYPE is given, it designates the kind of deployment to perform. It may be one of :EXECUTABLE -- A GUI application is deployed. :CONSOLE -- A console application is deployed. :IMAGE -- An image core file is deployed.
-
EXTERNAL GENERIC-FUNCTION ENTRY-POINT
- OBJECT
-
EXTERNAL GENERIC-FUNCTION (SETF ENTRY-POINT)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION FIND-SOURCE-FILE
- LIBRARY
Attempt to find the source file of the library on the system. Uses the directories listed in POSSIBLE-DIRECTORIES to look for the library source. The directories are searched for pathnames that match one of the POSSIBLE-PATHNAMES for the library. See LIBRARY See POSSIBLE-DIRECTORIES See POSSIBLE-PATHNAMES
-
EXTERNAL GENERIC-FUNCTION HOOK-FUNCTION
- OBJECT
-
EXTERNAL GENERIC-FUNCTION (SETF HOOK-FUNCTION)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION HOOK-NAME
- OBJECT
Accessor to the name of the hook. The name should be a symbol. See HOOK
-
EXTERNAL GENERIC-FUNCTION (SETF HOOK-NAME)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION HOOK-PRIORITY
- OBJECT
Accessor to the priority of the hook. The priority should be an integer. The higher the priority, the earlier the hook is executed. See HOOK
-
EXTERNAL GENERIC-FUNCTION (SETF HOOK-PRIORITY)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION HOOK-TYPE
- OBJECT
Accessor to the type of the hook. The type can be one of :LOAD :BUILD :DEPLOY :BOOT :QUIT. See HOOK
-
EXTERNAL GENERIC-FUNCTION (SETF HOOK-TYPE)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION LIBRARY-DEPENDENCIES
- LIBRARY
Return the library's dependant libraries, if possible. The returned value is a list of string names of the libraries. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION LIBRARY-DONT-DEPLOY-P
- LIBRARY
Accessor to whether to deploy (copy) the library to the resources directory on build. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION (SETF LIBRARY-DONT-DEPLOY-P)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION LIBRARY-DONT-OPEN-P
- OBJECT
Accessor to whether the library should not be opened on boot. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION (SETF LIBRARY-DONT-OPEN-P)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION LIBRARY-NAME
- LIBRARY
Return the library's name. See CFFI:FOREIGN-LIBRARY-NAME See LIBRARY
-
EXTERNAL GENERIC-FUNCTION LIBRARY-OPEN-P
- LIBRARY
Returns whether the library is currently open. See LIBRARY See CFFI:FOREIGN-LIBRARY-LOADED-P
-
EXTERNAL GENERIC-FUNCTION LIBRARY-PATH
- OBJECT
Accessor to the definite path to the library's source file. If this is NIL, the library could not be found. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION (SETF LIBRARY-PATH)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION LIBRARY-SONAME
- LIBRARY
Return the library's encoded soname, if possible. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION LIBRARY-SOURCES
- OBJECT
Accessor to the list of additional paths to search for source files. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION (SETF LIBRARY-SOURCES)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION OPEN-LIBRARY
- LIBRARY
Open/load the library. See LIBRARY See CFFI:LOAD-FOREIGN-LIBRARY
-
EXTERNAL GENERIC-FUNCTION OUTPUT-FILE
- OBJECT
Accesses the target output file of the deployment operation. If NIL a file will be picked for you. In the case of an ASDF operation, this will be a file named after the system being operated on, and the directory will be a subdirectory called bin/ within the system's source directory. Otherwise the bin/ directory within Deploy's source directory will be used and the name will simply be "application". See DEPLOY See DEPLOY-OP
-
EXTERNAL GENERIC-FUNCTION (SETF OUTPUT-FILE)
- NEW-VALUE
- OBJECT
No documentation provided. -
EXTERNAL GENERIC-FUNCTION PATCH-DEPENDENCIES
- LIBRARY
- CHANGES
Patch the library's encoded dependencies to match the given spec. The spec should be a list of lists, each inner list having two elements, the first being the name of the dependency to change, and the second being the name to change it to. Can be invoked with a LIBRARY, a LIBRARY designator, or a pathname of the library file to patch. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION PATCH-SONAME
- LIBRARY
Patch the library's encoded soname to match the file name. Can be invoked with a LIBRARY, a LIBRARY designator, or a pathname of the library file to patch. See LIBRARY
-
EXTERNAL GENERIC-FUNCTION POSSIBLE-DIRECTORIES
- LIBRARY
Return a list of possible directories to search for the library. By default this list includes: - The LIBRARY-SOURCES of the library. - The directory tree of the LIBRARY-SYSTEM's source. - The CFFI:*FOREIGN-LIBRARY-DIRECTORIES* - The *SYSTEM-SOURCE-DIRECTORIES* - The paths from the following environment variables: - PATH on Windows - LD_LIBRARY_PATH on Linux - DYLD_LIBRARY_PATH on Darwin See LIBRARY-SOURCES See LIBRARY-SYSTEM See DISCOVER-SUBDIRECTORIES See CFFI:*FOREIGN-LIBRARY-DIRECTORIES* See *SYSTEM-SOURCE-DIRECTORIES* See ENVVAR-DIRECTORIES
-
EXTERNAL GENERIC-FUNCTION POSSIBLE-PATHNAMES
- LIBRARY
Return a list of possible file pathnames that match the library. By default this list includes: - The CFFI:FOREIGN-LIBRARY-PATHNAME if present. - Paths computed through the CFFI library's spec. - A generic path after the LIBRARY-NAME. See CFFI:FOREIGN-LIBRARY-PATHNAME See CFFI:DEFINE-FOREIGN-LIBRARY See LIBRARY-NAME See LIBRARY See RESOLVE-CFFI-SPEC
-
EXTERNAL MACRO DEFINE-HOOK
- TYPE
- NAME
- &OPTIONAL
- PRIORITY
- ARGS
- &BODY
- BODY
Define a new hook function. The args list's arguments are automatically turned into keyword arguments for the hook function. This allows you to only specify the arguments that you are interested in. The following arguments are available for all hook types: - SYSTEM The ASDF system object the application is built with. - OP The ASDF operation object used to build the application. The following hook types are recognised: - :load These functions should perform the loading of systems or other kinds of things that will potentially change the set of libraries. - :deploy These functions are responsible for copying files into the deployment target directory. It supplies the following extra arguments: - DIRECTORY The target directory into which resource files should be placed. - :build These functions should prepare the system for the dump to binary. Specifically you might want to shut down existing threads, close file handles, remove unneeded baggage, and remove potentially sensitive information about your system. - :boot These functions are run right before the primary entry point is executed. Thus they are responsible for preparing the runtime to continue by restarting threads, re-opening files, and so forth. It supplies the following extra arguments: - DIRECTORY The directory in which the resource files now reside after boot. - :quit These functions are run right before the executable exits completely. They offer a last-minute opportunity to dump some information about the system, or to clean up vital resources. See HOOK See REMOVE-HOOK -
EXTERNAL MACRO DEFINE-LIBRARY
- NAME
- &BODY
- INITARGS
Define additional properties for a foreign library. The NAME should be one of a valid CFFI foreign library as defined by CFFI:DEFINE-FOREIGN-LIBRARY. Valid properties are: - :SYSTEM - :SOURCES - :PATH - :DONT-OPEN - :DONT-DEPLOY See LIBRARY See LIBRARY-SYSTEM See LIBRARY-SOURCES See LIBRARY-PATH See LIBRARY-DONT-OPEN-P See LIBRARY-DONT-DEPLOY-P
-
EXTERNAL MACRO DEFINE-RESOURCE-DIRECTORY
- NAME
- DIRECTORY
- &KEY
- COPY-ROOT
Shorthand to define a hook that simply deploys the given directory. The directory has to be a form that evaluates to a pathname to a directory that should be copied. The path is merged with the system source directory of the system being deployed. This means that relative paths are relative to the source root of your system. See DEFINE-HOOK See COPY-DIRECTORY-TREE