├── missdep └── .ignore ├── use_missdep.ml ├── use_b.ml ├── BRZO ├── use_e.ml ├── a ├── a.ml └── a.mli ├── b ├── b.ml └── b.mli ├── c ├── c.ml └── c.mli ├── use_d.ml ├── use_f.ml ├── e ├── e.ml └── e.mli ├── d ├── d.ml └── d.mli ├── use_da.ml ├── .gitignore ├── f ├── f.ml ├── f_stubs.c └── f.mli ├── require.ml ├── Makefile └── manual.md /missdep/.ignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /use_missdep.ml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /use_b.ml: -------------------------------------------------------------------------------- 1 | let b = Sys.opaque_identity (B.v 1) 2 | -------------------------------------------------------------------------------- /BRZO: -------------------------------------------------------------------------------- 1 | (domain cmark) 2 | (srcs-x .) 3 | (srcs-i manual.md) 4 | -------------------------------------------------------------------------------- /use_e.ml: -------------------------------------------------------------------------------- 1 | (* *) 2 | 3 | let v = Sys.opaque_identity (E.v 3 2) 4 | -------------------------------------------------------------------------------- /a/a.ml: -------------------------------------------------------------------------------- 1 | type t = int 2 | let v i = i 3 | let () = print_endline "init a.A" 4 | -------------------------------------------------------------------------------- /b/b.ml: -------------------------------------------------------------------------------- 1 | type t = A.t 2 | let v = A.v 3 | let () = print_endline "init b.B" 4 | -------------------------------------------------------------------------------- /c/c.ml: -------------------------------------------------------------------------------- 1 | type t = A.t 2 | let v = A.v 3 | let () = print_endline "init c.C" 4 | -------------------------------------------------------------------------------- /use_d.ml: -------------------------------------------------------------------------------- 1 | let b = Sys.opaque_identity (D.b 1) 2 | let c = Sys.opaque_identity (D.c 1) 3 | -------------------------------------------------------------------------------- /use_f.ml: -------------------------------------------------------------------------------- 1 | let f = Sys.opaque_identity (F.v ()) 2 | let () = print_endline (string_of_int (F.f ())) 3 | -------------------------------------------------------------------------------- /e/e.ml: -------------------------------------------------------------------------------- 1 | 2 | type t = D.b * D.c 3 | let v b c = D.b b, D.c c 4 | 5 | let () = print_endline "init e.E" 6 | -------------------------------------------------------------------------------- /d/d.ml: -------------------------------------------------------------------------------- 1 | type b = B.t 2 | type c = C.t 3 | let b = B.v 4 | let c = C.v 5 | 6 | let () = print_endline "init d.D" 7 | -------------------------------------------------------------------------------- /a/a.mli: -------------------------------------------------------------------------------- 1 | (* Lib [a] has no dependency. 2 | Clients of [a] need to require [a]. *) 3 | 4 | type t 5 | val v : int -> t 6 | -------------------------------------------------------------------------------- /use_da.ml: -------------------------------------------------------------------------------- 1 | 2 | let a = Sys.opaque_identity (A.v 2) 3 | let b = Sys.opaque_identity (D.b 1) 4 | let c = Sys.opaque_identity (D.c 1) 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.so 3 | *.o 4 | *.cma 5 | *.cmxa 6 | *.cmi 7 | *.cmo 8 | *.cmx 9 | *.cmxs 10 | *.native 11 | *.byte 12 | *.top 13 | _b0 -------------------------------------------------------------------------------- /f/f.ml: -------------------------------------------------------------------------------- 1 | 2 | external f : unit -> int = "ocaml_f" 3 | type t = E.t 4 | let v () = E.v 53 (f ()) 5 | let () = 6 | ignore (v ()); 7 | print_endline "init f.F" 8 | -------------------------------------------------------------------------------- /c/c.mli: -------------------------------------------------------------------------------- 1 | (* Lib [c] depends on [a] but makes that abstract in his interface. 2 | a ... c 3 | 4 | Clients of [c] need to require [c]. *) 5 | 6 | type t 7 | val v : int -> t 8 | -------------------------------------------------------------------------------- /b/b.mli: -------------------------------------------------------------------------------- 1 | (* Lib [b] depends on [a] and shows it in its interface. 2 | a --- b 3 | 4 | Clients of [b] need to require [b] and [a]. *) 5 | 6 | type t = A.t 7 | val v : int -> t 8 | -------------------------------------------------------------------------------- /f/f_stubs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | CAMLprim value ocaml_f (value unit) 5 | { 6 | CAMLparam1 (unit); 7 | CAMLreturn (Val_int (42)); 8 | } 9 | -------------------------------------------------------------------------------- /e/e.mli: -------------------------------------------------------------------------------- 1 | (* Lib [e] depends on [d] but makes this abstract in its iterface. 2 | 3 | a ... c --\ 4 | \ d ... e 5 | \--- b --/ 6 | 7 | Clients of [e] need only to require [e]. *) 8 | 9 | type t 10 | val v : int -> int -> t 11 | -------------------------------------------------------------------------------- /f/f.mli: -------------------------------------------------------------------------------- 1 | 2 | (* Lib [f] depends on [e] but makes this abstract in its iterface. 3 | It also has a c binding. 4 | 5 | a ... c --\ 6 | \ d ... e ... f 7 | \--- b --/ 8 | 9 | Clients of [f] need only to require [f]. *) 10 | 11 | type t 12 | val f : unit -> int 13 | val v : unit -> t 14 | -------------------------------------------------------------------------------- /require.ml: -------------------------------------------------------------------------------- 1 | 2 | let ocamlpath = ["."] 3 | 4 | let require arg = try Dynlink.require ~ocamlpath arg with 5 | | Dynlink.Error e -> 6 | Printf.printf "require %s: %s" arg (Dynlink.error_message e); exit 2 7 | 8 | let main () = 9 | let reqs = List.tl (Array.to_list Sys.argv) in 10 | Dynlink.allow_unsafe_modules true; 11 | List.iter require reqs; 12 | exit 0 13 | 14 | let () = main () 15 | -------------------------------------------------------------------------------- /d/d.mli: -------------------------------------------------------------------------------- 1 | (* Lib [d] depends on [b] and [c] and shows it in its interface since 2 | [b] didn't make its usage of [a] abstract it also depends on 3 | [a] and so do its clients. 4 | 5 | a .... c --\ 6 | \ d 7 | \--- b --/ 8 | 9 | Clients of [d] need to require [b], [c] and [a] (via [b]) aswell. 10 | *) 11 | 12 | type b = B.t 13 | type c = C.t 14 | val b : int -> b 15 | val c : int -> c 16 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | 3 | # The library graph is as follows with ... denoting fully abstract 4 | # dependencies (the library does not rexeport constructs of its 5 | # dependencies in its interface). [a] has no deps, [f] depends on 6 | # everthing and has C stubs. 7 | # 8 | # /... c --\ 9 | # a d ... e ... f 10 | # \--- b --/ 11 | # 12 | # 13 | 14 | default: lib-a lib-b lib-c lib-d lib-e lib-f lib-missdep use-d use-da use-e \ 15 | top-use-e top-use-b use-f require 16 | 17 | .PHONY: lib-a lib-b lib-c lib-d lib-e lib-f use-d use-e use-f top-use-e \ 18 | top-use-b use-da use-e use-f use-da-fail use-da-fail-native use-b-fail \ 19 | use-b-fail-native use-missdep use-missdep-native require clean 20 | 21 | clean: 22 | rm -f */*.cmi */*.cmo */*.cmx */*.cma */*.cmxa */*.cmxs */*.a */*.o */*.so \ 23 | *.cmi *.cmo *.cmx *.byte *.native *.o *.top 24 | 25 | lib-a: 26 | ocamlc -L . -c a/a.mli 27 | ocamlc -L . -c a/a.ml -I a 28 | ocamlc -L . -a -o a/lib.cma a/a.cmo 29 | ocamlopt -L . -c a/a.ml -I a 30 | ocamlopt -L . -a -o a/lib.cmxa a/a.cmx 31 | ocamlopt -L . -linkall -shared -o a/lib.cmxs a/lib.cmxa 32 | 33 | lib-b: lib-a 34 | ocamlc -L . -c b/b.mli -require a 35 | ocamlc -L . -c b/b.ml -I b -require a 36 | ocamlc -L . -a -o b/lib.cma b/b.cmo -require a 37 | ocamlopt -L . -c b/b.ml -I b -require a 38 | ocamlopt -L . -a -o b/lib.cmxa b/b.cmx -require a 39 | ocamlopt -L . -linkall -shared -o b/lib.cmxs b/lib.cmxa 40 | 41 | lib-c: lib-a 42 | ocamlc -L . -c c/c.mli -require a 43 | ocamlc -L . -c c/c.ml -I c -require a 44 | ocamlc -L . -a -o c/lib.cma c/c.cmo -require a 45 | ocamlopt -L . -c c/c.ml -I c -require a 46 | ocamlopt -L . -a -o c/lib.cmxa c/c.cmx -require a 47 | ocamlopt -L . -linkall -shared -o c/lib.cmxs c/lib.cmxa 48 | 49 | lib-d: lib-b lib-c 50 | ocamlc -L . -c d/d.mli -require b -require c 51 | ocamlc -L . -c d/d.ml -I d -require b -require c 52 | ocamlc -L . -a -o d/lib.cma d/d.cmo -require b -require c 53 | ocamlopt -L . -c d/d.ml -I d -require b -require c 54 | ocamlopt -L . -a -o d/lib.cmxa d/d.cmx -require b -require c 55 | ocamlopt -L . -linkall -shared -o d/lib.cmxs d/lib.cmxa 56 | 57 | lib-e: lib-d 58 | ocamlc -L . -c e/e.mli -require d 59 | ocamlc -L . -c e/e.ml -I e -require d 60 | ocamlc -L . -a -o e/lib.cma e/e.cmo -require d 61 | ocamlopt -L . -c e/e.ml -I e -require d 62 | ocamlopt -L . -a -o e/lib.cmxa e/e.cmx -require d 63 | ocamlopt -L . -linkall -shared -o e/lib.cmxs e/lib.cmxa 64 | 65 | lib-f: lib-e 66 | ocamlc -L . -c f/f.mli -require e 67 | ocamlc -L . -c f/f.ml -I f -require e 68 | ocamlopt -L . -c f/f.ml -I f -require e 69 | ocamlc -L . -c f/f_stubs.c 70 | mv f_stubs.o f/ 71 | ocamlmklib -o f/lib -oc f/f f/f.cmo f/f.cmx f/f_stubs.o -require e 72 | ocamlopt -linkall -shared -o f/lib.cmxs f/lib.cmxa 73 | 74 | lib-missdep: 75 | # This is ok, lookup is done at link time. 76 | ocamlc -L . -a -o missdep/lib.cma -require does.not.exist 77 | ocamlopt -L . -a -o missdep/lib.cmxa -require does.not.exist 78 | 79 | use-d: lib-d 80 | ocamlc -L . -c use_d.ml -require d 81 | ocamlc -L . -o use_d.byte use_d.cmo -require d 82 | ocamlopt -L . -c use_d.ml -require d 83 | ocamlopt -L . -o use_d.native use_d.cmx -require d 84 | 85 | use-da: lib-d 86 | ocamlc -L . -c use_da.ml -require a -require d 87 | ocamlc -L . -o use_da.byte use_da.cmo -require d # Does not fail but comp fails 88 | ocamlopt -L . -c use_da.ml -require a -require d 89 | ocamlopt -L . -o use_da.native use_da.cmx -require d # Does not fail but comp fails 90 | 91 | use-e: lib-e 92 | ocamlc -L . -c use_e.ml -require e 93 | ocamlc -L . -o use_e.byte use_e.cmo -require e 94 | ocamlopt -L . -c use_e.ml -require e 95 | ocamlopt -L . -o use_e.native use_e.cmx -require e 96 | # Alternate init sequence 97 | ocamlc -L . -o use_e_alt.byte use_e.cmo -require c -require b -require e 98 | ocamlopt -L . -o use_e_alt.native use_e.cmx -require c -require b -require e 99 | 100 | use-f: lib-f 101 | ocamlc -L . -c use_f.ml -require f 102 | # Normally the dll would be installed at the right place 103 | CAML_LD_LIBRARY_PATH=./f ocamlc -L . -o use_f.byte use_f.cmo -require f 104 | ocamlc -L . -custom -o use_f_custom.byte use_f.cmo -require f 105 | ocamlopt -L . -c use_f.ml -require f 106 | ocamlopt -L . -o use_f.native use_f.cmx -require f 107 | 108 | top-use-e: lib-e 109 | ocamlmktop -L . -o use_e.top -require e 110 | 111 | top-use-b: lib-b 112 | ocamlmktop -L . -o use_b.top -require b 113 | 114 | use-da-fail: lib-d 115 | ocamlc -L . -c use_da.ml -require d 116 | 117 | use-da-fail-native: lib-d 118 | ocamlopt -L . -c use_da.ml -require d 119 | 120 | use-b-fail: lib-d 121 | ocamlc -L . -c use_b.ml -require b 122 | ocamlc -L . -o use_b.byte use_b.cmo -require b -noautoliblink 123 | 124 | use-b-fail-native: lib-d 125 | ocamlopt -L . -c use_b.ml -require b 126 | ocamlopt -L . -o use_b.native use_b.cmx -require b -noautoliblink 127 | 128 | use-missdep: lib-missdep 129 | ocamlc -L . -c use_missdep.ml -require missdep 130 | ocamlc -L . -o use_missdep use_missdep.cmo -require missdep 131 | 132 | use-missdep-native: lib-missdep 133 | ocamlopt -L . -c use_missdep.ml -require missdep 134 | ocamlopt -L . -o use_missdep use_missdep.cmx -require missdep 135 | 136 | require: 137 | ocamlc -L . -o require.byte dynlink.cma require.ml 138 | ocamlopt -L . -o require.native dynlink.cmxa require.ml 139 | ocamlc -L . -linkall -o require_has_implicit_a.byte \ 140 | dynlink.cma a/lib.cma require.ml -assume-library a 141 | ocamlopt -L . -linkall -o require_has_implicit_a.native \ 142 | dynlink.cmxa a/lib.cmxa require.ml -assume-library a 143 | ocamlc -L . -linkall -o require_has_d.byte dynlink.cma require.ml -require d 144 | ocamlopt -L . -linkall -o require_has_d.native dynlink.cmxa \ 145 | require.ml -require d 146 | CAML_LD_LIBRARY_PATH=./f \ 147 | ocamlc -L . -linkall -o require_has_f.byte dynlink.cma require.ml -require f 148 | ocamlopt -L . -linkall -o require_has_f.native dynlink.cmxa require.ml -require f 149 | -------------------------------------------------------------------------------- /manual.md: -------------------------------------------------------------------------------- 1 | # OCaml library convention 2 | 3 | Historically OCaml library management has been provided by the 4 | third-party tool `ocamlfind`. Since vX.Y.Z, the toolchain provides 5 | direct support for using libraries installed according to the library 6 | convention described in this section. 7 | 8 | Libraries installed according to the convention can be used as 9 | `ocamlfind` packages transparently. The OCaml toolchain however does 10 | not understand `ocamlfind` packages. Moving to the simpler OCaml 11 | library convention is encouraged. 12 | 13 | *Note on terminology.* `.cma`, `.cmxa` or `.cmxs` may sometimes be 14 | mentioned in the wild as being *libraries*. Technically these are 15 | *archives* or *library archives* and should not be confused with 16 | libraries as defined by this convention; archives are an 17 | implementation detail of it. Also the `ocamlfind` tool uses (most of 18 | the time) the term *package* for what the OCaml library convention 19 | calls a *library*. 20 | 21 | ## Libraries and OCAMLPATH 22 | 23 | A *library* is a named set of modules designed to be used and 24 | distributed together. Each library is installed in its own, isolated, 25 | *library directory*. 26 | 27 | The compiler looks for library directories in the root directories 28 | defined in the `OCAMLPATH` environment variable. The *name* of a 29 | library is the relative path up to its root directory with directory 30 | separators substituted by the character `.` (U+002E). For example with 31 | the following `OCAMLPATH` definition: 32 | 33 | ``` 34 | OCAMLPATH=/home/bactrian/opam/lib:/usr/lib/ocaml 35 | ``` 36 | 37 | We get the following map between library directories and library names: 38 | 39 | ``` 40 | Library directory Library name 41 | ---------------------------------------------------------------- 42 | /home/bactrian/opam/lib/ptime/clock/jsoo ptime.clock.jsoo 43 | /home/bactrian/opam/lib/re/emacs re.emacs 44 | /usr/lib/ocaml/ocamlgraph ocamlgraph 45 | /usr/lib/ocaml/ocaml/unix ocaml.unix 46 | /usr/lib/ocaml/re/emacs N/A (shadowed) 47 | /haha/hihi/hoho N/A (not in a root dir) 48 | ``` 49 | 50 | In library names, each `.` separated segment (and thus directory name) 51 | must be a non-empty, uncapitalized OCaml compilation unit name except 52 | for the `-` (U+002D) character which is also allowed. Even though this 53 | is not checked by the toolchain, having segment names in the same 54 | directory that differ only by their `_` and - characters must not be 55 | done (e.g. `dir.foo-bar` and `dir.foo_bar`). 56 | 57 | A library directory always defines a single library. It can contain 58 | subdirectories which have other libraries but there is no connection 59 | between them except for the name prefix they share. 60 | 61 | The `OCAMLPATH` variable follows the usual conventions for `PATH`-like 62 | environment variables. Directories are separated by the platform 63 | specific separator, namely `:` (U+003A) on POSIX platforms, `;` 64 | (U+003B) on Windows platforms. Empty paths are allowed and 65 | discarded. If the same library name is available in more than one 66 | root directory of `OCAMLPATH` the leftmost one takes over. 67 | 68 | The `ocamlc -ocamlpath` invocation returns the current value of the 69 | `OCAMLPATH`. This is either the value of the `OCAMLPATH` environment 70 | variable or, if undefined, a default set at OCaml configuration time. 71 | 72 | The toolchain supports prepending to the `OCAMLPATH` directly on the 73 | command line via the `-L DIR` option. 74 | 75 | ## Using libraries 76 | 77 | To use a library for compiling and linking use the `-require` option. 78 | For example to compile a `test.ml` file with the `re.emacs` library 79 | invoke: 80 | 81 | ``` 82 | ocamlc -require re.emacs test.ml 83 | ``` 84 | 85 | this includes the library directory of `re.emacs` during compilation 86 | and links the library's modules and its dependencies for producing the 87 | final executable. 88 | 89 | In the OCaml toplevel (REPL) use the corresponding `#require` 90 | directive. This loads the library's modules and its dependencies and 91 | adds its directory to the includes: 92 | 93 | ``` 94 | ocaml 95 | 96 | OCaml version 4.09.0 97 | 98 | # #require "re.emacs" 99 | ``` 100 | 101 | Invoking `ocaml` with `ocaml -require re.emacs` is strictly equivalent. 102 | 103 | The current value of the `OCAMLPATH` can be output with the 104 | `-ocamlpath` option: 105 | 106 | ``` 107 | ocamlc -ocamlpath 108 | /usr/lib/ocaml:/usr/local/lib/ocaml 109 | ``` 110 | 111 | This outputs either the value of the `OCAMLPATH` environment variable 112 | or the default value set at OCaml configuration time if it is 113 | undefined. 114 | 115 | ``` 116 | (unset OCAMLPATH; ocamlc -ocamlpath) # Show default value 117 | ``` 118 | 119 | If you need to extend the `OCAMLPATH` for your environment you can use: 120 | 121 | ``` 122 | export OCAMLPATH=~/.local/lib/ocaml:$(ocamlc -ocamlpath) 123 | ``` 124 | 125 | It is also possible to extend it directly on the command line via `-L` 126 | option which prepends root directories to the `OCAMLPATH` starting 127 | from the right. These two invocations are equivalent: 128 | 129 | ``` 130 | ocamlc -L foo -L bar -require re.emacs test.ml 131 | OCAMLPATH=foo:bar:$(ocamlc -ocamlpath) ocamlc -require re.emacs test.ml 132 | ``` 133 | 134 | ## Defining libraries 135 | 136 | The directory of a library holds all the compilation objects of the 137 | modules it defines and archives them into `lib.{cma,cmxa,cmxs,a}` (as 138 | needed) files. For a library named `mylib` with modules 139 | `m0`, ..., `mn`. the library directory has the following files: 140 | 141 | ``` 142 | mylib/{m0,...,mn}.{cmi,cmx,cmti,cmt} 143 | mylib/lib.{cma,cmxa,cmxs,a} 144 | ``` 145 | 146 | The following constraints are assumed to hold on a library directory. 147 | 148 | 1. `m.{cmti,cmt}` files are optional they do however enhance other tools. 149 | `m.cmti` files are needed for documentation generation. 150 | 2. If a `m.cmx` has no `m.cmi` then the module is private to the library. 151 | 3. If a `m.cmi` has no `m.cmx` and no implementation in the archives then it 152 | is an `mli`-only module. 153 | 4. If there is a `m.cmx` file there must be a `lib.cmxa`. Any `m.cmx` 154 | must also be present in the `lib.cmxa` archive. 155 | 6. If there is a `lib.cmxa` there must be a `lib.a` unless `lib.cmxa` 156 | is empty (since 4.12). 157 | 7. FIXME discuss. All `lib.{cma,cmxa,cmxs}` files (as available) contain the 158 | same compilation units. 159 | 8. FIXME discuss. All `lib.{cma,cmxa,cmxs}` files (as available) contain the 160 | same dependency specifications. 161 | 9. Empty archives are allowed. They can 162 | contain library dependency specifications which are used at link time. 163 | 10. A missing library archive means that the library is not available for the 164 | given code backend, failures are reported on usage at link time. This 165 | entails that a library made from `mli`-only modules must install empty 166 | `lib.{cma,cmxa,cmxs}` files in its library directory so that the library 167 | can be used both during the compilation and link phase without users 168 | needing to know it has no implementations. 169 | 170 | Library dependencies are used to indicate that a particular library 171 | uses other ones for implementing its modules. Dependencies are 172 | specified as library names which are resolved at link time in the 173 | `OCAMLPATH`. The toolchain is in charge of resolving and sorting the 174 | dependencies of libraries specified via `-require` options at link 175 | time. 176 | 177 | Library dependencies are stored as library names in library 178 | archives. They are specified by using the `-require` flag during 179 | archive creation (`-a` option). Note that dependencies are not 180 | resolved during archive creation and do not need to exist in the 181 | `OCAMLPATH` at that time. 182 | 183 | For example the following generates library archives for a library 184 | `mylib` that needs `re.emacs` at link time: 185 | 186 | ``` 187 | ocamlc -require re.emacs -a -o mylib/lib.cma a.cmo b.cmo 188 | ocamlopt -require re.emacs -a -o mylib/lib.cmxa a.cmx b.cmx 189 | ``` 190 | 191 | Assuming you have a library `mylib` with modules `{a,b}.{mli,ml}` 192 | whose implementations depends on `re.emacs` here are full instructions 193 | on how to define it's library directory in `mylib` according to the 194 | convention: 195 | 196 | ``` 197 | mkdir -p mylib 198 | 199 | # Compile interfaces 200 | ocamlc -bin-annot -c -o mylib/a.cmi a.mli 201 | ocamlc -bin-annot -c -o mylib/b.cmi b.mli 202 | 203 | # Compile bytecode objects 204 | ocamlc -bin-annot -c -o mylib/a.cmo -I mylib -require re.emacs a.ml 205 | ocamlc -bin-annot -c -o mylib/b.cmo -I mylib -require re.emacs b.ml 206 | ocamlc -a -o mylib/lib.cma -require re.emacs mylib/a.cmo mylib/b.cmo 207 | 208 | # Compile native code objects 209 | ocamlopt -c -o mylib/a.cmx -I mylib -require re.emacs a.ml 210 | ocamlopt -c -o mylib/b.cmx -I mylib -require re.emacs b.ml 211 | ocamlopt -a -o mylib/lib.cmxa -require re.emacs mylib/a.cmx mylib/b.cmx 212 | ocamlopt -a -o mylib/lib.cmxa -require re.emacs mylib/a.cmx mylib/b.cmx 213 | ocamlopt -shared -o mylib/lib.cmxs mylib/lib.cmxa 214 | ``` 215 | 216 | ## Example 217 | 218 | In this example we show how to compile and define two libraries to use 219 | locally in a native code build. We have: 220 | 221 | * Library `a` made of sources `a.{mli,ml}` depending on the `ocaml.str` 222 | library. 223 | * Library `b` made of sources `b.{mli,ml}` depending on the library `a`. 224 | * An executable `exec.ml` which depends on `b` 225 | 226 | Here are our sources: 227 | 228 | ``` 229 | . 230 | ├── a.mli 231 | ├── a.ml 232 | ├── b.mli 233 | ├── b.ml 234 | └── exec.ml 235 | ``` 236 | We create directories for the libraries. The `libs` directory 237 | will be added to the `OCAMLPATH` via `-L`. 238 | 239 | ``` 240 | mkdir -p libs/a libs/b 241 | ``` 242 | 243 | We compile and define library `a`: 244 | 245 | ``` 246 | ocamlopt -bin-annot -c -o libs/a/a.cmi a.mli 247 | ocamlopt -bin-annot -c -o libs/a/a.cmx -I libs/a -require ocaml.str a.ml 248 | ocamlopt -a -o libs/a/lib.cmxa -require ocaml.str libs/a/a.cmx 249 | ``` 250 | 251 | We compile and define library `b`. We extend the `OCAMLPATH` on the 252 | command line with the `-L` option of the toolchain. 253 | 254 | ``` 255 | ocamlopt -bin-annot -c -o libs/b/b.cmi b.mli 256 | ocamlopt -bin-annot -c -o libs/b/b.cmx -L libs -I libs/b -require a b.ml 257 | ocamlopt -a -o libs/b/lib.cmxa -require ocaml.str libs/b/b.cmx 258 | ``` 259 | 260 | We compile our executable: 261 | ``` 262 | ocamlopt -L libs -require b exec.ml 263 | ``` 264 | 265 | ## Packaging OCaml 266 | 267 | If you are packaging OCaml for a system distribution or a package 268 | manager, the resulting install should have a properly setup 269 | `OCAMLPATH` so that by default the OCaml libraries are available under 270 | the `ocaml.*` library name prefix. 271 | 272 | A default `OCAMLPATH` value for when the `OCAMLPATH` environment 273 | variable is undefined can be set by setting OCaml's `configure` script 274 | `DEFAULT_OCAMLPATH` variable. For example with: 275 | 276 | ``` 277 | ./configure DEFAULT_OCAMLPATH=/usr/lib/ocaml:/usr/local/lib/ocaml 278 | ``` 279 | 280 | the default `OCAMLPATH` value will be: 281 | 282 | ``` 283 | /usr/lib/ocaml:/usr/local/lib/ocaml 284 | ``` 285 | 286 | If no value is defined at configuration time, the default `OCAMLPATH` 287 | is empty and only the standard library can be used if the `OCAMLPATH` 288 | environment variable is undefined. 289 | 290 | End user can extend their `OCAMLPATH` by using `ocamlc -ocamlpath`. For 291 | example: 292 | 293 | ``` 294 | export OCAMLPATH=~/.local/lib/ocaml:$(ocamlc -ocamlpath) 295 | ``` 296 | 297 | 298 | --------------------------------------------------------------------------------