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.
Related
At my employment we are working on a large C++ project on Red Hat Enterprise Linux (RHEL) 6, soon to be RHEL 8. with Bash shell. We sometimes use Netbeans for editing source code, but I prefer to use vim. We are doing DevOps and Agile with two week sprints, and using Jenkins build engine with AccuRev for source control. Every time a code change is promoted in AccuRev, Jenkins automatically starts a new build of the code base. As part of that build, CPPCHECK is used to do static code analysis on the C++ source code.
In part of our system, we are using C++ macros to define unit test scripts. the macros are not fully defined, since we are allowing the unit test script developer to customize them for doing unit tests. This system works fine with no error at compile time with g++ compiler, and also there is no error at run time either.
However, when Jenkins does a build, and it uses CPPCHECK to analyze the code, it is generating
error-id: unknownMacro
text: There is an unknown macro here somewhere. Configuration is required. If SCRIPT is a macro then please configure it.
Here is an example of the C++ code we are using to complete partially defined C++ macro:
SCRIPT(SampleScript)
BODY()
{
cout << "SampleScript running." << endl;
}
END_SCRIPT()
SCRIPT, BODY, and END_SCRIPT are C++ macros listed in an include file, but are not completely defined. On the Github site for CPPCHECK there is a supposed solution to this issue by using -I option, but I tried that and the missing macro CPPCHECK errors are still occurring.
This is the CPPCHECK command listed with its arguments, including the -I option, but so far this command is still generating "unknownMacro" error.
cppcheck \
-I ./* \
-j 4 \
--xml-version=2 \
Ok, I have many years experience with Unix and Linux, but was not aware of the following fix. The fix is to use the -I option with CPPCHECK, which I was doing, but I was doing the following in the Makefile with an asterisk:
cppcheck \
-I ./* \
-j 4 \
--xml-version=2 \
I just found out from another person that asterisk * is not recognized in Unix and Linux Makefiles, but IS recognized from the command line with Bash and other shells like I have known for a long time. So I removed the asterisk from the CPPCHECK call and now there are no more CPPCHECK errors with the C++ code in the Jenkins build.
cppcheck \
-I ./ \
-j 4 \
--xml-version=2 \
Assuming this is possible, could someone tell me, how I have to configure the cmake build to create a "pure" llvm toolchain on ubuntu-16.04 consisting of
clang
lld
libc++
libc++abi
libunwind (llvm)
compiler-rt
any other pieces that might be relevant and are "production ready"
The resulting compiler should
be as fast as possible (optimizations turned on, no unnecessary asserts or other checks in the compiler binary itself)
be installed in a separate, local directory (lets call it <llvm_install>)
not have dependencies to the llvm tolchain provided by packet manager
use libc++, libc++abi etc by default.
support the sanitizers (ubsan, address, memory, thread) (which probably means that I have to compile libc++ a second time)
So far I have cloned
llvm from http://llvm.org/git/llvm.git into <llvm_root>
clang from http://llvm.org/git/clang.git into <llvm_root>/tools/clang
lld from http://llvm.org/git/lld.git into <llvm_root>/tools/lld
compiler-rt, libcxx, libcxxabi, libunwind from http://llvm.org/git/<project_name> into <llvm_root>/projects/<project_name>
Then run ccmake in a separate directory - I have tried various settings, but as soon as I try anything more fancy beyond turning optimizations on, I almost always get some sort of build error. Unfortunately, I have yet to find a way to export my changes from ccmake otherwise I'd give you an example with the settings and according error, but I'm more interested in a best practice than a fix to my test configs anyway.
Bonus points: By default, this should build with the default g++ toolchain, but I'd also be interested in a two stage build if that improves the performance of the final toolchain (e.g. by using LTO).
Btw.: The whole Idea came from watching chandler's talk
Pacific++ 2017: Chandler Carruth "LLVM: A Modern, Open C++ Toolchain"
My usual procedure is to build a small enough LLVM/Clang so that I have something working with libc++ and libc++abi. I guess you can use the system-provided LLVM, but I haven't tried it. For this step, what you have checked-out is probably enough. A sample script for this:
cmake
-G Ninja \
-DCMAKE_EXPORT_COMPILE_COMMANDS=On \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DBUILD_SHARED_LIBS=On \
-DLLVM_ENABLE_ASSERTIONS=Off \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DLLVM_ENABLE_SPHINX=Off \
-DLLVM_ENABLE_THREADS=On \
-DLIBCXX_ENABLE_EXCEPTIONS=On \
-DLIBCXX_ENABLE_RTTI=On \
-DCMAKE_INSTALL_PREFIX=[path-to-install-dir] \
[path-to-source-dir]
Having the aforementioned clang in your PATH environment variable,
you can use the below build script again and adjust based on your needs (sanitizers, etc). Apart from the main documentation page on the subject, poking around the CMakeLists.txt of each respective tool is also illuminating and helps adjust the build process from version to version.
LLVM_TOOLCHAIN_LIB_DIR=$(llvm-config --libdir)
LD_FLAGS=""
LD_FLAGS="${LD_FLAGS} -Wl,-L ${LLVM_TOOLCHAIN_LIB_DIR}"
LD_FLAGS="${LD_FLAGS} -Wl,-rpath-link ${LLVM_TOOLCHAIN_LIB_DIR}"
LD_FLAGS="${LD_FLAGS} -lc++ -lc++abi"
CXX_FLAGS=""
CXX_FLAGS="${CXX_FLAGS} -stdlib=libc++ -pthread"
CC=clang CXX=clang++ \
cmake -G Ninja \
-DCMAKE_EXPORT_COMPILE_COMMANDS=On \
-DBUILD_SHARED_LIBS=On \
-DLLVM_ENABLE_LIBCXX=On \
-DLLVM_ENABLE_LIBCXXABI=On \
-DLLVM_ENABLE_ASSERTIONS=On \
-DLLVM_TARGETS_TO_BUILD="X86" \
-DLLVM_ENABLE_SPHINX=Off \
-DLLVM_ENABLE_THREADS=On \
-DLLVM_INSTALL_UTILS=On \
-DLIBCXX_ENABLE_EXCEPTIONS=On \
-DLIBCXX_ENABLE_RTTI=On \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="${CXX_FLAGS}" \
-DCMAKE_SHARED_LINKER_FLAGS="${LD_FLAGS}" \
-DCMAKE_MODULE_LINKER_FLAGS="${LD_FLAGS}" \
-DCMAKE_EXE_LINKER_FLAGS="${LD_FLAGS}" \
-DCMAKE_POLICY_DEFAULT_CMP0056=NEW \
-DCMAKE_POLICY_DEFAULT_CMP0058=NEW \
-DCMAKE_INSTALL_PREFIX=${INSTALL_DIR} \
[path-to-source-dir]
A note on performance: I haven't watched that talk yet, but my motivation behind this 2 step build was to have a toolchain that I can easily relocate between systems since the minimal system dependence that matters is libc.
Lastly, relevant to the above procedure is this older question of mine, which still bugs me. If you have any insight on this, please don't hesitate.
PS: Scripts have been tested with LLVM 3.7 through 3.9 and current trunk 6.0.0.
Update: I've also applied these suggestions, and there is marked improvement when using the gold linker instead of ld. LTO is also a boost.
My program uses all of available memory, so I wanted to check which functions and abstracts are spoiling my project. I decided to use Memprof, so I installed their compiler and compiled my code with command
ocamlfind ocamlopt -package xml-light unix.cmxa str.cmxa -c -g NKJPxmlbasics.ml NKJP.mli NKJP.ml test.ml
and then run as suggested in tutorial
ocp-memprof --exec ./test
But there is error instead of result:
Error: no memory profiling information found. Possible causes:
- the application was not compiled with memory profiling support;
- the application exited before any major garbage collection was performed.
I even managed once to make it work but I have no idea how it happened
http://memprof.typerex.org/users/97beffbaec332eb7b2a048b94f7a38cf/2015-12-15_17-33-50_ab17218e800fe0a68fc2cfa54c13bfa6_16194/index.html
Is there any way to use this tool properly in this situation? What am I missing?
ocamlfind ... -c ... does not generate any executable. So, the ./test that you are running was probably generated by a previous command, probably without the memprof switch.
I want to compile some OCaml bytecode and have it run on Windows and Unix-type systems. My source code works fine if I recompile it on each platform, but the bytecode isn't portable.
Sample code:
open Unix
let on_windows = Filename.dir_sep <> "/";;
Printf.printf "On windows: %b\n" on_windows;;
let child = create_process "gpg" (Array.of_list ["gpg"; "--version"]) stdin stdout stderr;;
Printf.printf "Child %d\n" child;;
Build command:
ocamlbuild -use-ocamlfind -pkg unix test.byte
If I compile on Windows and run on Linux, I get
Fatal error: unknown C primitive `win_waitpid'
If I compile on Linux and run on Windows I get:
Fatal error: unknown C primitive `unix_waitpid'
How can I make the bytecode work everywhere?
Obviously, the reason is that ocaml unix library has different names for C stubs depending on the platform, and this hinders bytecode portability. I do not see the way out except for patching stub names..
Merely renaming the C symbols doesn't work because there are two completely different versions of the unix.ml module (though with the same interface). If you link your code statically, you'll get the one for the build platform and it won't work on the other platform.
The solution is to create and distribute a .cma archive (with the Unix module not linked in) rather than an executable. Then use ocaml to link dynamically on the target platform:
http://roscidus.com/blog/blog/2013/07/07/ocaml-binary-compatibility/#windows--linux-compatibility
Update: This isn't safe. When you do ocaml /path/to/script.ml, it adds the current directory (not the directory containing the script) to the start of the search path. Thus:
$ cd /tmp
$ /usr/bin/myprog
will first try to load myprog's libraries (e.g. unix.cma) from /tmp.
Should be fixed in 4.03: http://caml.inria.fr/mantis/view.php?id=6081
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