I'd like to pass the -S flag to ocamlopt when building with the ocamlbuild and corebuild commands.
I understand doing ocamlbuild -cflag -S ... won't work since -S flag does only exist for ocamlopt and not ocamlc.
How can I do this using _tags files?
Here's one way to do it using myocamlbuild.ml and _tags.
In myocamlbuild.ml, add a flag instruction to let ocamlbuild recognize a new tag - here keep_asm - which will enable -S for selected files when compiling to native:
flag ["ocaml";"compile";"native";"keep_asm"] (S [A "-S"]);
Without the "native" string in the list passed to flag, the flag would be enabled for any compilation stage using ocaml (as indicated by the strings "ocaml" and "compile"), and would trigger when ocamlc is invoked, which you don't want.
So, for a complete stand alone myocamlbuild.ml doing only the above, this would turn out as:
open Ocamlbuild_plugin;;
open Command;;
dispatch begin function
| Before_rules ->
begin
end
| After_rules ->
begin
flag ["ocaml";"compile";"native";"keep_asm"] (S [ A "-S"]);
end
| _ -> ()
end
Once, you've got that new tag defined, you may use it in your _tags file as with any other tag, for instance:
<myfile.ml>: use_bigarray, keep_asm
Related
I am currently using ocaml 4.06.0 and I am trying to use the Z3 sat solver. I am using opam's oasis to compile the files (which is building everything successfully). However, when I run the native code produced I am getting the following error: error while loading shared libraries: libz3.so. I tried reinstalling the z3 package but the error still persists. Can anyone help me solve this please because I have no idea what else to try?
Here is what I did just now to install z3 under Ubuntu 18.04.1:
$ opam depext conf-gmp.1
$ opam depext conf-m4.1
These installed gmp and m4 outside of opam. Pretty impressive.
$ opam install z3
Now the z3 library is installed so you can use it from OCaml code. But there are no executables installed (that I can find).
$ export LD_LIBRARY_PATH=~/.opam/4.06.0/lib/z3
$ ocaml -I ~/.opam/4.06.0/lib/z3
OCaml version 4.06.0
# #load "nums.cma";;
# #load "z3ml.cma";;
# let ctx = Z3.mk_context [];;
val ctx : Z3.context = <abstr>
The setting of LD_LIBRARY_PATH is what makes it possible to find libz3.so.
This is as far as I got for now. Maybe this will be helpful.
Update
Here is how I compiled and linked a test program.
$ export LD_LIBRARY_PATH=~/.opam/4.06.0/lib/z3
$ cat tz3.ml
let context = Z3.mk_context []
let solver = Z3.Solver.mk_solver context None
let xsy = Z3.Symbol.mk_string context "x"
let x = Z3.Boolean.mk_const context xsy
let () = Z3.Solver.add solver [x]
let main () =
match Z3.Solver.check solver [] with
| UNSATISFIABLE -> Printf.printf "unsat\n"
| UNKNOWN -> Printf.printf "unknown"
| SATISFIABLE ->
match Z3.Solver.get_model solver with
| None -> ()
| Some model ->
Printf.printf "%s\n"
(Z3.Model.to_string model)
let () = main ()
$ ocamlopt -I ~/.opam/4.06.0/lib/z3 -o tz3 \
nums.cmxa z3ml.cmxa tz3.ml
$ ./tz3
(define-fun x () Bool
true)
$ unset LD_LIBRARY_PATH
$ ./tz3
./tz3: error while loading shared libraries: libz3.so:
cannot open shared object file: No such file or directory
It works--i.e., it says that the trivial formula x can be satisfied by making x be true.
Note: initially I thought the setting of LD_LIBRARY_PATH wasn't necessary here. But in later testing I've found that it is necessary. So that is probably the key to your problem.
It's a little cumbersome and error prone to set LD_LIBRARY_PATH for running your programs. It's good enough for personal testing, but probably not for any kind of wider deployment. There are ways to set the search path for shared libraries at link time.
I hope this helps.
I want to parse command line options with arguments in OCaml.
The module Arg of the standard library seems to do everything I need and there are some tutorials which explain how to use this module.
My problem is, that they all seem to share the same strange behavior when the argument of an option is missing. For example, executing the program from this example with ./a.out -d produces the following output:
./a.out: option '-d' needs an argument.
usage: ./a.out [-b] [-s string] [-d int]
-b : set somebool to true
-s : what follows -s sets some string
-d : some int parameter
-help Display this list of options
--help Display this list of options
./a.out: ./a.out: option '-d' needs an argument.
usage: ./a.out [-b] [-s string] [-d int]
-b : set somebool to true
-s : what follows -s sets some string
-d : some int parameter
-help Display this list of options
--help Display this list of options
.
usage: ./a.out [-b] [-s string] [-d int]
-b : set somebool to true
-s : what follows -s sets some string
-d : some int parameter
-help Display this list of options
--help Display this list of options
I was not able to find out why the error/usage message is printed three times. This also happens to all the other code examples I found online. Is this a problem in the Arg module or is it somehow not used correctly in these examples?
I have managed to reproduce the bug with OCaml 4.04.2, but not with 4.02.3, so it would seem that there is some sort of regression going on there.
So, one thing you could do is sticking to an older version of OCaml, but I wouldn't recommend that.
Instead, you could use an alternative standard library, such as Jane Street's Core. It has a module named Command which allows you to write command-line interfaces just like the one you're trying to run.
An extensive tutorial for this module is available here.
As an example, here is the CLI from Rosetta using Command:
open Core
let spec =
let open Command.Spec in
empty
+> flag "-b" (no_arg) ~doc:"Sets some flag"
+> flag "-s" (optional_with_default "" string) ~doc:"STRING Some string parameter"
+> flag "-d" (optional_with_default 0 int) ~doc:"INTEGER Some int parameter"
let command =
Command.basic
~summary:"My awesome CLI"
spec
(fun some_flag some_string some_int () ->
printf " %b '%s' %d\n" some_flag some_string some_int
)
let () =
Command.run command
EDIT : This bug was known and is going to be fixed in OCaml 4.05.
I'm new to OCaml and I would like to know how can I write an ocaml code into a file and then compile it to run it whenever I want.
Now I'm using OCaml by typing ocaml in the mac or linux terminal and writing the code, but when I'm done and I close the software I lose all the work.
There're plenty of options, but the easiest one (to my opinion) is to use ocamlbuild. If you have your code in file program.ml, then
ocamlbuild program.native
will compile your program into a native binary, so that you can run it as simple as:
./program.native
There is also a shortcut that allows you to compile and run a program as one action:
ocamlbuild program.native --
You can pass arguments to your program after the -- sign.
If your program consists of more than one file, that's not a problem, as ocamlbuild will scan it, and automatically build all dependencies in a correct order.
If your program requires external libraries, then you can specify them with a -pkg or -pkgs option. Like this:
ocamlbuild -pkg lwt program.native
I'm thinking this tutorial - Compiling OCaml projects might help. It describes the basics of compiling OCaml. It discusses ocamlc and ocamlopt compilers in depth and other compiler tools.
If you are using Jane Street's Core, you should consider using the command corebuild to compile, which includes a bunch of defaults after ocamlbuild:
ocamlbuild \
-use-ocamlfind \
-pkg core \
-tag "ppx(ppx-jane -as-ppx)" \
-tag thread \
-tag debug \
-tag bin_annot \
-tag short_paths \
-cflags "-w A-4-33-40-41-42-43-34-44" \
-cflags -strict-sequence \
"$#"
I got this here.
I have an OCaml program(with a main method - it generates an executable) and I want to use it as a library.
I was compiling my program like this: ocamlc -I someDir -g -unsafe lotsOfCmoFiles -o outputFile and the program works fine.
Now I'm removing the line that makes it an executable(something like let _ = ...) and adding -a parameter to compile command: ocamlc -a -I someDir -g -unsafe lotsOfCmoFiles -o outputFile.cma
But somehow I can't load generated .cma file with ocamltop and ocamlbrowser shows an empty list. When I try to load from ocamltop:
# #load "outputFile.cma";;
Error: Reference to undefined global `Xyz'
And I'm 100% sure that xyz.cmo is included in lotsOfCmoFiles.
Am I giving some parameter wrong while compiling? Or else, what should I do to load my program in ocamltop ? (I'll use this library in another program, I'm giving ocamltop outputs as an example)
Any helps will be appreciated.
EDIT: So I can finally managed to compile and load it thanks to #cago, now I can load my library, and when I don't remove the main let _ = ... line it's automatically run when I load the .cma.
But I still can't open any modules. Strangely, this doesn't raise an exception
open Main
but then when I call a function from module Main:
# someFun;;
Error: Reference to undefined global `Main'
and ocamlbrowse still shows an empty list. now why is that?
EDIT2: I realized open Main doesn't fail because I have a Main module in the same folder(even though I didn't explicitly load it). If I move my .cma file somewhere else and load it, it works(ie. main function runs automatically), but now I can't open any modules even though ocamlobjinfo shows the modules.
EDIT3: -I doesn't help:
$ ocaml
OCaml version 4.00.1
# #load "lib.cma";;
ok
# open Lib;;
Error: Unbound module Lib
#
$ ocaml -I libFolder
OCaml version 4.00.1
# #load "toylib.cma";;
ok
# open Lib;;
# fun;;
Error: Reference to undefined global `Lib'
Some of the cmo in your lotsOfCmoFiles need to know the module Xyz. You need to take care of the dependency between your cmo files.
For example:
toto.ml:
let x = "toto"
titi.ml:
let y = Toto.x ^ " titi"
ocamlc -c toto.ml
ocamlc -c titi.ml
ocamlc -a titi.cmo toto.cmo -o lib.cma (* here is the probleme *)
# #load "lib.cma"
Error: Reference to undefined global `Toto'
Because titi depends on toto so you need to change the order of cmos:
ocamlc -a toto.cmo titi.cmo -o lib.cma
# #load "lib.cma"
# Titi.y;;
- : string = "toto titi"
EDIT:
If your cma is in a subdirectory for example, when you call ocaml you need to specify the path:
ocaml -I subdir/ (* subdir which contains lib.cma *)
# #load "lib.cma"
# Toto.x;;
- : string = "toto"
TL;DR: Make sure you don't have any top-level side-effects in the
I was running into this same kind of trouble. My project would build fine, most modules were available, but there was one module that kept triggering Reference to undefined global. But it was clear that the module was visible to the system: it was showing up in utop's autocomplete list, along with all of it's values, and I could reference it and import it into other modules.
The problem turned out to be an uncaught exception that was being thrown when that module was loaded. The exception was due to an attempt to load a non-existing file. It wouldn't cause problems during complication, but when the module was actually loaded it was breaking and the exception was being swallowed somewhere before I ever saw it.
I'm trying to compile an XML-RPC server written using the xmlrpc-light library in OCaml with ocamlbuild but I get:
$ ocamlbuild server.native
Finished, 0 targets (0 cached) in 00:00:00.
+ ocamlfind ocamlopt -linkpkg -package xmlrpc-light -package unix -package threads -package netsys -thread server.cmx -o server.native
File "_none_", line 1, characters 0-1:
Error: No implementations provided for the following modules:
Netsys referenced from /usr/lib/ocaml/equeue/equeue.cmxa(Uq_engines)
Command exited with code 2.
Compilation unsuccessful after building 4 targets (3 cached) in 00:00:00.
Note that I have a myocamlbuild.ml file like this one and a _tags file containing a single line:
<server.ml> or <server.native>: pkg_unix,pkg_netsys,pkg_xmlrpc-light,pkg_threads
This plugin has worked fine for me in other cases (for client.native of the same client/server application, for example) but not for server.native. The complaint suggests that the library Netsys is not available to the compiler. But we get
$ ocamlfind query netsys
/usr/lib/ocaml/netsys
meaning that netsys is installed in /usr/lib/ocaml/netsys. Inspecting that directory gives me:
$ ls /usr/lib/ocaml/netsys
META libnetsys.a netsys.a netsys.cma netsys.cmi netsys.cmxa netsys.mli
Also,
$ ocamlfind list | grep netsys
netsys (version: 2.2.9)
So, there is indeed a library called netsys installed, it does have a cmxa file ready to be used, but for some strange reason, ocamlbuild complaints that there is no implementation provided for the module Netsys. The fact that ocamlbuild could read /usr/lib/ocaml/equeue/equeue.cmxa should be enough to conclude that everything should be fine regarding environment ($PATH, etc.) in terms of finding libraries.
This is all in Debian 6.0 and my OCaml's version is 3.11.2.
After some browsing, I found an svn commit message (repository diff) which suggests that it may have to do with the number of threads used. And, in fact, I'm using a Mutex somewhere in my code (check the code of server.ml and client.ml in this other question). If I remove the Mutex stuff from my server.ml the error still happens. But if I additionally remove the pkg_threads from the _tags file then everything compiles. So, my conclusion is that I can't directly use the threads library with xmlrpc-light, which is weird.
IMHO equeue META is wrong. Adding netsys to dependencies fixes your issue :
sed -i 's/threads/netsys,threads/' /usr/lib/ocaml/equeue/META