runtime-path.ss: Declaring Paths Needed at Run Time

To load: (require (lib "runtime-path.ss"))

The runtime-path.ss library provides forms for accessing non-module files and directories at run time using a path that is usually relative to the module's source file. Unlike using collection-path or this-expression-source-directory, using a runtime-path.ss form exposes each run-time path to tools like the executable and distribution creators, so that files and directories needed at run time are carried along in a distribution.

(define-runtime-path identifier expr)      SYNTAX

Uses expr as both a compile-time expression and a run-time expression. In either context, expr should produce a path, a string that represents a path, a list of the form (list 'lib string ···1), or a list of the form (list 'so string).

For run time, identifier is bound to a path that is based on the result of expr. The path is normally computed by taking a relative path result from expr and adding it to the same path that this-expression-source-directory would produce (see section 19). However, tools like the executable creator can also arrange (by colluding with runtime-path.ss) to have a different base path substituted in a generated executable. If expr produces an absolute path, it is normally returned directly, but again may be replaced by an executable creator. In all cases, the executable creator preserves the relative locations of all paths. When expr produces a relative or absolute path, then the path bound to identifier is always an absolute path.

If expr produces a list of the form (list 'lib string ···1), the value bound to identifier is an absolute path. The path refers to a file named by the first string that is (originally) in the collection specified by the remaining strings, where the collection mzlib is used if only one string is provided.

If expr produces a list of the form (list 'so string), the value bound to identifier can be either string or an absolute path; it is an absolute path when adding the platform-specific shared-library extension -- as produced by (system-type 'so-suffix) -- and then searching in the PLT-specific shared-object library directories (as determined by find-dll-dirs from dirs.ss in the setup collection) locates the path. In this way, shared-object libraries that are installed specifically for PLT Scheme get carried along in distributions.

For compile-time, the expr result is used by an executable creator -- but not the result when the containing module is compiled. Instead, expr is preserved in the module as a compile-time expression (in the sense of begin-for-syntax). Later, at the time that an executable is created, the compile-time portion of the module is executed (again), and the result of expr is the file to be included with the executable. The reason for the extra compile-time execution is that the result of expr might be platform-dependent, so the result should not be stored in the (platform-independent) bytecode form of the module; the platform at executable-creation time, however, is the same as at run time for the executable. Note that expr is still evaluated at run-time; consequently, avoid procedures like collection-path, which depends on the source installation, and instead use relative paths and forms like (list 'lib string ···1).

If a path is needed only on some platforms and not on others, use define-runtime-path-list with an expr that produces an empty list on platforms where the path is not needed.

Examples:

;; Access a file data.txt at run-time that is originally
;; located in the same directory as the module source file:
(define-runtime-path data-file "data.txt")
(define (read-data) 
  (call-with-input-file data-file 
    (lambda () 
      (read-bytes (file-size data-file)))))
 
;; Load a platform-specific shared object (using ffi-lib; see
;; PLT Foreign Interface Manual) that is located in a platform-specific sub-directory
;; of the module's source directory:
(define-runtime-path libfit-path
  (build-path "compiled" "native" (system-library-subpath #f)
              (path-replace-suffix "libfit" (system-type 'so-suffix))))
(define libfit (ffi-lib libfit-path))
 
;; Load a platform-specific shared object that might be installed
;; as part of the operating system, or might be installed specifically
;; for PLT Scheme:
(define-runtime-path libssl-so
  (case (system-type)
    [(windows) '(so "ssleay32")]
    [else '(so "libssl")]))
(define libssl (ffi-lib libssl-so))

(define-runtime-paths (identifier ···) expr)      SYNTAX

Like define-runtime-path but declares and binds multiple paths at once.

(define-runtime-path-list identifier expr)      SYNTAX

Like define-runtime-path, but expr should produce a list of paths.

(runtime-path module-path)      SYNTAX

This form is mainly for use by tools such as executable builders. It expands to a quoted list containing the run-time paths declared by module-path, returning the compile-time results of the declaration exprs, except that paths are converted to byte strings. The enclosing module must require (directly or indirectly) the module specified by module-path, which is an unquoted module path.