(OCamlfind) build library with dependencies to Core - ocaml

I'm trying to build a small library that has dependencies to Core and Core_extended. I followed the instructions under Where to place a shared utility module in OCaml? and installed the library in ocamlfind (declaring a dependency to Core_extended and Core in the META-file).
Using it in the top-level works fine now.
However, when I try to build a test-file using this library, it doesn't detect the dependencies to Core and Core_extend automatically. Using these compile instructions
ocamlfind ocamlopt -c -g -package my_lib -thread -o file.cmx file.ml
ocamlfind ocamlopt -g -linkpkg -package my_lib -thread file.cmx -o file.native
I get the following error:
Error: No implementations provided for the following modules:
Core referenced from /.../mylib.cmx
Core_extended referenced from /.../mylib.cmx
If I compile the file using the extra arguments "-package core_extended" then it compiles, however this is quite impractical.
Is there a way to make this dependency transparent to the compilation-process, such that "-package my_lib" automatically loads in Core and Core_extended?
EDIT:
This is the content of my META-file:
name="my_lib"
description="small library"
version="0.1"
depends="core,core_extended"
archive(byte)="my_lib.cmo"
archive(native)="my_lib.cmx"
EDIT2:
Renaming "depends" to "requires" in the META-file fixed this!

You should write requires instead of depends

Related

How to separate binary code from source in ocaml?

I have my source next to a build directory
ocamlc -c file1.ml
ocamlc -c file2.ml
…
ocamlc -o main.ml ….cmo
I have the source with the file generated by the compilation.
I would like an option of ocamlc that enable me to have this file in the build directory.
I know i can do ocamlc -o build/main.ml .....cmo but i would like to have to .cmo in the build directory too
Thank you for your help
The answer of your main question is very simple:
in order to put the main binary of your OCaml application in the build folder, you just need to run:
ocamlc -o build/main.exe main.ml ….cmo
Indeed as indicated in the documentation (man ocamlc):
-o exec-file
Specify the name of the output file produced by the linker. The
default output name is a.out, in keeping with the Unix tradition. […]
However, doing all the build steps by hand in the way you are suggesting in your question may not be very effective (in particular, all .cmo files will stay along with the sources in the same folder).
To avoid this and facilitate the build of your OCaml project, I suggest using a build management tool for OCaml, for example one of the four tools mentioned in the end of the tutorial Compiling OCaml Projects:
ocamlbuild
GNU make
OMake
Oasis
(ocamlbuild is probably the easiest tool to use among the four.)
But you may also consider using Dune (formerly known as JBuilder), which is the build system used by a majority of packages in opam.

OCaml: how to solve findlib warnings of multiple `cmi`s

Now I try to write a compiler using ocamlfind and some packages, especially ppx_sexp_conv with opam.
Somehow dependencies of ppx_sexp_conv require compiler-libs so the compilation option -I ~/.opam/VERSION/lib/compiler-libs is added when compiling files by ocamlfind ocamlc -package ppx_sexp_conv.
The problem is, compiler-libs includes very common name files like parsing.cmi, main.cmi, lexing.cmi.
This make conflicts of .cmi files and make many noisy warnings as follows:
$ ocamlfind ocamlc -package ppx_sexp_conv -c parser.mli
findlib: [WARNING] Interface main.cmi occurs in several directories: ., /home/nomaddo/.opam/4.02.3/lib/ocaml/compiler-libs
findlib: [WARNING] Interface lexer.cmi occurs in several directories: ., /home/nomaddo/.opam/4.02.3/lib/ocaml/compiler-libs
findlib: [WARNING] Interface topdirs.cmi occurs in several directories: /home/nomaddo/.opam/4.02.3/lib/ocaml/compiler-libs, /home/nomaddo/.opam/4.02.3/lib/ocaml
findlib: [WARNING] Interface parser.cmi occurs in several directories: ., /home/nomaddo/.opam/4.02.3/lib/ocaml/compiler-libs
```
Note that main.cmi, parsing.cmi, lexing.cmi and main.cmi exist in the same directory.
I believe that such file names are common and everybody want to use.
My question is, how to quiet such noisy warnings.
Thanks to them, it is hard to find more important warnings and errors immediately...
My environment: ocaml 4.02.3 with opam 1.2.2.
One way to suppress those warnings is to set findlib environment variable OCAMLFIND_IGNORE_DUPS_IN to /home/nomaddo/.opam/4.03.0/lib/ocaml/compiler-libs.
Here is an example with OCaml 4.03.0 and ppx_sexp_conv version 113.33.01+4.03.
parser.mli:
type t = int [##deriving sexp]
In shell, do the following
export OCAMLFIND_IGNORE_DUPS_IN=/home/nomaddo/.opam/4.03.0/lib/ocaml/compiler-libs
ocamlfind ocamlc -package ppx_sexp_conv -dsource -c parser.mli
You can see the .mli is preprocessed and no extra warning is emitted.
Reference:
findlib man page
Mantis 6754

MirageOS - Unable to build unikernel for XEN

I've written a simple MirageOS-based Unikernel to execute a basic HTTP GET call. While it is working without any problems when I run it as a Unix binary, the moment I configure it for XEN (mirage configure --xen) and launch the make command, I get the following error:
ocamlbuild -use-ocamlfind -pkgs lwt.syntax,cohttp.lwt,cohttp.lwt-core,mirage-console.xen,mirage-http,mirage-types.lwt -tags "syntax(camlp4o),annot,bin_annot,strict_sequence,principal" -tag-line "<static*.*>: -syntax(camlp4o)" -cflag -g -lflags -g,-linkpkg,-dontlink,unix main.native.o
+ ocamlfind ocamlopt -g -linkpkg -dontlink unix -output-obj -package mirage-types.lwt -package mirage-http -package mirage-console.xen -package cohttp.lwt-core -package cohttp.lwt -package lwt.syntax -syntax camlp4o unikernel.cmx main.cmx -o main.native.o
File "_none_", line 1:
Error: No implementations provided for the following modules:
Unix referenced from /home/mirage/.opam/system/lib/lwt/lwt-unix.cmxa(Lwt_engine),
/home/mirage/.opam/system/lib/lwt/lwt-unix.cmxa(Lwt_unix),
/home/mirage/.opam/system/lib/lwt/lwt-unix.cmxa(Lwt_io),
/home/mirage/.opam/system/lib/lwt/lwt-unix.cmxa(Lwt_log),
/home/mirage/.opam/system/lib/ipaddr/ipaddr_unix.cmxa(Ipaddr_unix),
/home/mirage/.opam/system/lib/xenstore_transport/xenstore_transport_lwt_unix.cmxa(Xs_transport_lwt_unix_client),
/home/mirage/.opam/system/lib/conduit/conduit-lwt-unix.cmxa(Conduit_lwt_unix),
/home/mirage/.opam/system/lib/cohttp/cohttp_lwt_unix.cmxa(Cohttp_lwt_unix_debug),
/home/mirage/.opam/system/lib/cohttp/cohttp_lwt_unix.cmxa(Cohttp_lwt_unix)
Command exited with code 2.
Compilation unsuccessful after building 7 targets (0 cached) in 00:00:03.
make: *** [main.native.o] Error 10
I just started working with MirageOS and OCaml so it might be a stupid question but right now I really don't know what to do.
You should not use Cohttp_lwt_unix. As the name suggests, it runs on unix, not on xen. If you want an example of a webserver that is xen-proof, you can look at this skeleton or at the code used by mirage-seal.
As #Drup says, you need to avoid any "unix" packages if you want to be portable. Instead, use a Mirage adaptor for cohttp. This one should work:
https://github.com/mirage/mirage-http

OCaml: Reference to undefined global `A`

I have a three signatures A.mli,B.mli,and C.mli. Within them I have submodules Aa, Bb, and Cc respectively and also a signature for the implementations Ai, Bi, and Ci.
I have implemented them in a file called D.ml which looks like this
open A
open B
open C
module Ai : Aa = struct ... end
module Bi : Bb = struct ... end
module Ci : Cc = struct ... end
I compile them each in turn with the following commands:
ocamlfind ocamlc -linkpkg -thread -package core A.mli
ocamlfind ocamlc -linkpkg -thread -package core B.mli
ocamlfind ocamlc -linkpkg -thread -package core C.mli
ocamlfind ocamlc -linkpkg -thread -package core D.ml
which all succeed.
I then have a file E.ml where I try to use the modules Ai, Bi, Ci.
open A
open B
open C
module M = Ai(Ci)
(* do something else *)
However when I try to compile E.ml I get the
Error: Error while linking E.cmo:
Reference to undefined global `A`
I think I have to somehow include D.ml in the compilation step but I'm unsure how to.
Using ocamlc or ocamlopt compiler directly (even with the help of ocamlfind) is not an easy task, and should be left only for those, who write OCaml tools and very sure in what they're doing. So, in short, just use ocamlbuild, that is the default way of compiling things in OCaml world. Since, you're using Core library it would be also a good idea to use corebuild instead of ocamlbuild. corebuild is shipped with core, and is actually a small wrapper around ocamlbuild, that adds core dependencies, as well as some handy flags. So, with corebuild you can compile just with:
corebuild E.native
Without corebuild, you can compile with
ocamlbuild -pkg core E.native
ocamlbuild will do all the work for you, i.e., find all dependencies, sort them in correct order, invoke proper tools, etc... You just need this one, command.
If you're still interested in how to compile your example project properly, then you can ask ocamlbuild about this. Use -classic-display option, that will show you all intermediate commands,
ocamlbuild -use-ocamlfind -classic-display -pkg core E.byte
Will show you all steps. (You may need to ocamlbuild -clean, so that you can see all the steps from the start).

How to use modules with js_of_ocaml?

I am currently working on a website project written in OCaml and compiled to javascript using js_of_ocaml. It works pretty well as long as I have only one source file using the command ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml.syntax -syntax camlp4o -linkpkg -o file.byte file.ml but I would like to include several modules in my project. How can I do that ?
The other modules are actually a lexer and a parser poduced by ocamllex and menhir. I have read a tutorial on how to use ocamllex and menhir with js_of_ocaml but it makes wrong assumptions on where js_of_ocaml is installed (I installed it with opam) and it uses ocamlbuild and I want to know how to do it by hand without using an automated tool such as ocamlbuild.
I found the solution by trying to understand the makefiles for the official examples.
Here is my Makefile :
OBJS=file1.cmo file2.cmo file3.cmo
NAME=projectname
OCAMLC=ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml.syntax -syntax camlp4o
$(NAME).byte: $(OBJS)
$(OCAMLC) -linkpkg -o $# $(OBJS)
$(NAME).js: $(NAME).byte
js_of_ocaml $<
%.cmo: %.ml
$(OCAMLC) -c $<
...
ocamlbuild keeps a log of the operations it performs. After an ocamlbuild call, look at _build/_log and you will see all the commands that it has invoked, with full arguments etc. That's probably the easiest way for you to figure how to do it by hand.
(Regarding +site-lib assumptions and OPAM, that's something you should report to the authors of the tutorial, they'll want to make sure that it also works for OPAM users.)
It's taken a bunch of experimentation, but I finally figured out how to have ocamlbuild pass the same flags to ocamlfind as ocsigen use in those makefiles. I'm also using js_of_ocaml installed with OPAM.
For my test case, I created a very small example with two files - main.ml and square.ml.
square.ml:
let square x = x * x
main.ml:
let () = (Js.Unsafe.coerce Dom_html.window)##square <- Js.wrap_callback Square.square
The command to build this successfully:
ocamlbuild -use-ocamlfind -pkgs js_of_ocaml,js_of_ocaml.syntax -syntax camlp4o main.byte
This produces identical JS output to my initial test case where the square function was in main.ml. The ocamlbuild log shows exactly what I expect (two calls to ocamldep, two to ocamlc -c, one to ocamlc -linkpkg).