Quantcast
Viewing all articles
Browse latest Browse all 521

How to compile and link a Fortran library component with dune

I’m wondering if I am compiling and linking a simple one-file Fortran sublibrary correctly into my OCaml library. Ideally I would like to be able to make my library installable on linux and macos with a simple opam install.

After some fiddling and googling I have arrived at the project structure shown below, which seems to work for loading the Fortran library via ctypes like so:

integrate_mvnd.ml

open Containers
open Ctypes
[...]
let mvnd =
  match
    Sys.getenv "CAML_LD_LIBRARY_PATH"
    |> String.split_on_char ':'
    |> List.cons (Sys.getcwd ())
    |> List.find_map (fun p ->
        try
          let filename = p ^ "/dllmvnd.so" in
          Some (Dl.dlopen ~flags:Dl.[RTLD_NOW;] ~filename)
        with Dl.DL_error _ -> None)
  with
  | Some l -> l
  | None -> failwith "unable to load mvnd shared library"

let ocaml_mvnd arg1 arg2 [...] = 
   Foreign.foreign ~from:mvnd "mvnormaldist" (ptr.integer @-> [...])

Some points I’m not content with:

  • I have to manually check for the CAML_LD_LIBRARY_PATH
  • I have to build a static library although afaict this will never work the way the library is loaded, because otherwise dune complains
  • I am using hardcoded dll filenames, but when trying @{dll_ext} in dune that also gave .so on macos not .dylib as i had expected.

Am I using dune correctly? Is there a way to switch to either fully static linking of the fortran sublibrary or only dynamic linking?

Relevant project structure bits follow:

dune:

(data_only_dirs fortran-lib)

(library
	(name vbar)
	(public_name vbar)
	(modules vbar)
	(libraries [...]))

(rule
	(deps (source_tree fortran-lib))
	(targets dllmvnd.so libmvnd.a)
	(action
		(no-infer
			(progn
				(chdir fortran-lib (run make))
				(copy fortran-lib/dllmvnd.so dllmvnd.so)
				(copy fortran-lib/libmvnd.a libmvnd.a)))))

(library
	(name integrate_mvnd)
	(public_name vbar.integrate_mvnd)
	(modules integrate_mvnd)
	(libraries [...] ctypes ctypes.foreign)
	(foreign_archives mvnd))

[...]

fortran-lib/Makefile:

.PHONY: clean all

all: mvnd.dylib libmvnd.a

mvnd.dylib: 
	gfortran -shared -O3 -fPIC -fcheck=bounds -std=f2008 -w -o dllmvnd.so mvndstpack_mod.f

libmvnd.a: 
	gfortran -c -O3 -fPIC -fcheck=bounds -std=f2008 -w mvndstpack_mod.f
	ar -rcs libmvnd.a mvndstpack_mod.o 

clean:
	rm -f *.o *.mod *.a *.dylib

12 posts - 2 participants

Read full topic


Viewing all articles
Browse latest Browse all 521

Trending Articles