Files <file> and <the same file> both define a module named Unix

If I give ocamlbuild only the name of my target executable “phoebe.native”, the build fails because the Unix library isn’t included. If I add “-lib unix”, then the remaining part of the build completes. But if I include “-lib unix” when I’m doing a build from scratch, ocamlbuild complains that the Unix module is being defined twice. How can I get a clean build in one step?

~/Documents/Work/Code/Phoebe/compiler: ocamlbuild phoebe.native
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt unix.cmxa -I /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild/ocamlbuildlib.cmxa myocamlbuild.ml /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules phoebe.ml > phoebe.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules error.ml > error.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamllex.opt -q lex.mll
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules lex.ml > lex.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules ast.ml > ast.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o error.cmo error.ml
menhir --raw-depend --ocamldep '/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules' grammar.mly > grammar.mly.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o ast.cmo ast.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules parse.ml > parse.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules symbol.ml > symbol.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules utility.ml > utility.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o utility.cmo utility.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o symbol.cmo symbol.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o parse.cmo parse.ml
menhir --ocamlc '/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -g' --infer grammar.mly
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules grammar.mli > grammar.mli.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o grammar.cmi grammar.mli
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules verilog.ml > verilog.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o lex.cmo lex.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o verilog.cmo verilog.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlc.opt -c -g -o phoebe.cmo phoebe.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o error.cmx error.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamldep.opt -modules grammar.ml > grammar.ml.depends
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o ast.cmx ast.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o utility.cmx utility.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o symbol.cmx symbol.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o parse.cmx parse.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o grammar.cmx grammar.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o lex.cmx lex.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o verilog.cmx verilog.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -c -g -o phoebe.cmx phoebe.ml
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -g error.cmx ast.cmx utility.cmx symbol.cmx parse.cmx grammar.cmx lex.cmx verilog.cmx phoebe.cmx -o phoebe.native
+ /Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt -g error.cmx ast.cmx utility.cmx symbol.cmx parse.cmx grammar.cmx lex.cmx verilog.cmx phoebe.cmx -o phoebe.native
File "_none_", line 1:
Error: No implementations provided for the following modules:
         Unix referenced from utility.cmx
Command exited with code 2.
~/Documents/Work/Code/Phoebe/compiler: ocamlbuild -lib unix phoebe.native
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt unix.cmxa -g error.cmx ast.cmx utility.cmx symbol.cmx parse.cmx grammar.cmx lex.cmx verilog.cmx phoebe.cmx -o phoebe.native
~/Documents/Work/Code/Phoebe/compiler: rm _build/*
zsh: sure you want to delete all 67 files in /Users/Tim_1/Documents/Work/Code/Phoebe/compiler/_build [yn]? y
~/Documents/Work/Code/Phoebe/compiler: ocamlbuild -lib unix phoebe.native
ocamlbuild -lib unix phoebe.native
/Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt unix.cmxa -I /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild/ocamlbuildlib.cmxa unix.cmxa myocamlbuild.ml /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
+ /Users/Tim_1/.opam/4.12.0/bin/ocamlopt.opt unix.cmxa -I /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild/ocamlbuildlib.cmxa unix.cmxa myocamlbuild.ml /Users/Tim_1/.opam/4.12.0/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
File "myocamlbuild.ml", line 1:
Error: Files /Users/Tim_1/.opam/4.12.0/lib/ocaml/unix.cmxa
       and /Users/Tim_1/.opam/4.12.0/lib/ocaml/unix.cmxa
       both define a module named Unix
Command exited with code 2.
~/Documents/Work/Code/Phoebe/compiler:

Just fyi, ocamlbuild is effectively deprecated and the replacement is dune. Whenever possible, projects should migrate to dune. Dune is generally better at taking care of build dependencies like this, and can handle menhir too: Stanza reference — dune documentation

This is ocamlopt’s obscure way to tell you that unix.cmxa is linked twice, while it should be linked only once.

Why does ocamlbuild decides to link unix.cmxa twice? No idea, but it may be time to switch to another build system, as @yawaramin suggested.

2 Likes

I considered switching to Dune but was put off by its poorly organized documentation. (Many terms are used before they’re defined, and some are never adequately defined.) I can switch to Dune if I must, but I’d hoped to avoid spending time doing that.

1 Like

It would help a lot if you would file an issue against the dune docs repo pointing out what was unclear or undefined. Nothing can improve if no one takes the first step :slightly_smiling_face:

4 Likes