dbenoit17 / dynamic-ffi

Auto define Racket bindings to C by parsing header files.
Other
28 stars 10 forks source link

`.so` prefix assumed on libraries that use version as extension #26

Open zyrolasting opened 4 years ago

zyrolasting commented 4 years ago

Here is a excerpt from a Vulkan SDK's lib directory listing:

libvulkan.so -> libvulkan.so.1
libvulkan.so.1 -> libvulkan.so.1.1.121
libvulkan.so.1.1.121

Here everything points to the same .so file. But I can only reference libvulkan.so using define-dynamic-ffi and define-dynamic-ffi/cached with the following program:

#lang racket/base

(require dynamic-ffi/unsafe)

(define vulkan-sdk (bytes->string/utf-8
                    (environment-variables-ref (current-environment-variables)
                                               #"VULKAN_SDK")))

(define (vulkan-path . args)
  (apply build-path vulkan-sdk args))

(define lib-path (vulkan-path "lib/libvulkan"))
(define header-path (vulkan-path "include/vulkan/vulkan.h"))

(define-dynamic-ffi/cached vulkan lib-path header-path)

(Aside: I do not use dynamic-ffi-lib because the docs do not clarify if "default system library paths" include PATH or some other way for me to point to a user-level installation. More clarification on how dynamic-ffi-lib should be used for user-level installations would also be helpful)

I know the docs say that the .so should be omitted, and it's easy enough to set libvulkan to point elsewhere, but if I wanted the program to explicitly include its own version number--say by changing lib-path to (vulkan-path "lib/libvulkan.so.1.1.121")--then the program will error out as follows due to using an extra .so extension:

file-or-directory-modify-seconds: error getting file/directory time
  path: /home/sage/vulkan/1.1.121.1/x86_64/lib/libvulkan.so.1.1.121.so
  system error: No such file or directory; errno=2
  context...:
   /home/sage/.racket/7.4/pkgs/dynamic-ffi/cached.rkt:89:2: for-loop

I believe there should be fewer assumptions about how libraries are organized and named in the system..

dbenoit17 commented 4 years ago

The dynamic FFI does assume .so by default on Linux, but that actually happens under the hood inside Racket's built-in ffi-lib. ffi-lib handles both system paths and real paths, and allows users to pass the expected version extensions as an optional list argument. The built-in ffi-lib docs do a good job going through the library search path.

dynamic-ffi-lib tries to provide an interface similar to ffi-lib for defining version extensions, but I see now how that does not come across in the docs. This library should probably document the functionality better by linking to the ffi-lib docs.

I will have a look and see about cleaning up the docs and also making the error reporting around it more clear.

In the meantime, can you see if this snippet works for you?

(define-dynamic-ffi/cached vulkan 
  (dynamic-ffi-lib lib-path '("1.1.121" #f))
  header-path)

I will keep this issue open until the documentation around it is improved.

Thanks for reporting!