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
Related
I have this in a file named main.ml:
let () = JsooTop.initialize ()
I tried compiling the file using:
ocamlfind ocamlc -package js_of_ocaml -linkpkg -o main.byte main.ml
But this error appears:
File "main.ml", line 1, characters 9-27:
Error: Unbound module JsooTop
It appears that JsooTop is not present on my machine, so I ran opam install js_of_ocaml-toplevel, and tried compiling the file again using:
ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-toplevel -linkpkg -o main.byte main.ml
js_of_ocaml main.byte
But I get warnings:
Warnings from ocamlfind:
findlib: [WARNING] Interface topdirs.cmi occurs in several directories: /usr/lib/ocaml, /usr/lib/ocaml/compiler-libs
Warnings from the js_of_ocaml executable:
There are some missing primitives
Dummy implementations (raising 'Failure' exception) will be used if they are not available at runtime.
You can prevent the generation of dummy implementations with the commandline option '--disable genprim'
Missing primitives provided by +dynlink.js:
caml_add_debug_info
caml_dynlink_add_primitive
caml_dynlink_get_current_libs
caml_dynlink_lookup_symbol
caml_dynlink_open_lib
caml_remove_debug_info
Missing primitives provided by +toplevel.js:
caml_get_current_environment
caml_get_section_table
caml_invoke_traced_function
caml_realloc_global
caml_reify_bytecode
caml_static_alloc
caml_static_free
caml_static_release_bytecode
caml_terminfo_setup
My question is: what is the proper way to compile a file that uses the JsooTop module?
First, make sure that the required OPAM packages are present:
opam install js_of_ocaml js_of_ocaml-toplevel
To build a program that uses the JsooTop module, compile the file in this way:
ocamlfind ocamlc -package js_of_ocaml -package js_of_ocaml-toplevel -linkpkg -o main.byte main.ml
js_of_ocaml --toplevel --dynlink +dynlink.js +toplevel.js main.byte
Note the inclusion of --toplevel, --dynlink, +dynlink.js, and +toplevel.js. The commands above will produce a JavaScript file named main.js.
I'm attempting to build the xencat tool from this project. When I try to use ocamlopt to build it, I get
$ ocamlopt -o xencat xencat.ml
File "xencat.ml", line 1, characters 5-13:
Error: Unbound module Cmdliner
Following guidance here, I verified that cmdliner was installed and that it was visible to ocamlfind, and then tried again:
Here's what ocamlfind list shows:
$ ocamlfind list
bigarray (version: [distributed with Ocaml])
bytes (version: [distributed with OCaml 4.02 or above])
...
cmdliner (version: 0.9.8)
...
No luck:
$ ocamlfind ocamlopt -o xencat xencat.ml
File "xencat.ml", line 1, characters 5-13:
Error: Unbound module Cmdliner
Following this page, I tried ocamlbuild:
$ocamlbuild -use-ocamlfind xencat.byte
+ ocamlfind ocamlc -c -o xencat.cmo xencat.ml
File "xencat.ml", line 1, characters 5-13:
Error: Unbound module Cmdliner
Command exited with code 2.
Clearly I'm missing something, but being new to Ocaml, I don't know what else to try.
ocamlbuild -use-ocamlfind -package cmdliner xencat.byte
?
To build this project use the following command at the root of the project:
./configure
make build
You will find a xencat.native file in the root folder.
You can also use opam to build it, as opam will handle all dependencies to you. Just go to the root of the project and say:
opam pin add vchan .
and answer yes to whatever opam asks to do.
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).
Just beginning with ocaml and am struggling with the various compilers and tooling. E.g. ocamlopt, ocamlc, ocamlbuild, corebuild and so on. So, how do I compile the following?
open Core.Std
module Regex = Re2.Regex
let ls pattern =
let pat = Regex.create_exn pattern in
let matcher = Regex.matches pat in
Sys.ls_dir "."
|> List.filter ~f:matcher
|> List.iter ~f:(fun s -> print_string s; print_newline ())
let () =
match In_channel.input_line stdin with
| None -> print_string "No Input"
| Some pat -> ls pat
In utop I can just #require "re2" and go from there.
Without the inclusion of the regular expressions module I would just use corebuild ls.native, assuming that the above code is placed into ls.ml.
[edit]
Have so far tried
ocamlbuild -use-ocamlfind -package core -package re2
which spit out
ocamlfind ocamldep -package core -package re2 -modules ls.ml > ls.ml.depends
ocamlfind ocamlc -c -package core -package re2 -o ls.cmo ls.ml
+ ocamlfind ocamlc -c -package core -package re2 -o ls.cmo ls.ml
ocamlfind: Error from package `threads': Missing -thread or -vmthread switch
Command exited with code 2.
So after some googling I was led to this blog I tried
ocamlbuild -tag thread -use-ocamlfind -package core -package re2
which spits out over 6000 lines of what looks like make output before failing with:
collect2: error: ld returned 1 exit status
File "caml_startup", line 1:
Error: Error during linking
Command exited with code 2.
so I'm not sure what to try next.
I am using Ubuntu 14.04 on a 64bit machine. I ditched the apt-get versions of ocaml:
sudo apt-get remove --purge ocaml ocaml-base-nox ocaml-compiler-libs \
ocaml-interp ocaml-native-compilers \
ocaml-nox campl4 ocaml-base ocaml-docs opam
Then I installed opam from source according to the instructions here.
Next I installed core, utop, and re2 with opam install core utop re2
And finally I ran ocamlbuild -use-ocamlfind -package re2 -package core -tag thread ls.native
which built the desired executable.
I would suggest you to use oasis tool. It is not as hard, as one may think. But it removes all library burden from you.
Lets create a simple _oasis file for your project:
OASISFormat: 0.4
Name: ls
Version: 0.1
Synopsis: Testing oasis
Authors: Fizz_ed
License: MIT
Plugins: META (0.4), DevFiles (0.4)
BuildTools: ocamlbuild, camlp4o
BuildDepends: core, camlp4, threads,
sexplib.syntax,
bin_prot.syntax,
comparelib.syntax,
herelib,
herelib.syntax
Executable "ls"
Path: .
MainIs: ls.ml
CompiledObject: best
BuildDepends: re2
After you've created this file, run oasis setup command (if oasis is not installed, then install it using opam, or your package manager).
After that you will have a common configure script and makefiles. So all you need is to type
./configure
make
and your file will be compiled.
Or you can just use ocamlbuild directly, it will work too, since oasis created all the necessary files
ocamlbuild ls.native
A few explanations about the file. The preamle contains everything you need to build your core-style applications.
Executable section describes your executable file, and also adds a dependency to re2 library.
Update: fixed some issues.
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).