ocaml / Zarith

The Zarith library implements arithmetic and logical operations over arbitrary-precision integers and rational numbers. The implementation, based on GMP, is very efficient.
Other
231 stars 70 forks source link

gmp.h not found when compiling with `4.11.1+musl+static+flambda` #77

Closed mseri closed 4 years ago

mseri commented 4 years ago

On ubuntu-20.04 (x86_64) with the 4.11.1+musl+static+flambda zarith fails to build: caml_z.c:32:10: fatal error: gmp.h: No such file or directory. (libgmp-dev is installed and vanilla 4.11.1 works fine)

#=== ERROR while compiling zarith.1.10 ========================================#
# context              2.0.7 | linux/x86_64 | ocaml-variants.4.11.1+musl+static+flambda | git+https://github.com/ocaml/opam-repository.git
# path                 ~/.opam/4.11.1+musl+static+flambda/.opam-switch/build/zarith.1.10
# command              ~/.opam/opam-init/hooks/sandbox.sh build make
# exit-code            2
# env-file             ~/.opam/log/zarith-14525-ab7083.env
# output-file          ~/.opam/log/zarith-14525-ab7083.out
### output ###
# [...]
# ocamlc -I +compiler-libs -bin-annot  -c q.mli
# ocamlc -I +compiler-libs -bin-annot  -c q.ml
# ocamlc -I +compiler-libs -bin-annot  -c big_int_Z.mli
# ocamlc -I +compiler-libs -bin-annot  -c big_int_Z.ml
# ocamlmklib -failsafe -o zarith z.cmo q.cmo big_int_Z.cmo -lgmp
# gcc -DZ_OCAML_HASH -DZ_OCAML_COMPARE_EXT -DHAS_GMP -DZ_ELF -DZ_DOT_LABEL_PREFIX     -c -o caml_z_x86_64.o caml_z_x86_64.S
# ocamlc -ccopt "-I/home/runner/.opam/4.11.1+musl+static+flambda/lib/ocaml  -DZ_OCAML_HASH -DZ_OCAML_COMPARE_EXT -DHAS_GMP -DZ_ELF -DZ_DOT_LABEL_PREFIX  -O3 -Wall -Wextra " -c caml_z.c
# caml_z.c:32:10: fatal error: gmp.h: No such file or directory
#    32 | #include <gmp.h>
#       |          ^~~~~~~
# compilation terminated.
# make: *** [project.mak:142: caml_z.o] Error 2
xavierleroy commented 4 years ago

I suspect the 4.11.1+musl+static+flambda configuration uses musl-gcc as its C compiler. What happens if you put

#include <gmp.h>

in file x.c and do

musl-gcc -c x.c

?

mseri commented 4 years ago

I see the same failure:

x.c:1:10: fatal error: gmp.h: No such file or directory
    1 | #include <gmp.h>
      |          ^~~~~~~
compilation terminated.

The output of pkg-config --cflags --libs gmp is just -lgmp, but it fails in the same way also with musl-gcc -lgmp -c x.c

xavierleroy commented 4 years ago

OK, thanks for running the test. It shows that the problem is not in Zarith nor in OCaml, but with a bad interaction between the Musl and GMP packages on your system. Maybe there's a "GMP for Musl" package? At any rate, you'd better ask on your Linux distribution support channels, or on Stack Overflow, because none of the Zarith maintainers can help you here.

mro commented 2 years ago

@xavierleroy I just tried to apply the recipe of @nberth (mlgmpidl) to zarith here – without success.

I guess https://github.com/ocaml/Zarith/blob/master/zarith.opam is the culprit – it sets explicit include paths and doesn't care about the prefix, does it?

https://github.com/nberth/mlgmpidl/blob/master/opam/opam looks quite different and works ok.

Do you want to have a look?

xavierleroy commented 2 years ago

I guess https://github.com/ocaml/Zarith/blob/master/zarith.opam is the culprit – it sets explicit include paths and doesn't care about the prefix, does it?

I didn't write this OPAM script, but, yes, it assumes default locations.

What is this "prefix" you're talking about?

Do you want to have a look?

I see 500+ lines of shell scripting for the ./configure script, so, no, I'm not going to read all of that.

Can you summarize the gist of mlgmpidl's approach?

mro commented 2 years ago

What is this "prefix" you're talking about?

in order to use gmp from a musl+static switch, @nberth builds the gmp binary (in above recipe) to a separate location:

$ cd gmp-6.2.1; CC=musl-gcc ./configure --prefix /tmp/gmp-prefix && make && make install

and instructs opam to use it like

$ MPFR_PREFIX=/tmp/gmp-prefix GMP_PREFIX=/tmp/gmp-prefix opam install mlgmpidl

I see 500+ lines of shell scripting for the ./configure script

@antoinemine, can you comment on the zarith configure script?

Can you summarize the gist of mlgmpidl's approach?

frankly, I have no idea, @nberth could you please help a hand?

What puzzles me a bit, is that @nberth s approach seems to encapsulate gmp into a ocaml wrapper/dependency while zarith embeds it directly. Maybe zarith could just use @nberth s wrapper lib mlgmpidl as a dependency instead of embedding gmp directly?

antoinemine commented 2 years ago

@antoinemine, can you comment on the zarith configure script?

There is not much to say about the configuration script. Please run "./configure --help" for some basic information. You can add non-standard locations with CPPFLAGS="-Iinclude-path" LDFLAGS="-Llibrary-path", as hinted in the --help. I think that this should be sufficient, if the non-standard location is the only problem.

What puzzles me a bit, is that @nberth s approach seems to encapsulate gmp into a ocaml wrapper/dependency while zarith embeds it directly.

Sorry, I don't understand what this means. They opam files and approaches look very similar to me.

Maybe zarith could just use @nberth s wrapper lib mlgmpidl as a dependency instead of embedding gmp directly?

Adding an unneeded dependency does not seem a good idea. I am not sure how it would solve the problem. zarith still needs to find the gmp C library, the same way mlgmpidl does. In both cases, this may require adding arguments to the ./configure script, just not the same ones.

nberth commented 2 years ago

in order to use gmp from a musl+static switch, @nberth builds the gmp binary (in above recipe) to a separate location:

$ cd gmp-6.2.1; CC=musl-gcc ./configure --prefix /tmp/gmp-prefix && make && make install

and instructs opam to use it like

$ MPFR_PREFIX=/tmp/gmp-prefix GMP_PREFIX=/tmp/gmp-prefix opam install mlgmpidl

The first step of building libgmp and libmpfr with musl-gcc is required for mlgmpidl and zarith alike. The second step above, however, instructs the configure script of mlgmpidl about where the MUSL versions of those libraries are to be found. A similar effect can be achieved by similarly tweaking the CFLAGS (and/or CPPFLAGS) and LDFLAGS environment variables.

What puzzles me a bit, is that @nberth s approach seems to encapsulate gmp into a ocaml wrapper/dependency while zarith embeds it directly. Maybe zarith could just use @nberth s wrapper lib mlgmpidl as a dependency instead of embedding gmp directly?

As far as the search for libraries are concerned, the only difference I see between mlgmpidl and zarith lies in the environment variables used: mlgmpidl's *_PREFIX's are custom and may just be slightly easier to use for such tweaks.

With libraries compiled and installed as in the example I gave here, I could install zarith perfectly fine just now with (as @antoinemine suggested):

CPPFLAGS=-I/tmp/gmp-prefix/include LDFLAGS=-L/tmp/gmp-prefix/lib opam install zarith