load|use|require a library object file within an Ocaml source file - ocaml

The Ocaml manual contains an exercise (here) in which library object files are loaded in the toplevel loop (the ocaml interactive interpreter) in the following way:
#load "dynlink.cma";;
#load "camlp4o.cma";;
I'm trying to replicate the subsequent code in a compilable source file, and the code requires the above library object files. Can I load these files with a line of code within the source file and compile it with ocamlc? I've tried "#load", "load", "#use", "use", "#require", "require", and all these proceded by "#directory" and "directory". I know that you can include modules with "include ;;", but this shouldn't work either, because they're just library files, not modules. I've tried to find a way to do this in the manual, but to no avail.
Do I need to reference the files in the compilation command? If so, how do I do this?

Directives starting with a # character are used only in the toplevel and are not strictly part of the OCaml language. In a file that you want to compile, you don't use # directives. See the OCaml manual Chapter 9. The #load directives are for loading a library. When compiling a file, you have to tell the compiler to use the library (on the command line, not in the file). It's good to learn the compiler commands directly at first, but eventually you should use ocamlfind and oasis, which make compilation much easier.

I'm assuming your source is written using extensions implemented by camlp4o. To compile your source, you can say:
ocamlc -pp camlp4o -o myfile myfile.ml
I believe the complexities of the #load command are required only when you want to use the extensions in the toplevel (the interpreter).

Related

How to generate bitcode (.bc file) using emscripten with a cmake project?

I have a c++ project that I built with cmake. It compiles and links fine. The goal is to use Emscripten to generate code from it that will run in the browser.
From the docs on the Emscripten site here one finds:
After running the first two commands (emconfigure and emmake), seemingly successfully, I do not have any .bc file anywhere, although it actually does produce a .js and .wasm file. The docs imply there that the .js file would only result from executing the third command ./emcc.
A little further down on the same docs page you find:
Make generates linked LLVM bitcode. It does not automatically generate
JavaScript during linking because all the files must be compiled using
the same optimizations and compiler options — and it makes sense to do
this in the final conversion from bitcode to JavaScript.
so it seems it should produce some bitcode. How to do this?
(I did use the VERBOSE command as those docs suggest and although I do not see emcc being used instead of the native compiler, em++ is being used, which seems to mostly the same as emcc.)
When the Emscripten build system is used to build a project, it will always generate a bitcode file. This is regardless of the file extension of the default output file. It can't generate a different file, since that would confuse Make, with the file not being created that it was told would be. At the Emscripten website there is a note a short way down the page that says:
The file output from make might have a different suffix: .a for a static library archive, .so for a shared library, .o or .bc for object files (these file extensions are the same as gcc would use for the different types). Irrespective of the file extension, these files contain linked LLVM bitcode that emcc can compile into JavaScript in the final step. If the suffix is something else - like no suffix at all, or something like .so.1 - then you may need to rename the file before sending it to emcc.
Whatever files the build is supposed to create, even ones that are usually shared libraries, will always contain the bitcode, and can be linked directly with the rest of your project.
Edit:
I can only assume that the reason for the .js output file is because the CMake project is set up to produce an executable. It is possible that Emscripten is smart enough to create .js in that case, but I don't know for sure.
From the manpage of emscripten:
The target file, if specified (-o <target>), defines what will be generated:
<name>.js
JavaScript
<name>.html
HTML with embedded JavaScript
<name>.bc
LLVM bitcode (default)
<name>.o
LLVM bitcode (same as .bc)
I assume you can just then create a custom command where the output file has the extension .bc to produce bitcode. Seems like you could just skip the hassle potentially by going straight to producing .js from .c(pp).
Edit:
Alternatively, if you just want it as a side-effect and not the actual product:
--save-bc PATH
When compiling to JavaScript or HTML, this option will save a copy of the bitcode to the specified
path. The bitcode will include all files being linked, including standard libraries, and after any
link-time optimizations (if any).
Depending on the project, you may be able to skip configure entirely. In the past, i've specified C functions to export that my Wasm implementation would then use to quickly build from. Some C libraries require autogen to be run at a minimum, but I have bypassed configure for multi-dependency C projects.
# create bitcode library for WebAssembly module
$ emcc \
-o wasmlib.bc \
-s EXPORTED_FUNCTIONS="[ \
'_needed_c_function1' \
'_needed_c_function2', \
]" \
-I "c_lib_src/include" \
c_lib_src/*.c
# Quickly build using the bitcode we just created
$ emcc \
-o my_wasm_module.js \
-I "c_lib_src/include" \
wasmlib.bc \
my_wasm_impl.c
Up until Emscripten 1.38.x fastcomp you could use the CMake option EMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES set to ON and static libraries would end up being .bc files:
cmake -Bbuild -DEMSCRIPTEN_GENERATE_BITCODE_STATIC_LIBRARIES=ON
To check, inspected in a hex-editor those .bc files start with BC.
The option was removed (and throws an error) in recent upstream Emscripten versions (like 2.0.x). I still have to figure out, how it's done there.

Loading OCaml modules not in the current directory

I'm writing a large OCaml project. I wrote a file foo.ml, which works perfectly. In a subdirectory of foo.ml's directory, there is a file bar.ml.
bar.ml references code in foo.ml, so its opening line is:
open Foo
This gives me an error at compile time:
Unbound module Foo.
What can I do to fix this without changing the location of foo.ml?
The easy path is to use one of OCaml build system like ocamlbuild or oasis. Another option would be jbuilder but jbuilder is quite opiniated about file organization and does not allow for the kind of subdirectory structure that you are asking for.
The more explicit path comes with a warning: OCaml build process is complicated with many moving parts that can be hard to deal with.
After this customary warning, when looking for modules, OCaml compiler first looks for module in the current compilation environment, then looks for compiled interface ".cmi" files in the directories specified by the "-I" option flags (plus the current directory and the standard library directory).
Thus in order to compile your bar.ml file, you will need to add the parent directory in the list of included directories with the -I .. option.
After all this, you will discover that during the linking phase, all object files (i.e. .cmo or .cmx) need to be listed in a topological order compatible with the dependency graph of your project.
Consequently, let me repeat my advice: use a proper build system.

Don't Link all Standard Library Modules when Compiling OCaml

I'm putting together an intro OCaml project for a CS class and part of it involves implementing list operations. I want them to be able to use Pervasives, but not List or any other standard library modules. Is there a way to set up ocamlbuild so it only links against Pervasives in the standard library?
You can use the -nostdlib option of the compilers but that will hide both Pervasives and List.
What you want is difficult to achieve since both compilation units are part of the same library archive namely stdlib.cma.
You could maybe try to compile your own copy of Pervasives and use the above flag.
I see two opportunities: either remove module directly from the OCaml standard library or hide them by overloading with a module with different (possibly empty) signature.
The first variant requires editing OCaml distribution Makefiles. With opam and is not that scary, actually, as you can patch OCaml quite easily and distribute each patched OCaml as a separate compiler. To remove module from the stdlib archive you will need to edit stdlib/Makefile.shared, stdlib/StdlibModules, and stdlib.mllib. After you've removed the unnecessary modules, you can do:
./configure
make world.opt
make install
Another option is to (ab)use the -open command line argument of ocamlc. When this option is specified with a name of a module, this module will be automatically opened in the compiled program. For example, you can write your own overlay over a standard library, that has the following interface (minimal.mli):
module List = sig end (* or whatever you want to expose *)
and then you can compile either with ocamlc -open minimal ..., or, with ocamlbuild: ocamlbuild -cflags -open,minimal ... (you can also use _tags file to pass the open flag, or write an ocamlbuild plugin).

What's the purpose of _tags file with OCaml, and how to interpret the contents?

From Building OCaml code that uses list comprehension post, I can use _tags file to execute ocamlbuild with less build options.
$ cat _tags
<**/*> : package(camlp4),syntax(camlp4o),package(pa_comprehension)
From the Batteries introduction, I also need to have _tags file to use Batteries package.
<*>: package(batteries)
Why the first example uses <**/*> when the second example uses <*>? In general, what's the purpose of _tags file in ocamlbuild? Do you have some good tutorials on it?
A _tags file in addition to myocamlbuild.ml forms the root of the ocamlbuild compilation system.
ocamlbuild is a very generic tool, that can compile anything. It is driven by a solver, that according to the target, set by a user, finds a solution that can satisfy the target. The solution is a chain of rules that are applied to files. Files can be tagged by tags. Tags can alter rules. For example, it can add flags, like enabling profiling or linking to a library.
A _tags file provides a mechanism to assign tags to files and it has a simple grammar:
pattern ":" tag "," {tag}.
What is to the left of : is actually a pattern or regular expression. Each file that matches the expression will be assigned with all tags that occur to the right of :.
<**/*> means for all files in this folder, and all subfolders, there is a shortcut for this: true. <*> means for all files on this folder (without descending into subfolders). Other examples are <*.ml>, <*.cmx> or <**/*.cma> (btw or can also be used to build a pattern).
OCamlbuild is documented in OCaml Manual, also there is a dump of old wiki, with lots of information.
But the fun part is that usually you do not need to know this in order to use OCaml. There is an OASIS tool that will automate all tasks, and create _tags file for you from a simple and high-level definition.

Creating an OCaml library

I am trying to create a library that I can use in other OCaml projects, and I'm totally lost.
I'm currently using ocamlbuild which is great for spitting out executables, but I don't know how to get a library out of it.
I've discovered the -a option in ocamlopt and ocamlc but I'm not really sure how to use it. The documentation I've found (for example, here), seems to assume some preexisting knowledge. I don't even know what a .a file is. After I run that, which of the outputted files do I need to build a project that depends on this library? Do I need the mli files so that the application knows the signatures of the library code, or is that included in the output somehow? Also, it would be nice to be able to package all the files together, something similar to a .jar file for Java.
In any case, I would love for ocamlbuild to do all of this for me, since if I have to invoke ocamlopt -a I will have to either manually specify dependencies or hack a script around ocamldep -- something that ocamlbuild was supposed to fix. However, I don't know how to tell it to build a library.
I'm willing to use oasis or OPAM or something if it's necessary, but I would like to learn how to do this using just the basic tools first.
OCamlbuild has some built-in functionality for building libraries, so you can get started with just ocamlbuild foo.cma foo.cmxa (assuming foo.ml is your entry point). This will invoke ocamlopt -a and ocamlc -a for you, handling all the dependency plumbing and leaving the generated files inside _build.
That should be enough to let you compile a library and link it from another program. Since this is just a test you can simply point at the aforementioned _build with -I when compiling the program that uses the library. For real use a library should be packaged - when you get to that point you'll want to look into ocamlfind, oasis, etc.
Have a look at the ocaml.org tutorial on compiling OCaml projects. Additionally the official manual for the bytecode and native code compilers contains useful detail on producing and using the various types of files.
The documentation for ocamlbuild archives seems to cover this pretty well.
In any case, here's one way to do ocaml libraries. Let's say you have a directory called foo containing your .ml, .mli, and .mllib files. Let's say it contained bar.ml, bar.mli, baz.ml, and baz.mli. To distribute all this as one library, you'd also have a foo.mllib in that directory, whose contents are
Bar
Baz
Then to compile, do
$ ocamlbuild -use-ocamlfind foo.cma foo.cmxa
Here is an example.
Then to use your library foo, let's say you had a sibling directory called main, and main contains main.ml, _tags, myocamlbuild.ml.
myocamlbuild.ml should have the following contents:
open Ocamlbuild_plugin
open Command
let () =
dispatch (
function
| After_rules ->
ocaml_lib
~extern:true
~dir:"/path/to/foo/_build"
"foo"
| _ -> ()
)
_tags should have the following contents:
<main.{ml,native,byte}>: use_foo
Compile main.ml with
$ ocamlbuild -use-ocamlfind main.byte main.native
run with
$ ./main.byte
$ ./main.native
More information here as well: https://ocaml.org/learn/tutorials/ocamlbuild/Using_an_external_library.html