CL+SSL: Analysis of useful code.
CL+SSL implements a config system that allows the user to customize the location of the needed .so, .mylib, or .dll external files. I believe this mechanism is a big win for the Common Lisp community. This is my analysis of the configuration of external library paths available in CL+SSL.
The Terms I Use
External Library - non-lisp code libraries usually the .so, .mylib, or .dll file types.
Interface Library - lisp FFI code that allows the use of External Libraries.
Guessing Code - the part of the Interface Library that attempts to find the .so, .mylib, or .dll file which contains the External Library.
Certain Location - A location the user or programmer knows for certain to find the External Library.
The Problem
The Guessing Code does not know the Certain Location and throws a condition on loading of the Interface Library.
The Solution
The interface libraries to external libraries should have a configuration option to locate the external file containing that library. The user configures the interface library by indicating the Certain Location.
The CL+SSL system allows the user to call macros from the CL+SSL/config package to set the Certain Location for libssl and libcrypto which are External Libraries needed by the Interface Library.
The Gory Details
About the Code
The source version of the CL+SSL code is https://github.com/cl-plus-ssl/cl-plus-ssl/tree/1e2ffc9511df4b1c25c23e0313a642a610dae352.
The code is written using the CFFI foreign function library system.
The system definition, the cl+ssl.asd
cl+ssl is specified by the cl+ssl.asd which also specifes a secondary system cl+ssl/config. The system cl+ssl is dependent on cl+ssl/config and thus must be loaded before the cl+ssl system. To use a fully configured cl+ssl the user must use the package cl+ssl/config and call the "define-libxxxx-path" macros before using the package cl+ssl.
The config package - src/config.lisp
cl+ssl requires libssl and libcrypto, which are external libraries, the user can configure the location for the package cl+ssl/config. cl+ssl/config specifies *libssl-override* and *libcrypto-override* which I refer to as "override flags" both of which are initialized to nil. The macros (define-libssl-path path) and (define-libcrypto-path path) both call cffi:define-foreign-lbrary with a path and define symbols libssl and libcrypto respectfully. In addition, the "override flags" are marked as true, which indicates the configurator knows the correct path to the library. You can see the source where the macros are being exported in lines 28 and 29.
The Documentation String has an accurate usage description of the path definition process. Also, note the deprecation of the cl+ssl-foreign-libs-already-loaded feature being the previous mechanism for defining how to externally load the libraries.
config.lisp enforces the following conditions, when the override flag is true the Certain Location is set in the CFFI:libssl or CFFI:libcrypo variable. When the override flag is nil the external library location is determined by the guessing code.
src/reload.lisp
When no override is called for the guessing code searches and stores it in the CFFI:libssl or CFFI:libcrypo But when the override is called for all the guessing code is bypassed because of the known Certain Location.
reload.lisp has four sections: First, MacOS code that is not required on Windows or Linux. Second, a libcrypto lib search section guarded by libcrypto override flags. Third, a libssl lib search section guarded by libssl override flag. Forth, the libraries are loaded by the final four lines of code, where two are guarded based on the deprecation of the cl+ssl-foreign-libs-already-loaded feature flag.
(unless *override*
(a lot of guessing for libxxxx-paths))
(load-foreign-library libxxxx)
My test on windows
Using the above config method, loading cl+ssl with mingw64 versions of OpenSSL libraries was successful. The current Windows version of OpenSSL libraries also worked as expected.