Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ctypes stanza does not compile cstubs .o files with -fPIC #5809

Open
droyo opened this issue Jun 2, 2022 · 8 comments · Fixed by ocaml/opam-repository#21555
Open

ctypes stanza does not compile cstubs .o files with -fPIC #5809

droyo opened this issue Jun 2, 2022 · 8 comments · Fixed by ocaml/opam-repository#21555
Labels
c-bindings When dune is trying to interop with C

Comments

@droyo
Copy link
Contributor

droyo commented Jun 2, 2022

Please see my minimal example here: https://github.com/droyo/dune32-ctypes-fpic

Expected Behavior

When building a library with the ctypes stub generation in dune 3.2.0, dune should generate position-independent object files. This ensures that they can be put into the shared library $lib/dll$lib_stubs.so later in the build.

Actual Behavior

Dune runs a command like the following:

(cd _build/default && /usr/bin/gcc -g \
  -I /usr/lib/ocaml -I /home/droyo/.opam/default/lib/bigarray-compat \
  -I /home/droyo/.opam/default/lib/ctypes \
  -I /home/droyo/.opam/default/lib/integers \
  -I /home/droyo/.opam/default/lib/stdlib-shims \
  -o libmnl__c_cout_generated_functions__c_stub__libmnl.o \
  -c libmnl__c_cout_generated_functions__c_stub__libmnl.c )

note the lack of -fPIC. In my example, this does not cause a problem on its own, because the relocations that gcc generates are not deemed incompatible with dynamic linking by gcc:

$ objdump -r _build/default/libmnl__c_cout_generated_functions__c_stub__libmnl.o
_build/default/libmnl__c_cout_generated_functions__c_stub__libmnl.o:     file format elf64-x86-64
RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
000000000000001c R_X86_64_PLT32    mnl_socket_open-0x0000000000000004
000000000000002c R_X86_64_PLT32    caml_copy_nativeint-0x0000000000000004

However, if I patch dune to enable use of the return_errno policy, and use it, the generated c code now requires a R_X86_64_PC32 relocation for Caml_state:

$ objdump -r _build/default/mnl/libmnl__c_cout_generated_functions__c_stub__libmnl.o
RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE
0000000000000015 R_X86_64_PC32     Caml_state-0x0000000000000004

And then compilation fails with the error:

gcc -shared  -g -o dllmnl_stubs.so libmnl__c_cout_generated_functions__c_stub__libmnl.o
ld: libmnl__c_cout_generated_functions__c_stub__libmnl.o: relocation R_X86_64_PC32 against undefined symbol `Caml_state' can not be used when making a shared object; recompile with -fPIC

I can work around this issue with a vendored build_flags_resolver:

(build_flags_resolver
  (vendored
    (c_flags (:standard -fPIC))
    (c_library_flags (:standard -lmnl))))

Reproduction

  1. Checkout https://github.com/droyo/dune32-ctypes-fpic
  2. Install ctypes (dune might pull this in already)
  3. Run dune build
  4. Observe in _build/log that the -fPIC option is absent from the gcc command (or any other flags in :standard, really).

Specifications

  • Version of dune (output of dune --version): 3.2.0
  • Version of ocaml (output of ocamlc --version): reproduced on 4.13.1, 4.14.0
  • Operating system (distribution and version): Arch Linux, kernel 5.17.9, gcc 12.1.0
@rgrinberg rgrinberg added the c-bindings When dune is trying to interop with C label Jun 2, 2022
@rgrinberg
Copy link
Member

cc @mbacarella

@mbacarella
Copy link
Collaborator

mbacarella commented Jun 2, 2022

Hmm, should the ctypes stuff be compiled using the value in ocamlc_cflags from the output of ocamlc -config to run cc? On Linux this includes -fPIC, but does not on Darwin.

EDIT: or, rather, whatever corresponds to native_c_compiler from ocamlc -config? On Linux this says:

gcc -O2 -fno-strict-aliasing -fwrapv -fPIC  -D_FILE_OFFSET_BITS=64 -D_REENTRANT 

Darwin

cc -O2 -fno-strict-aliasing -fwrapv -pthread   -D_FILE_OFFSET_BITS=64

@mbacarella
Copy link
Collaborator

Anyway, I believe the problem here is in Ctypes_stubs.add
https://github.com/ocaml/dune/blob/main/src/dune_rules/ctypes_stubs.ml#L33-L37

Ideally instead of replacing flags with the contents of cflags.sexp, we can first prepend Ordered_set_lang.standard and then append cflags.sexp to that.

Is there a clean way to do this? The interface doesn't expose such functions. I wonder if this is a design decision on purpose or if it's fine to add something like an Ordered_set_lang.Unexpanded.standard_with_append?

@rgrinberg
Copy link
Member

The interface doesn't expose such functions. I wonder if this is a design decision on purpose or if it's fine to add something like an Ordered_set_lang.Unexpanded.standard_with_append?

Feel free to extend the interface as you wish to the fix the bug.

@mbacarella
Copy link
Collaborator

@droyo can you try #5816? I couldn't reproduce the relocation error but dune at least includes -fPIC in my logs now.

@droyo
Copy link
Contributor Author

droyo commented Jun 3, 2022

@mbacarella #5816 solves my problem; the stubs are compiled with -fPIC (and the rest of :standard) and I no longer get the reolcation error.

kit-ty-kate pushed a commit to ocaml/opam-repository that referenced this issue Jun 17, 2022
…ne-site, dune-rpc, dune-rpc-lwt, dune-private-libs, dune-glob, dune-configurator, dune-build-info, dune-action-plugin and chrome-trace (3.3.0)

CHANGES:

- Sandbox preprocessing, lint, and dialect rules by default. All these rules
  now require precise dependency specifications (ocaml/dune#5807, @rgrinberg)

- Allow list expansion in the `pps` specification for preprocessing (ocaml/dune#5820,
  @Firobe)

- Add warnings 67-69 to dune's default set of warnings. These are warnings of
  the form "unused X.." (ocaml/dune#5844, @rgrinbreg)

- Introduce project "composition" for coq theories. Coq theories in separate
  projects can now refer to each other when in the same workspace (ocaml/dune#5784,
  @Alitzer, @rgrinberg)

- Fix hint message for ``data_only_dirs`` that wrongly mentions the unknown
  constructor ``data_only`` (ocaml/dune#5803, @lambdaxdotx)

- Fix creating sandbox directory trees by getting rid of buggy memoization
  (@5794, @rgrinberg, @snowleopard)

- Handle directory dependencies in sandboxed rules. Previously, the parents of
  these directory dependencies weren't created. (ocaml/dune#5754, @rgrinberg)

- Set the exit code to 130 when dune is terminated with a signal (ocaml/dune#5769, fixes
  ocaml/dune#5757)

- Support new locations of unix, str, dynlink in OCaml >= 5.0 (ocaml/dune#5582, @dra27)

- The ``coq.theory`` stanza now produces rules for running ``coqdoc``. Given a
  theory named ``mytheory``, the directory targets ``mytheory.html/`` and
  ``mytheory.tex/`` or additionally the aliases `@doc` and `@doc-latex` will
  build the HTML and LaTeX documentation repsectively. (ocaml/dune#5695, fixes ocaml/dune#3760,
  @Alizter)

- Coq theories marked as `(boot)` cannot depend on other theories
  (ocaml/dune#5867, @ejgallego)

- Ignore `bigarray` in `(libraries)` with OCaml >= 5.0. (ocaml/dune#5526, fixes ocaml/dune#5494,
  @moyodiallo)

- Start with :standard when building the ctypes generated foreign stubs so that
  we include important compiler flags, such as -fPIC (ocaml/dune#5816, fixes ocaml/dune#5809).
@rgrinberg rgrinberg added this to the 3.3.0 milestone Jun 18, 2022
@rr0gi
Copy link

rr0gi commented Nov 8, 2023

looks like this issue is back in dune 3.11.1 at least
(same workaround works, thanks @droyo)
PS and I was surprised to see dune calls gcc directly, I believe it should be calling native_c_compiler as mentioned above

rr0gi added a commit to ahrefs/ocaml-cudajit that referenced this issue Nov 8, 2023
@kit-ty-kate kit-ty-kate reopened this Nov 8, 2023
@rgrinberg rgrinberg removed this from the 3.3.0 milestone Nov 10, 2023
@droyo
Copy link
Contributor Author

droyo commented Nov 29, 2023

looks like this issue is back in dune 3.11.1 at least

would you mind sharing reproduction steps? I upgraded to dune 3.11.1 and updated my reproduction, but the gcc command building the object file includes -fPIC:

> dune --version
3.11.1
> dune build
> grep cout_generated_functions _build/log
$ (cd _build/default && ./libmnl__function_gen__C_stub__Libmnl.exe c libmnl_stubs) > _build/default/libmnl__c_cout_generated_functions__C_stub__Libmnl.c
$ (cd _build/default && /usr/bin/gcc -O2 -fno-strict-aliasing -fwrapv -pthread -g -fno-omit-frame-pointer -fPIC -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -g -ffile-prefix-map=/build/ocaml/src=/usr/src/debug/ocaml -flto=auto -ffat-lto-objects -D_FILE_OFFSET_BITS=64 -fdiagnostics-color=always -I /usr/lib/ocaml -I /home/droyo/.opam/default/lib/bigarray-compat -I /home/droyo/.opam/default/lib/ctypes -I /home/droyo/.opam/default/lib/ctypes/stubs -I /home/droyo/.opam/default/lib/integers -I /home/droyo/.opam/default/lib/stdlib-shims -I /usr/lib/ocaml/str -o libmnl__c_cout_generated_functions__C_stub__Libmnl.o -c libmnl__c_cout_generated_functions__C_stub__Libmnl.c)
$ (cd _build/default && /usr/bin/ocamlmklib.opt -g -o mnl_stubs libmnl__c_cout_generated_functions__C_stub__Libmnl.o)

And using the errno_policy return_errno directive in my function_description section, which originally triggered build failures, seems to work fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c-bindings When dune is trying to interop with C
Projects
None yet
5 participants