From 6e0b25ef9b7b3accb8edb3a3a668d19b58bff1dc Mon Sep 17 00:00:00 2001 From: Frej Soya Date: Thu, 28 Sep 2023 00:50:49 +0200 Subject: [PATCH 1/2] test(ctypes): missing link flags to ocamlmklib Signed-off-by: Frej Soya --- .../ctypes/bytecode-stubs-external-lib.t/dune | 4 +++ .../dune-project | 3 ++ .../bytecode-stubs-external-lib.t/example.ml | 2 ++ .../bytecode-stubs-external-lib.t/run.t | 29 +++++++++++++++++++ .../stubgen/dune | 14 +++++++++ .../stubgen/function_description.ml | 8 +++++ .../stubgen/type_description.ml | 3 ++ test/blackbox-tests/test-cases/ctypes/dune | 1 + 8 files changed, 64 insertions(+) create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune-project create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/example.ml create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/dune create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/function_description.ml create mode 100644 test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/type_description.ml diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune new file mode 100644 index 00000000000..2ca1e427745 --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune @@ -0,0 +1,4 @@ +(executable + (name example) + (modes byte) + (libraries examplelib)) diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune-project b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune-project new file mode 100644 index 00000000000..d993321861b --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/dune-project @@ -0,0 +1,3 @@ +(lang dune 3.10) + +(using ctypes 0.3) diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/example.ml b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/example.ml new file mode 100644 index 00000000000..eebafeb3114 --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/example.ml @@ -0,0 +1,2 @@ +let () = + Printf.printf "%d\n" (Examplelib.C.Functions.add2 2) diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t new file mode 100644 index 00000000000..c7101a070be --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t @@ -0,0 +1,29 @@ +Build an example library as a DLL and set up the environment so that it looks +like a system/distro library that can be probed with pkg-config and dynamically +loaded. + + $ LIBEX=$(realpath "$PWD/../libexample") + +ocamlrun + requires CAML_LD_LIBRARY_PATH such that dlopen system call can find +dllexamplelib_stub.so + +Explictly set {DYLD,LD}_LIBRARY_PATH at runtime for this testcase, otherwise +dlopen cannot find libexample, after loading dllexamplelib_stub.so + + $ PKG_CONFIG_PATH="$LIBEX/pkgconfig" PKG_CONFIG_ARGN="--define-prefix" DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$LIBEX" LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIBEX" CAML_LD_LIBRARY_PATH="$CAML_LD_LIBRARY_PATH:$PWD/_build/default/stubgen" dune exec ./example.bc + Fatal error: cannot load shared library dllexamplelib_stubs + Reason: $TESTCASE_ROOT/_build/default/stubgen/dllexamplelib_stubs.so: undefined symbol: example_add2 + Aborted + [134] + +Utop works with ctypes pkg-config external library. + + $ DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$LIBEX" LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIBEX" PKG_CONFIG_PATH="$LIBEX/pkgconfig" PKG_CONFIG_ARGN="--define-prefix" dune utop --display=short ./ -- example.ml + pkg-config stubgen/.pkg-config/libexample.cflags + pkg-config stubgen/.pkg-config/libexample.libs + ocamlc .utop/.utop.eobjs/byte/dune__exe__Utop.{cmi,cmo,cmt} + ocamlc .utop/utop.bc + Fatal error: cannot load shared library dllexamplelib_stubs + Reason: $TESTCASE_ROOT/_build/default/stubgen/dllexamplelib_stubs.so: undefined symbol: example_add2 + Aborted + [134] diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/dune b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/dune new file mode 100644 index 00000000000..a426491271d --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/dune @@ -0,0 +1,14 @@ +(library + (name examplelib) + (flags (:standard -w -9-27)) + (ctypes + (external_library_name libexample) + (build_flags_resolver pkg_config) + (headers (include "example.h")) + (type_description + (instance Types) + (functor Type_description)) + (function_description + (instance Functions) + (functor Function_description)) + (generated_entry_point C))) diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/function_description.ml b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/function_description.ml new file mode 100644 index 00000000000..05c43d79e2f --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/function_description.ml @@ -0,0 +1,8 @@ +open Ctypes + +module Types = Types_generated + +module Functions (F : Ctypes.FOREIGN) = struct + open F + let add2 = foreign "example_add2" (int @-> returning int) +end diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/type_description.ml b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/type_description.ml new file mode 100644 index 00000000000..41693fda9b3 --- /dev/null +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/stubgen/type_description.ml @@ -0,0 +1,3 @@ +module Types (F : Ctypes.TYPE) = struct + +end diff --git a/test/blackbox-tests/test-cases/ctypes/dune b/test/blackbox-tests/test-cases/ctypes/dune index 3d9ec9e0309..a3d6c3586aa 100644 --- a/test/blackbox-tests/test-cases/ctypes/dune +++ b/test/blackbox-tests/test-cases/ctypes/dune @@ -27,6 +27,7 @@ (cram (applies_to + bytecode-stubs-external-lib lib-pkg_config lib-pkg_config-multiple-fd lib-external-name-need-mangling From 2ad6ac9aa895434d51cd47a30b21a5deaeb55d40 Mon Sep 17 00:00:00 2001 From: Frej Soya Date: Wed, 13 Mar 2024 21:56:11 +0000 Subject: [PATCH 2/2] fix(ctypes): Add link flags for external dependencies when using ctypes. Required when the external lib is not statically linked, in which case linker needs to be aware at runtime what libs to call. This is the case for - dune exec .bc - dune utop - mdx tests That is add to ocamlmklib, link flags such as -l -L from ctypes if info is available. If dependent library are not installed in expected locations, env variable such as LD_LIBRARY_PATH must be extended when required program is run, depending on os. This may be fixed by adding relocatable paths to link flags. Signed-off-by: Frej Soya --- doc/changes/8784.md | 1 + src/dune_rules/lib_rules.ml | 9 ++++++++- .../ctypes/bytecode-stubs-external-lib.t/run.t | 10 ++-------- 3 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 doc/changes/8784.md diff --git a/doc/changes/8784.md b/doc/changes/8784.md new file mode 100644 index 00000000000..7833995a5b0 --- /dev/null +++ b/doc/changes/8784.md @@ -0,0 +1 @@ +- Add link flags to to ocamlmklib for ctypes stubs (#8784, @frejsoya) diff --git a/src/dune_rules/lib_rules.ml b/src/dune_rules/lib_rules.ml index 048bd582976..a5f9e8540cf 100644 --- a/src/dune_rules/lib_rules.ml +++ b/src/dune_rules/lib_rules.ml @@ -328,7 +328,14 @@ let build_stubs lib ~cctx ~dir ~expander ~requires ~dir_contents ~vlib_stubs_o_f | _ -> Action_builder.return [] in let c_library_flags = - Expander.expand_and_eval_set expander lib.c_library_flags ~standard + let open Action_builder.O in + let+ c_lib = Expander.expand_and_eval_set expander lib.c_library_flags ~standard + and+ ctypes_lib = + (* CR rgrinberg: Should we add these flags to :standard? to make + it possible for users to remove these *) + Ctypes_rules.ctypes_cclib_flags sctx ~expander ~buildable:lib.buildable + in + c_lib @ ctypes_lib in let lib_o_files_for_all_modes = Mode.Map.Multi.for_all_modes o_files in let for_all_modes = List.rev_append vlib_stubs_o_files lib_o_files_for_all_modes in diff --git a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t index c7101a070be..c9ec942bad1 100644 --- a/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t +++ b/test/blackbox-tests/test-cases/ctypes/bytecode-stubs-external-lib.t/run.t @@ -11,10 +11,7 @@ Explictly set {DYLD,LD}_LIBRARY_PATH at runtime for this testcase, otherwise dlopen cannot find libexample, after loading dllexamplelib_stub.so $ PKG_CONFIG_PATH="$LIBEX/pkgconfig" PKG_CONFIG_ARGN="--define-prefix" DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$LIBEX" LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LIBEX" CAML_LD_LIBRARY_PATH="$CAML_LD_LIBRARY_PATH:$PWD/_build/default/stubgen" dune exec ./example.bc - Fatal error: cannot load shared library dllexamplelib_stubs - Reason: $TESTCASE_ROOT/_build/default/stubgen/dllexamplelib_stubs.so: undefined symbol: example_add2 - Aborted - [134] + 4 Utop works with ctypes pkg-config external library. @@ -23,7 +20,4 @@ Utop works with ctypes pkg-config external library. pkg-config stubgen/.pkg-config/libexample.libs ocamlc .utop/.utop.eobjs/byte/dune__exe__Utop.{cmi,cmo,cmt} ocamlc .utop/utop.bc - Fatal error: cannot load shared library dllexamplelib_stubs - Reason: $TESTCASE_ROOT/_build/default/stubgen/dllexamplelib_stubs.so: undefined symbol: example_add2 - Aborted - [134] + 4