i am trying to compile a ocaml program (part of it shown below)
open Ocamlbuild_plugin
open Command
(** helper functions )
( splitting strings using a delimeter character *)
let rec strsplit sep str accu len =
try let idx = String.rindex_from str (len - 1) sep in
strsplit sep str ((String.sub str (idx + 1) (len - 1 - idx)) :: accu) idx
with Not_found -> (String.sub str 0 len) :: accu
let strsplit sep str = strsplit sep str [] (String.length str)
(** initializing variables from the environment *)
let host = Ocamlbuild_pack.Ocamlbuild_Myocamlbuild_config.system
the last line is causing unbound module error. What can i do? thanks
update 1:
The code is from a github project https://github.com/ykazakov/cb-reasoner
And i am following an instruction there to use "make" to compile the program .. this make file looks like this
BUILDDIR ?= _build
OCAMLBUILD ?= ocamlbuild
OCAMLBUILD := $(OCAMLBUILD) -build-dir $(BUILDDIR)
.PHONY: main clean clib
main:
$(OCAMLBUILD) main/cb.native
all:
$(OCAMLBUILD) main/cb.native jni cwrap/libcb.a
cwrap:
$(OCAMLBUILD) cwrap/libcb.a
jni:
$(OCAMLBUILD) jni
clean:
$(OCAMLBUILD) -clean;\
rm -f cb.native
I answered this question on the ocamlbuild issue tracker (I follow StackOverflow but less closely, sorry). Quoting below for convenience:
OCamlbuild exports a stable interface for plugin users as the Ocamlbuild_plugin module. Using Ocamlbuild_pack directly accesses ocamlbuild's internal definitions, and is recommended against as there are no guarantees of backward-compatibility.
In your specific case, a module is used by this code that indeed was removed in more recent ocamlbuild versions (its presence was an artifact of the specific way ocamlbuild's build system was integrated into the compiler distribution). I could correctly build this software with OCaml 3.12.1, 4.00.1 and 4.01.0, but not any more recent version of OCaml and ocamlbuild.
Using opam makes it easy to install old OCaml versions:
opam install 4.01.0
eval $(opam env --switch=4.01.0)
make # if in the project's directoyr
If you are interested in patching this software to make it compatible with more recent OCaml versions, we could discuss how to get the corresponding information in a more robust way.
In any case, I'm closing this as it is not a problem of ocamlbuild, but rather a maintenance question for cb-reasoner. (Of course, feel free to post further comments.)
Related
I have a dune-project file that specifies that my ocaml compiler should be at least 4.05.0
I created a configure file to check that all I need is properly installed (using a mix of Unix.open_process_in "which <executabe>" and dune external-lib-deps --missing ##default) but for OCaml version I had to write:
let e = Sys.ocaml_version in
match String.split_on_char '.' e with
| major :: minor :: patchlevel :: _
when int_of_string major >= 4
&& int_of_string minor >= 5
&& int_of_string patchlevel >= 0 ->
printf "%s#," e
| _ -> printf "version < 4.05.0"
But I don't like it that much because if I ever need to change the version requirement, it won't propagate to this check and I'll have to change it manually.
Is there a way to do it like I check that all the OCaml packages needed are installed with dune external-lib-deps --missing ##default? (And not necessarily only for the OCaml compiler but for each package that is bound to a version?)
Since the dependency specification is a logical expression I hoped that the solver behind opam could do it for me because I can't implement a SMT Solver in my configure file.
I'm having trouble linking a very simple OCaml program:
open Core
Format.printf "hello world %s\n" "foobar";;
Format.printf "argv= %s\n" (Sys.get_argv()).(0) ;;
which I compile with
ocamlfind ocamlc -thread -package core visitor.ml
The compile step always generates the error:
Error: Required module `Core__Core_sys' is unavailable
I've pinned version 4.0.9, and I can see the file:
$ ocamlfind query core
/home/ubuntu/.opam/4.09.0/lib/core
and $ ls -la /home/ubuntu/.opam/4.09.0/lib/core shows
-rw-r--r-- 1 ubuntu ubuntu 17891 Dec 3 20:14 core__Core_sys.cmi
-rw-r--r-- 1 ubuntu ubuntu 93777 Dec 3 20:14 core__Core_sys.cmt
-rw-r--r-- 1 ubuntu ubuntu 75659 Dec 3 20:14 core__Core_sys.cmti
-rw-r--r-- 1 ubuntu ubuntu 16958 Dec 3 20:14 core__Core_sys.cmx
I've tried everything I can think of, with no luck. BTW, I notice that the documentation https://ocaml.org/api/Sys.html makes no mention at all of get_argv but if I try just plain Sys.argv I get a warning:
# Sys.argv ;;
Alert deprecated: Core.Sys.argv
[since 2019-08] Use [Sys.get_argv] instead, which has the correct behavior when [caml_sys_modify_argv] is called.
So I conclude that the core OCaml documentation published at ocaml.org is more than two years out of date! How can one obtain up-to-date documentation, ideally documentation that describes these kinds of newbie errors?
A few points. First, it looks like you are on a fairly old version of OCaml. Unless you need to stay on 4.09 for some reason, I highly recommend upgrading to the latest version, 4.13.1. Instructions for installing are here: https://ocaml.org/learn/tutorials/up_and_running.html
In case you have any trouble with that, try upgrading to the latest version of opam (the OCaml package manager) and doing opam update to download the most up-to-date package index.
Second, it looks like you are trying to use Jane Street's Core library, which is a third-party package which is intended as a standard library replacement. As such, it has its own version of the OCaml standard library's Sys module, i.e. Core.Sys. Regarding the alert that you are getting, the Core.Sys.argv value is actually deprecated by Jane Street Core: https://ocaml.janestreet.com/ocaml-core/latest/doc/core/Core__/Core_sys/index.html#val-argv
A single result from get_argv (). This value is indefinitely deprecated. It is kept for compatibility...
This leads us to the final issue, when you try to compile it is unable to find the core package. There are a couple of choices here. First, one option is that the core package and standard library replacement are actually optional; you may not actually need them. If you're an OCaml beginner you could try sticking with the standard library only (so no open Core, no trying to compile with the core package).
Another option, if you decide to keep using the core package, is to the dune build system instead of ocamlfind. Dune is a powerful, modern OCaml build system that handles almost all aspects of package linking during the build, so you don't need to worry about issuing individual compile commands.
Here's what a dune file would look like:
(executable
(name visitor)
(libraries core))
And the visitor.ml file would be in the same directory:
let () =
Printf.printf "hello world %s\n" "foobar";
Printf.printf "argv= %s\n" Sys.argv.(0)
Then you would run:
dune exec ./visitor.exe
The .exe is a dune convention, executables across operating systems are given this extension.
Finally, in source code you never actually need ;;. More about that here: https://discuss.ocaml.org/t/terminate-a-line-with-or-or-in-or-nothing/8941/21?u=yawaramin
Note on documentation being out of date: it would help if you could point us to where you got the instructions that led you to this point of confusion. There is a lot of effort to clean up install instructions and modernize documentation, but unfortunately there are a lot of outdated getting started guides out there. The 'Up and Running' link I provided at the top of this answer is the best resource.
You need to link the package by adding the -linkpkg flag:
ocamlfind ocamlc -thread -package core -linkpkg visitor.ml
My problem is similar to this, however, in my case .ocamlinit is set.
Here is my ocaml version.
mymac:Desktop myusr$ ocaml --version
The OCaml toplevel, version 4.08.1
Here is my opam version.
mymac:Desktop myusr$ opam --version
2.0.5
Here is my opam switch.
mymac:Desktop myusr$ opam switch
# switch compiler description
→ 4.08.1 ocaml-base-compiler.4.08.1 4.08.1
default ocaml-base-compiler.4.08.1 default
Here's my .ocamlinit:
mymac:Desktop myusr$ cat ~/.ocamlinit
(* ## added by OPAM user-setup for ocamltop / base ## 3ec62baf6f9c219ae06d9814069da862 ## you can edit, but keep this line *)
#use "topfind";;
(* ## end of OPAM user-setup addition for ocamltop / base ## keep this line *)
#thread;;
#require "core.top";;
#require "core.syntax";;
Here is the evidence that I already have core installed.
mymac:Desktop myusr$ opam install core utop
[NOTE] Package utop is already installed (current version is 2.4.1).
[NOTE] Package core is already installed (current version is v0.12.3).
Here is the sum.ml file from Real World OCaml:
open Core.Std
let rev read_and_accumulate accum =
let line = In_channel.input_line In_channel.stdin in
match line with
| None -> accum
| Some x -> read_and_accumulate (accum +. Float.of_string x)
let () =
printf "Total: %F\n" (read_and_accumulate 0.)
Here's what happens when I try to build it with corebuild:
mymac:Desktop myusr$ corebuild sum.native
+ ocamlfind ocamlc -c -w A-4-33-40-41-42-43-34-44 -strict-sequence -g -bin-annot -short-paths -thread -package core -ppx 'ppx-jane -as-ppx' -o sum.cmo sum.ml
File "sum.ml", line 1, characters 5-13:
1 | open Core.Std
^^^^^^^^
Error: Unbound module Core.Std
Command exited with code 2.
Hint: Recursive traversal of subdirectories was not enabled for this build,
as the working directory does not look like an ocamlbuild project (no
'_tags' or 'myocamlbuild.ml' file). If you have modules in subdirectories,
you should add the option "-r" or create an empty '_tags' file.
To enable recursive traversal for some subdirectories only, you can use the
following '_tags' file:
true: -traverse
<dir1> or <dir2>: traverse
Compilation unsuccessful after building 2 targets (1 cached) in 00:00:00.
Why isn't corebuild linking to the core library? How can I fix this?
The build script loads everything correctly. The module that you're trying to load no longer exists. You're trying to use an old version of the Real World OCaml book together with a very new version of OCaml and Core. The Janestreet Core library has changed a lot since those times. You should either switch to a newer book or downgrade to an older version of OCaml and Core library.
Using modern Core
Since the admission of Dune and module aliases, it is no longer needed to have an extra Std submodule, therefore Janestreet removed it (after a two-year-long deprecation). Therefore, now we're writing
open Core
instead of
open Core.Std (* no longer works *)
The same is true with Core_kernel et alas.
Since OCaml and Janesteet have moved since that time a lot, the newer version of RWO was created with updated examples. It is still a work in progress but looks quite close to be ready. So you can switch to it.
Sticking to older versions of OCaml
If you would like to use the first version of Real World OCaml, then you have to choose a version of OCaml and Janesteet's Core library which are known to be compatible. I failed to find any authoritative recommendations on which version it is better to use with the old book. So I would suggest using OCaml 4.02.3. Then you can install core as usual with opam install core (it should install version 113.33.03), and as far as I remember, it should work with the old book. If you or anyone else is having problems with this version please tell me in the comments section, and I will update this recommendation.
I was messing around with the OCaml FFI to try to figure out how it goes about inferring the width of a C enum (which I think is implementation-defined for C) and am trying to insert a type of the wrong width to see what blows up at runtime. That's the motivation, but the actual issue I ran into is much more mundane.
I have a simple OCaml file that uses the C FFI to call a trivial function in example.c that converts an enum to an int.
open Printf;;
let (#->) = Ctypes.(#->);;
let returning = Ctypes.returning;;
let foreign = Foreign.foreign;;
(* deliberately use the wrong scalar type for argument *)
let wrong_int64_of_color =
foreign "int_of_color" (Ctypes.int64_t #-> returning Ctypes.int64_t);;
let main () =
printf "%Ld\n" (wrong_int64_of_color (Int64.of_int 100));;
let () = main ();;
I configured opam and installed Ctypes and Ctypes.Foreign
% opam config env | sed -e 's/=.*/=/'
CAML_LD_LIBRARY_PATH=
OPAMUTF8MSGS=
MANPATH=
PERL5LIB=
OCAML_TOPLEVEL_PATH=
PATH=
% opam list | grep ctypes
ctypes 0.6.2 Combinators for binding to C libraries withou
ctypes-foreign 0.4.0 Virtual package for enabling the ctypes.forei
The two usual incantations I use for compiling a simple .ml script have both failed me and I'm out of ideas. ocamlfind and corebuild (which I think is a wrapper on top of ocamlbuild)
ocamlfind can't seem to find ctypes and foreign. However, it doesn't complain that about not being able to locate the packages so I'm guessing ctypes and ctypes.foreign are the correct names for these packages in the weird findlib namespace.
% ocamlfind ocamlopt -package findlib,ctypes,ctypes.foreign -thread call_example.ml
File "_none_", line 1:
Warning 58: no cmx file was found in path for module Foreign, and its interface was not compiled with -opaque
File "call_example.ml", line 1:
Error: No implementations provided for the following modules:
Ctypes referenced from call_example.cmx
Foreign referenced from call_example.cmx
Why can't ocamlfind locate these modules? I have no problem loading them into the toplevel.
─( 22:30:42 )─< command 0
utop # #require "ctypes";;
─( 22:30:42 )─< command 1
utop # open Ctypes;;
─( 22:30:55 )─< command 2
utop # #require "ctypes.foreign";;
─( 22:31:00 )─< command 3
utop # open Ctypes;;
It seems to me that you forget to add -linkpkg ocamlfind option to instruct the compiler actually link the libraries from the packages to build the executable.
From this SO question: List Comprehension in Ocaml?, I could install the comprehension package with opam install pa_comprehension, and use the package in toplevel REPL.
# #require "pa_comprehension";;
# open Batteries;;
# [? 2 * x | x <- 0 -- max_int ; x * x > 3 ?];;
- : int Batteries.Enum.t = <abstr>
Then, how can I compile the code?
Unfortunately, since pa_comprehension package name is not ended with .syntax extension, this is a little bit harder than it should be. (The fact that this issue is still not fixed, shows that using pa_comprehension is not very popular in modern OCaml). So, without the proper extension, we need to do everything manually. If your file is named pr.ml, then the correct invocation is:
$ ocamlbuild -use-ocamlfind -syntax camlp4o -pkg camlp4,pa_comprehension pr.native
If you don't wan't to type it every time, then you can create _tags file, with the following contents:
$ cat _tags
<**/*> : package(camlp4),syntax(camlp4o),package(pa_comprehension)
In that case, the command line spell is a little bit easier:
$ ocamlbuild -use-ocamlfind pr.native