Note that this is a related to Statically Link
So we started a greenfield project at work using OCaml/Reason (we are mainly a Scala based team) and we have successfully deployed however we noticed an issue that we need some help in.
The issue comes across making executable that can run without any runtime C dependencies, we need this due to our CDP build system. Since OCaml produces native bytecode, you basically have to do static linking for the platform. To be clear, the libraries which contain C dependencies which we are trying to static link are ocaml-ssl (https://github.com/savonet/ocaml-ssl) which binds to the openssh library and also libev which is used by
There is a guide on how to do this here http://rgrinberg.com/posts/static-binaries-tutorial/ however the main issue is that global static linking (i.e. using
(flags (-ccopt -static))) doesn’t work on MacOS (note that MacOS perfectly supports static linking specific dependency, just not every dependency in your project). This leaves to solutions for us. Most of our developers use machines that have MacOS for local development, however in production we deploy docker containers which run linux.
- The ideal (or perfect) solution is to only statically link the
opensshlibrary on every platform. Unfortunately I haven’t managed to figure out how to do this using
-ccoptflags. These flags are directly passed into
ldhowever with a lot of searching I haven’t actually managed to figure out how to only statically link
libev(I know there is a
-lflag that can be passed into
ldto do this, but I didn’t manage to get it to work in an agnostic way. Furthermore it has the known issue that it will always pick up the dynamic
.solibraries over the static
.afiles, so you need a manual prepossessing step to deal with this.
- The less ideal solution is to allow you to build your project with an optional flag (i.e. something like
--static-linux) so that by default it uses dynamic libraries but in our build systems on linux we can just build with
--static-linux). The issue is I haven’t managed to figure this out with
duneunder the hood). Firstly someone on discord recommended me to use the
envstanza to conditionally add the
(flags (-ccopt -static))flags and then use
dunehowever the issue with this is that
-p(i.e. package flag) to build dune projects which can’t be mixed with
--profile. I also had issues just getting the
envcommand to work when running dune directly, i.e. if you have a trivial dune file as shown
(library (name lib) (public_name hello-ocaml) (libraries lambda-term lwt lwt_ssl))
Where would you put the
env stanza, i.e. would you put it here
(env (static-linux (flags (:standard -ccopt -static)))) (library (name lib) (public_name hello-ocaml) (libraries lambda-term lwt lwt_ssl))
(library (name lib) (env (static-linux (flags (:standard -ccopt -static)))) (public_name hello-ocaml) (libraries lambda-term lwt lwt_ssl))
Note that in this case I still have the issue that I cant do something like
dune build --profile=static-linux -p hello because the flags don’t mix.
Anyone have any recommendation on what to do here?