Not a full solution, but here’s how I debugged this and a way to fix this:
First, you can repro the issue with just dune runtest
in argon2 itself without fpauth. The opam file does not run the tests through opam at the moment.
This library uses ctypes.foreign
which means it relies on dlsym
to look for symbols. Since it does not use a ~from
argument, it is just going to look in the current adress space for the symbol argon2_type2string
. This means that all executables using this library need to be linked against -largon2
(the native library).
In src/dune
, you can see that there’s some work done to pass the right flags when building the library. And indeed, it can be found in the output of ocamlobjinfo _build/install/default/lib/argon2/argon2.cmxa
:
Extra C object files: -largon2 -lrt -ldl
But for some reason, when linking an executable against this library, libargon2
is not present (see the output of ldd _build/default/tests/generic.exe
.
Note that if you pass the same flags to the tests, they’ll run normally.
I think what’s happening is that your linker is configured to not link unused libraries. Nothing in the executable statically refers to any symbol in libargon2
, so it won’t link it. You can control that by passing --no-as-needed
to the linker; so -Wl,--no-as-needed
to the compiler; so -ccopt -Wl,--no-as-needed
to the ocaml compiler.
Apply this patch:
diff --git a/src/config/discover.ml b/src/config/discover.ml
index 62d2aba..b71bec1 100644
--- a/src/config/discover.ml
+++ b/src/config/discover.ml
@@ -24,5 +24,6 @@ let () =
| Some deps -> deps)
in
+ (["-ccopt"; "-Wl,--no-as-needed"])@
concat_map (fun flag -> [ "-cclib"; flag ]) conf.libs
|> C.Flags.write_sexp "flags.sexp")
And the tests run.
Now, this isn’t a great fix because it requires your linker to know about this option, and it’s only necessary in some cases. I don’t know how to write that in a portable way.
- An alternative is not to use
ctypes.foreign
. You can use ctypes stub generation for this. It will generate OCaml and C code that will be linked to your application. Dune has some support for this.
- You might be able to force linking by refering to a C symbol using
external
. I’m not sure if it will be stripped or not. This is technically a naked pointer, but if you don’t use it, maybe that’s fine?