Create opam switch specifying custom C compiler

Hello,
On my system, I have both gcc and clang installed. I would like to set up an opam switch where the ocaml compiler is built with clang. I tried the following:

opam source ocaml.4.14.1

Modified the downloaded opam file to set the CC environment variable, like so:

...
setenv: [
  [CAML_LD_LIBRARY_PATH = "%{_:stubsdir}%"]
  [CAML_LD_LIBRARY_PATH += "%{lib}%/stublibs"]
  [OCAML_TOPLEVEL_PATH = "%{toplevel}%"]
  [CC = "clang"]
  [CPP = "clang"]
]
...
opam switch create 4.14.1+clang --empty
opam install ./ocaml.4.14.1/opam

After the compiler gets built, when I run ocamlopt -config, I see that it was built with gcc:
c_compiler: gcc. Is this a bug? How can I create an opam switch with my choice of C compiler?

1 Like

It’s simpler than I thought. I found the following to work:
env CC=clang opam switch create 4.14.1+clang 4.14.1

2 Likes

What are the benefits of doing this?

I needed this specifically for a project that uses bindings to the Objective-C runtime. On Linux I’m only able to make it work when binding to the newer Objective-C runtime which is intended to be used with clang.

What approach would you recommend for indicating in the opam file that setting up the switch with clang is a prerequisite for installing the package? There is a conf-clang package in opam, but it only makes sure clang is installed on the system.

One way would to have an ocaml-option-clang package that indicates (or requests, depending on how you see it) that the C compiler is a kind of clang. But that might be tricky to do because it requires changing how the ocaml-variants+options package works and this option might not compose well with the others.

(to answer your initial question, setenv: sets up environment variables in the opam switch once a package is installed, which is a different feature)

1 Like

Since I did considerable work on exactly this topic for my bazel build of the compilers I’ll throw a few possibly irrelevant cents. A compiler build records the c compiler (and linker?) used for the build. When you use the compiler… Well you can’t really do that, you can only use the cmd processors, which drive the compiler and possibly other tools. Which may involve calling out to the tools (c compiler, linker) used to build the OCaml tools.

That’s good enough in almost all cases but it does compromise hermeticity unless the full paths to the c compiler and linker are recorded. If not, what happens if you are working with multiple versions of the c toolchain? The ocamlopt cmd might call clang and ld; what it gets depends on your env config.

Not a big deal I reckon but kind of a fun problem.

For me the env CC= method suggested above does not work. When I run ´ocamlopt -config` afterwards, I still have:

ccomp_type: cc
c_compiler: cc

regardless of what I set CC to. There are also some hints in the internet that opam has its ways to determine the C compiler, but I couldn’t find any documentation on what these ways would be. I guess what would work is supplying a config file during switch creation.

P.S.: looking into switch config files it is not clear to me what I would set there. opam var does not contain anything which seems to be aligned with the c_compiler config of ocamlopt.

Looking at the ocamlc opam files, it appears that “CC=cc” is hard coded on MacOS and BSD - which is not nice. On other platforms it might work to set the CC environment variable.

See opam-repository/packages/ocaml-variants/ocaml-variants.4.14.2+options/opam at 1d393046209a3bf9a41284cde888d54879545c5e · ocaml/opam-repository · GitHub

I would suggest using opam source ocaml.4.14.2 to get the opam file locally, remove the hardcoded CC=cc, and try the env CC=your-compiler ... method. For me it worked on Linux.

@borsid: I maintain Coq Platform - an opam based setup for the Coq proof assistant - and looking for a method which can be deployed to a few 1000 people, so things are a bit tricker for me. But since Coq Platform anyway has a local opam patch repo, i will probably follow the method you suggested - other methods all have severe drawbacks.

Does anyone know why the “CC=cc” configure option on macOS is needed? Would it be acceptable to make it conditional, eg:

"CC=cc" {!ocaml-option-custom-cc:installed & (os="openbsd"|os="macos")}

@borisd : I made a lot of experiments the last weeks and dont’t see a reason why one would treat MacOS differently from other OSes here. Maybe this is required for openbsd. On MacOS, if Xcode is installed - which is pretty much a requirement since afaik there is no open source version of the MacOS SDK - cc, gcc, clang all wrap the same compiler.

1 Like