I am working through the LLVM ocaml tutorial, and using the following command line to compile:
ocamlbuild -cflags -g,-I,+llvm-3.4 -lflags -I,+llvm-3.4 toy.byte
Is there any way to move those extra cflags and lflags into the _tags or myocamlbuild.ml files so that I don't need to type them/can store them in source control/make reproducible builds?
Here is the _tags file:
<{lexer,parser}.ml>: use_camlp4, pp(camlp4of)
<*.{byte,native}>: g++, use_llvm, use_llvm_analysis
<*.{byte,native}>: use_llvm_executionengine, use_llvm_target
<*.{byte,native}>: use_llvm_scalar_opts, use_bindings
And here is the myocamlbuild.ml file:
open Ocamlbuild_plugin;;
ocaml_lib ~extern:true "llvm";;
ocaml_lib ~extern:true "llvm_analysis";;
ocaml_lib ~extern:true "llvm_executionengine";;
ocaml_lib ~extern:true "llvm_target";;
ocaml_lib ~extern:true "llvm_scalar_opts";;
flag ["link"; "ocaml"; "g++"] (S[A"-cc"; A"g++ -rdynamic"]);;
dep ["link"; "ocaml"; "use_bindings"] ["bindings.o"];;
I do something like...
let mlflags = []
and cflags = []
and clibs = []
let rec arg_weave p = function
| x::xs -> (A p) :: (A x) :: arg_weave p xs
| [] -> []
and arg x = A x
...
let () = dispatch begin function
| After_rules ->
flag ["ocaml"; "compile"] (S (List.map arg mlflags));
flag ["c"; "compile"] (S (arg_weave "-ccopt" cflags));
flag ["c"; "link"] (S (arg_weave "-cclib" clibs));
...
end
The other option is to tag additional options. For example, in the ocaml_specific.ml file they have one set-up for debug and all the combinations of flag options for where the option is relevant.
flag ["ocaml"; "debug"; "compile"; "byte"] (A "-g");;
flag ["ocaml"; "debug"; "link"; "byte"; "program"] (A "-g");;
flag ["ocaml"; "debug"; "pack"; "byte"] (A "-g");;
flag ["ocaml"; "debug"; "compile"; "native"] (A "-g");;
flag ["ocaml"; "debug"; "link"; "native"; "program"] (A "-g");;
flag ["ocaml"; "debug"; "pack"; "native"] (A "-g");;
then, in the _tags file, you can have true : debug to turn it on for all files, or true can be replaced by a pattern for limiting the option. So if an option doesn't exist already, you can create your own and you'll see that it's similar to the fully myocamlbuild.ml solution, but additional flags for each tag instead of including them all at once.
-g is replaced by true: debug in _tags.
-I options ideally should be replaced by the corresponding ocamlfind package, e.g. calling ocamlbuild -use-ocamlfind and specifying true: package(llvm,llvm_analysis) in _tags and/or whatever other packages are called (and remove ocaml_lib calls in myocamlbuild.ml).
On the side note, just create a Makefile with whatever ocamlbuild invocation is needed and run make to build.
Related
It works quite well in utop with #require "ppx_jane" but
I added (preprocess (pps ppx_jane)) in my dune file which looks like this:
(library
(preprocess (pps ppx_jane))
(name raftml)
(modules raft rpc types)
(libraries
core
core_unix
proto
grpc
grpc-lwt
ocaml-protoc
lwt
lwt.unix
h2
h2-lwt-unix
domainslib
yojson
ppx_jane
ppx_sexp_conv
ppx_deriving_yojson
ppx_deriving
ppx_deriving_yojson.runtime))
And my types are like this:
type log = {
mutable command: string;
mutable term: int32;
mutable index: int32
} [##deriving sexp]
I call sexp_of_log in my code like this:
let persist () = Out_channel.write_all "file_name" ~data:(Sexp.to_string (sexp_of_log { command = "hello"; term = (10l); index = (24l); }))
And there's an error when I run dune build: Unbound value "string_of_sexp"
I solved this by adding:
open Sexplib.Std
At the top of the file that has the record types deriving sexp.
I am trying to use jbuilder together with ppx_deriving (ppx_deriving_yojson specifically) but got stuck for well over an hour now. My current approach is a jbuild file, containing the following:
(jbuild_version 1)
(executables
((names (my-binary))
(libraries
(ppx_deriving
ppx_deriving_yojson
cohttp
yojson))
(preprocess (pps (ppx_deriving_yojson ppx_driver.runner)))))
But that results in
Command [5] exited with code 1:
$ (cd _build/default && ../.ppx/default/ppx_deriving_yojson+ppx_driver.runner/ppx.exe --dump-ast -o src/my_file.pp.ml --impl src/my_file.ml)
File "src/my_file.ml", line 16, characters 5-13:
Error: Attribute `deriving' was not used
Running the generated ppx_driver in _build/.ppx/default/ppx_deriving_yojson+ppx_driver.runner/ppx.exe manually with -print-transformations gives empty output, so I am obviously missing something.
The code builds fine with topkg by just including ppx_deriving and ppx_deriving_yojson as dependencies.
As of more recent versions of ppx_deriving_yojson this should be possible.
Code:
type t = {x: int; y: int} [##deriving to_yojson]
let () = print_endline (Yojson.Safe.to_string (to_yojson {x= 1; y= 2}))
And a sample jbuild file:
(jbuild_version 1)
(executables
((names (main))
(preprocess (pps (ppx_deriving_yojson)))
(libraries (ppx_deriving_yojson.runtime))))
(install
((section bin)
(files ((main.exe as main)))))
I currently have a project (Go to Python compiler) with the following files
ast.ml
parser.mly
lex.mll
weeder.ml
prettyPrint.ml
main.ml
Here are the dependencies:
parser: ast
lexer: parser, Core, Lexing
weeder: ast
prettyPrint: ast
main: ast, lex, parser, weeder, prettyPrint
I try to compile doing the following which should work according to the documentation I read:
$ menhir parser.mly
> Warning: you are using the standard library and/or the %inline keyword. We
recommend switching on --infer in order to avoid obscure type error messages.
$ ocamllex lex.mll
> 209 states, 11422 transitions, table size 46942 bytes
$ ocamlbuild -no-hygiene main.native
> File "parser.mli", line 77, characters 56-59:
Error: Unbound type constructor ast
Command exited with code 2.
Compilation unsuccessful after building 6 targets (2 cached) in 00:00:00.
ast.ml contains a list of type declarations in which I have a
type ast = ...
I spent a few hours now reading doc for ocamlfind, corebuild and ocamlopt and nothing. At some point it compiled by what seemed like a mere coincidence and never worked again. I'm open to using any tool.
Here is what is in parser.mly
%{
open Ast
exception ParserError of string
let rec deOptionTypeInList tupleList =
match tupleList with
| [] -> []
| (a, Some t)::tl -> (a, t)::(deOptionTypeInList tl)
| _ -> raise (ParserError "no type given in type declaration")
%}
[ ... long list of tokens ... ]
%type <ast> prog (* that seems to be the problem *)
%type <string> packDec
%type <dec> dec
%type <dec> subDec
[...]
%start prog
[ ... rules ... ]
And here is the line, the very last, that is refereed to in the error message.
val prog: (Lexing.lexbuf -> token) -> Lexing.lexbuf -> (ast)
The open Ast construct will not be exported to the .mli file where the type of symbols are mentioned. Try using
%type <Ast.ast>
Edit: also, your build commands are weird. You should not call ocamllex and menhir manually, and consequently not need -no-hygiene. Remove all generated files and just do
ocamlbuild -use-menhir main.byte
I made the mistake of updating software and now I can't run any OUnit tests.
I think I've managed to boil the problem down to a simple REPL session.
$ ocaml -I /opt/local/lib/ocaml/site-lib/oUnit
OCaml version 4.01.0
# Ounit.assert_equal;;
Error: Wrong file naming: /opt/local/lib/ocaml/site-lib/oUnit/ounit.cmi
contains the compiled interface for
Ounit when OUnit was expected
# OUnit.assert_equal;;
Error: Reference to undefined global `OUnit'
Any ideas what I'm doing wrong?
I'm running this on a Mac laptop which has the default case-insensitive/case-preserving file-system, but dinking with the case of the include path doesn't help.
My larger problem manifests thus:
ocamlbuild \
-libs \
nums,str,unix,oUnit,graph \
-cflags \
-g,-w,+a-4,-warn-error,+a-4,-I,/opt/local/lib/ocaml/site-lib/oUnit,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
-lflags \
-g,-I,/opt/local/lib/ocaml/site-lib/oUnit,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
./AllTests.native
Error: No implementations provided for the following modules:
OUnitCore referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitLoggerStd referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitUtils referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitConf referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitAssert referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitBracket referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitTest referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitRunner referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitChooser referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitLogger referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2),
/opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit)
OUnitTestData referenced from /opt/local/lib/ocaml/site-lib/oUnit/oUnit.cmxa(OUnit2)
Command exited with code 2.
Compilation unsuccessful after building 646 targets (645 cached) in 00:00:02.
Your first error is probably because your OS does not distinguish cases in filenames but OCaml does:
$ ocamlobjinfo `ocamlfind query oUnit`/oUnit.cmi
File /mnt/home/jun/.opam/system/lib/oUnit/oUnit.cmi
Unit name: OUnit
Interfaces imported:
cb146e345f0b34fc8ad4b5afe69d1f20 OUnit
...
You can see that the module is called "OUnit" not "Ounit".
The second error is clearly because the library is not loaded into the REPL yet. The REPL's knows the existence of the function, but has no code loaded. It is accessible if you load the library and those on which it depends:
ocaml -I `ocamlfind query oUnit` unix.cma oUnitAdvanced.cma oUnit.cma
OCaml version 4.01.0
# OUnit.assert_equal;;
- : ?cmp:('a -> 'a -> bool) ->
?printer:('a -> string) ->
?pp_diff:(Format.formatter -> 'a * 'a -> unit) ->
?msg:string -> 'a -> 'a -> unit
= <fun>
I solved the problem by changing my ocamlbuild invocation to use -use-ocamlfind which seems to work around all the path confusion.
I also uninstalled all OCaml modules and instead installed OPAM and then installed OUnit and others via OPAM, and re-logged in so that my environment is pristine.
The build command that works for me now is
ocamlbuild \
-use-ocamlfind \
-libs graph \
-pkgs str,unix,ounit \
-cflags -g,-w,+a-4,-warn-error,+a-4,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
-lflags -g,-I,/opt/local/lib/ocaml/site-lib/ocamlgraph \
./AllTests.native
which is generated by my updated build script
(* Usage: ocaml make.ml [<ModuleToBuild>.{byte,native}] *)
#load "unix.cma";;
let args = match Array.to_list Sys.argv with
| [] -> failwith "no program on argv"
| _::[] -> ["AllTests.byte"]
| _::argv -> argv
let library_paths = [
(* TODO: Figure out why `opam install ocamlgraph` fails *)
"-I"; "/opt/local/lib/ocaml/site-lib/ocamlgraph";
]
(* If the -p flag is first in the argument list, then replace it
with a host of flags that enable profiling via ocamlprof. *)
let args, c_opt_flags, l_opt_flags =
match args with
| "-p"::rest ->
(* Treat the targets as debug and profile targets. *)
"-tags"::"debug,profile"
(* Use profiling versions of the compilers which instrument
various flow control constructs with entry counters. *)
::"-ocamlc"::"ocamlcp"
::"-ocamlopt"::"ocamloptp"
::rest,
(* Instrument all available points. *)
["-P"; "a"],
(* Link with a wrapper that dumps profiling data if program
exits noramlly. *)
["-p"]
| _ -> args, [], []
let standard_flags = [
"-use-ocamlfind";
(* TODO: Figure out why `opam install ocamlgraph` fails *)
"-libs"; "graph";
"-pkgs"; "str,unix,ounit"; (* TODO: graph *)
"-cflags"; (String.concat "," (
[
"-g";
"-w"; "+a-4";
"-warn-error"; "+a-4";
]
# c_opt_flags
# library_paths));
"-lflags"; (String.concat "," (
[
"-g";
]
# l_opt_flags
# library_paths));
]
let build_command = "ocamlbuild"
let argv = build_command::(standard_flags # args)
let _ = begin
Printf.printf "%s\n" (String.concat " \\\n\t" argv);
flush stdout;
Unix.execvp build_command (Array.of_list argv);
end;;
I know next to nothing about ocaml, but I want to install Coccinelle (on cygwin), which has a dependency to the binary ocamlfind.
However, installing either ocaml-3.11.0-win-mgw.exe or ocaml-3.11.0-win-msvc.exe
from http://caml.inria.fr/download.en.html, there are no such binary. In fact not a single file in the installed directory contains any reference to the string "ocamlfind".
And downloading the source code (ocaml-3.12.1), grep only finds the following references:
./Changes:- PR#5165: ocamlbuild does not pass '-thread' option to ocamlfind
./Changes:- PR#5217: ocamlfind plugin should add '-linkpkg' for toplevel
./ocamlbuild/command.ml: else None (* Sh"ocamlfind ocamlc" for example will not be digested. *)
./ocamlbuild/findlib.ml: | Cannot_run_ocamlfind
./ocamlbuild/findlib.ml: | Cannot_run_ocamlfind ->
./ocamlbuild/findlib.ml:let ocamlfind = "ocamlfind"
./ocamlbuild/findlib.ml: run_and_parse Lexers.ocamlfind_query
./ocamlbuild/findlib.ml: "%s query -l -predicates byte %s" ocamlfind name
./ocamlbuild/findlib.ml: "%s query -a-format -predicates native %s" ocamlfind name
./ocamlbuild/findlib.ml: run_and_parse Lexers.blank_sep_strings "%s query -r -p-format %s" ocamlfind name
./ocamlbuild/findlib.ml: (* TODO: Improve to differenciate whether ocamlfind cannot be
./ocamlbuild/findlib.ml: error Cannot_run_ocamlfind
./ocamlbuild/findlib.ml: run_and_parse Lexers.blank_sep_strings "%s list | cut -d' ' -f1" ocamlfind
./ocamlbuild/findlib.ml:make another ocamlfind query such as:
./ocamlbuild/findlib.ml: ocamlfind query -p-format -r package1 package2 ... *)
./ocamlbuild/lexers.mli:val ocamlfind_query : Lexing.lexbuf ->
./ocamlbuild/lexers.mll:and ocamlfind_query = parse
./ocamlbuild/lexers.mll: | _ { raise (Error "Bad ocamlfind query") }
./ocamlbuild/manual/manual.tex:\texttt{ocamlfind}). Here is the list of relevant options:
./ocamlbuild/ocaml_specific.ml: if !Options.use_ocamlfind then begin
./ocamlbuild/ocaml_specific.ml: (* Note: if there is no -pkg option, ocamlfind won't be called *)
./ocamlbuild/ocaml_specific.ml:if not !Options.use_ocamlfind then begin
./ocamlbuild/options.ml:let use_ocamlfind = ref false
./ocamlbuild/options.ml: "ocamlyacc"; "menhir"; "ocamllex"; "ocamlmklib"; "ocamlmktop"; "ocamlfind"]
./ocamlbuild/options.ml:let ocamlfind x = S[V"OCAMLFIND"; x]
./ocamlbuild/options.ml: "-use-ocamlfind", Set use_ocamlfind, " Use ocamlfind to call ocaml compilers";
./ocamlbuild/options.ml: if !use_ocamlfind then begin
./ocamlbuild/options.ml: ocamlc := ocamlfind & A"ocamlc";
./ocamlbuild/options.ml: ocamlopt := ocamlfind & A"ocamlopt";
./ocamlbuild/options.ml: ocamldep := ocamlfind & A"ocamldep";
./ocamlbuild/options.ml: ocamldoc := ocamlfind & A"ocamldoc";
./ocamlbuild/options.ml: ocamlmktop := ocamlfind & A"ocamlmktop";
./ocamlbuild/signatures.mli: val use_ocamlfind : bool ref
./ocamlbuild/signatures.mli: | Cannot_run_ocamlfind
./ocamlbuild/signatures.mli: (** Transitive closure, as returned by [ocamlfind query -r]. *)
and none of this is any references to install of such a binary. So I am sort of lost on how to proceed. Go back to older releases of ocaml?
BTW, the native ocaml cygwin packages did also not contain any ocamlfind binary.
Is google down today? http://projects.camlcity.org/projects/findlib.html
There is no precompiled binary, but on cygwin it compiles fine out of the box.