dune icon indicating copy to clipboard operation
dune copied to clipboard

Dune builds C stubs with `bytecode_cflags` and never `native_cflags`

Open OlivierNicole opened this issue 8 months ago • 6 comments

Expected Behavior

Among the default flags for building C stubs, Dune should use OCaml’s bytecode_cflags for stubs destined to bytecode and native_cflags for stubs destined to native executables.

Actual Behavior

Dune always uses bytecode_cflags. This can cause crashes when using ThreadSanitizer ^1—and probably has ^2^3.

Reproduction

On a switch with ThreadSanitizer enabled (opam switch create test-switch --packages=ocaml-variants.5.3.0+options,ocaml-option-tsan), bytecode and native cflags differ, and it is easy to see that Dune only uses bytecode cflags:

$ ocamlc -config
version: 5.3.0
standard_library_default: /home/olivier/.opam/5.3.0+tsan/lib/ocaml
standard_library: /home/olivier/.opam/5.3.0+tsan/lib/ocaml
ccomp_type: cc
c_compiler: gcc
bytecode_cflags: -O2 -fno-strict-aliasing -fwrapv -fPIC -pthread
ocamlc_cflags: -O2 -fno-strict-aliasing -fwrapv -fPIC -pthread
bytecode_cppflags:  -D_FILE_OFFSET_BITS=64
ocamlc_cppflags:  -D_FILE_OFFSET_BITS=64
native_cflags: -O2 -fno-strict-aliasing -fwrapv  -fsanitize=thread -Wno-tsan --param=tsan-distinguish-volatile=1 -pthread
ocamlopt_cflags: -O2 -fno-strict-aliasing -fwrapv  -fsanitize=thread -Wno-tsan --param=tsan-distinguish-volatile=1 -pthread
...

$ cat dune
(library
 (name test)
 (foreign_stubs
   (language c)
   (flags (:standard))
   (names stubs))
)

$ dune build --verbose
...
Running[6]: (cd _build/default/lib && /nix/store/f0m6caffiykyvsjim9376a3hx2yj2ghj-gcc-wrapper-14.2.1.20250322/bin/gcc -O2 -fno-strict-aliasing -fwrapv -fPIC -pthread -D_FILE_OFFSET_BITS=64 -Wall -fdiagnostics-color=always -g -I /home/olivier/.opam/5.3.0+tsan/lib/ocaml -o stubs.o -c stubs.c)
...

Specifications

  • Version of dune (output of dune --version): 3.19.0
  • Version of ocaml (output of ocamlc --version): 5.3.0
  • Operating system (distribution and version): NixOS 25.05

OlivierNicole avatar Jun 17 '25 12:06 OlivierNicole

As a temporary workaround for TSan users, is there a way to alter the CFLAGS used by Dune using an environment variable, or something similar?

OlivierNicole avatar Jun 17 '25 12:06 OlivierNicole

Since we don't support foreign stubs with bytecode, we probably should be using OCaml_config.ocamlopt_flags rather than OCaml_config.ocamlc_flags in src/dune_rules/foreign_rules.ml. cc @rgrinberg WDYT?

let default_context_flags (ctx : Build_context.t) ocaml_config ~project =
  let cflags = Ocaml_config.ocamlc_cflags ocaml_config in
  let c, cxx =
    let cxxflags =

Alizter avatar Jun 17 '25 12:06 Alizter

Since we don't support foreign stubs with bytecode

What do you mean by that? I think C stubs work just fine in bytecode; they are built into a shared library.

nojb avatar Jun 17 '25 12:06 nojb

@nojb I may be mistaken. That was the impression I got from trying to reproduce https://github.com/ocaml/dune/issues/108. I don't know much about bytecode executables however.

Alizter avatar Jun 17 '25 12:06 Alizter

That was the impression I got from trying to reproduce #108.

There are recurring issues that users report regarding bytecode + C stubs which are due to the fact that one needs to tell the OCaml runtime where to find the shared library containing the stubs (typically by setting CAML_LD_LIBRARY_PATH) when runningthe bytecode executable, but that is a different question. Otherwise, C stubs in bytecode work just fine.

On the other hand, and more relevant to this issue, I believe to do what is being asked for here we would need to build C stubs twice (once for bytecode, once for native-code). There is already support for doing so (cf #5649), but it is opt-in; by default the same C stubs are shared between bytecode and native-code.

nojb avatar Jun 17 '25 12:06 nojb

Ah, that’s good to know; then it shouldn’t be too much work to always build them separately, and use ocamlopt_cflags for the native version.

OlivierNicole avatar Jun 17 '25 13:06 OlivierNicole