Search code examples
linuxmacoscommon-lispexecutablesbcl

Using $HOME in Common Lisp paths? Executable fails


My main dev environment is a Mac M1.

I sometimes also develop on an Intel mac and then deploy to a linux server. All of which have different home paths.

Ideally, id like to have a dynamic path.

This is the hardcoded M1 path:

(defvar *document* "/Users/vinceM1/quicklisp/local-projects/Project/web/")

Id like to have something like this:


(defvar *document* "$HOME/quicklisp/local-projects/Project/web/")

However, when creating an executable, the path with $HOME isn't recognised. Is there a way to use dynamic OS paths so i can capture /Users/vinceM1 or /home/server/?


Solution

  • Home directory

    The interpolation of $HOME in pathnames is not part of the language standard and not supported in any implementation I know. Some implementations support the tilde notation "~" to refer to the home directory. But if you want to be portable, your best option is to use USER-HOMEDIR-PATHNAME.

    For example:

    (defvar *document* (merge-pathnames "path/to/www" (user-homedir-pathname)))
    => #P"/home/user/path/to/www"
    

    ASDF systems

    In your example you define the document relative to some of your project. In fact, you can be portable in a different way by using ASDF:SYSTEM-RELATIVE-PATHNAME:

    (defvar *document* (asdf:system-relative-pathname :project "www/"))
    => #P"/home/user/quicklisp/local-projects/project/www"
    

    The paths are relative to the directory where the .asd file defining the given system is.

    Environment variables

    In case you really need to access an environment variable, you can rely on osicat to do that:

    (probe-file (osicat-posix:getenv "HOME"))
    => #P"/home/user/"
    

    I am using probe-file to convert a string to a pathname ending with a / (a directory).