Chapter 9 Batch compilation (ocamlc)
- 9.1 Overview of the compiler
- 9.2 Options
- 9.3 Modules and the file system
- 9.4 Common errors
- 9.5 Warning reference
This chapter describes the OCaml batch compiler ocamlc,which compiles OCaml source files to bytecode object files and linksthese object files to produce standalone bytecode executable files.These executable files are then run by the bytecode interpreterocamlrun.
9.1 Overview of the compiler
The ocamlc command has a command-line interface similar to the one ofmost C compilers. It accepts several types of arguments and processes themsequentially, after all options have been processed:
- Arguments ending in .mli are taken to be source files forcompilation unit interfaces. Interfaces specify the names exported bycompilation units: they declare value names with their types, definepublic data types, declare abstract data types, and so on. From thefile x.mli, the ocamlc compiler produces a compiled interfacein the file x.cmi.
Arguments ending in .ml are taken to be source files for compilationunit implementations. Implementations provide definitions for thenames exported by the unit, and also contain expressions to beevaluated for their side-effects. From the file x.ml, the ocamlccompiler produces compiled object bytecode in the file x.cmo. If the interface file x.mli exists, the implementationx.ml is checked against the corresponding compiled interfacex.cmi, which is assumed to exist. If no interfacex.mli is provided, the compilation of x.ml produces acompiled interface file x.cmi in addition to the compiledobject code file x.cmo. The file x.cmi producedcorresponds to an interface that exports everything that is defined inthe implementation x.ml.
Arguments ending in .cmo are taken to be compiled object bytecode. Thesefiles are linked together, along with the object files obtainedby compiling .ml arguments (if any), and the OCaml standardlibrary, to produce a standalone executable program. The order inwhich .cmo and .ml arguments are presented on the command line isrelevant: compilation units are initialized in that order atrun-time, and it is a link-time error to use a component of a unitbefore having initialized it. Hence, a given x.cmo file must comebefore all .cmo files that refer to the unit x.
- Arguments ending in .cma are taken to be libraries of object bytecode.A library of object bytecode packs in a single file a set of objectbytecode files (.cmo files). Libraries are built with ocamlc -a(see the description of the -a option below). The object filescontained in the library are linked as regular .cmo files (seeabove), in the order specified when the .cma file was built. Theonly difference is that if an object file contained in a library isnot referenced anywhere in the program, then it is not linked in.
- Arguments ending in .c are passed to the C compiler, which generatesa .o object file (.obj under Windows). This object file is linkedwith the program if the -custom flag is set (see the description of-custom below).
- Arguments ending in .o or .a (.obj or .lib under Windows)are assumed to be C object files and libraries. They are passed to theC linker when linking in -custom mode (see the description of-custom below).
- Arguments ending in .so (.dll under Windows)are assumed to be C shared libraries (DLLs). During linking, they aresearched for external C functions referenced from the OCaml code,and their names are written in the generated bytecode executable.The run-time system ocamlrun then loads them dynamically at programstart-up time. The output of the linking phase is a file containing compiled bytecodethat can be executed by the OCaml bytecode interpreter:the command named ocamlrun. If a.out is the name of the fileproduced by the linking phase, the command
- ocamlrun a.out arg1 arg2 … argn
executes the compiled code contained in a.out, passing it asarguments the character strings arg1 to argn.(See chapter 11 for more details.)
On most systems, the file produced by the linkingphase can be run directly, as in:
- ./a.out arg1 arg2 … argn
The produced file has the executable bit set, and it manages to launchthe bytecode interpreter by itself.
9.2 Options
The following command-line options are recognized by ocamlc.The options -pack, -a, -c and -output-obj are mutually exclusive.
- -a
Build a library(.cma file)with the object files ( .cmo files)given on the command line, instead of linking them into an executable file.The name of the library must be set with the -o option. If -custom, -cclib or -ccopt options are passed on the commandline, these options are stored in the resulting .cmalibrary. Then,linking with this library automatically adds back the -custom, -cclib and -ccopt options as if they had been provided on thecommand line, unless the -noautolink option is given.
-absname
- Force error messages to show absolute paths for file names.
- -annot
- Dump detailed information about the compilation (types, bindings,tail-calls, etc). The information for file src.mlis put into file src.annot. In case of a type error, dumpall the information inferred by the type-checker before the error.The src.annot file can be used with the emacs commands given inemacs/caml-types.el to display types and other annotationsinteractively.
- -argsfilename
- Read additional newline-terminated command line arguments from filename.
- -args0filename
- Read additional null character terminated command line arguments fromfilename.
- -bin-annot
- Dump detailed information about the compilation (types, bindings,tail-calls, etc) in binary format. The information for file src.ml(resp. src.mli) is put into file src.cmt(resp. src.cmti). In case of a type error, dumpall the information inferred by the type-checker before the error.The .cmt and .cmti files produced by -bin-annot containmore information and are much more compact than the files produced by-annot.
- -c
- Compile only. Suppress the linking phase of thecompilation. Source code files are turned into compiled files, but noexecutable file is produced. This option is useful tocompile modules separately.
- -ccccomp
- Use ccomp as the C linker when linking in “custom runtime” mode (see the -custom option)and as the C compiler for compiling .c source files.
- -cclib-llibname
- Pass the -llibname option to the C linkerwhen linking in “custom runtime” mode (see the -custom option).This causes the given C library to be linked with the program.
- -ccoptoption
- Pass the given option to the C compiler and linker.When linking in “custom runtime” mode, for instance-ccopt -Ldir causes the C linker to search for C libraries indirectory dir.(See the -custom option.)
- -colormode
Enable or disable colors in compiler messages (especially warnings and errors).The following modes are supported:
- auto
- use heuristics to enable colors only if the output supports them(an ANSI-compatible tty terminal);
- always
- enable colors unconditionally;
- never
- disable color output.The default setting is ’auto’, and the current heuristicchecks that the TERM environment variable exists and isnot empty or dumb, and that ’isatty(stderr)’ holds. The environment variable OCAML_COLOR is considered if -color is notprovided. Its values are auto/always/never as above.
-error-stylemode
Control the way error messages and warnings are printed.The following modes are supported:
- short
- only print the error and its location;
- contextual
- like short, but also display the source code snippetcorresponding to the location of the error.The default setting is contextual. The environment variable OCAML_ERROR_STYLE is considered if -error-style isnot provided. Its values are short/contextual as above.
-compat-32
- Check that the generated bytecode executable can run on 32-bitplatforms and signal an error if it cannot. This is useful whencompiling bytecode on a 64-bit machine.
- -config
- Print the version number of ocamlc and a detailedsummary of its configuration, then exit.
- -config-varvar
- Print the value of a specific configuration variable from the-config output, then exit. If the variable does not exist, the exitcode is non-zero. This option is only available since OCaml 4.08,so script authors should have a fallback for older versions.
- -custom
- Link in “custom runtime” mode. In the default linking mode, thelinker produces bytecode that is intended to be executed with theshared runtime system, ocamlrun. In the custom runtime mode, thelinker produces an output file that contains both the runtime systemand the bytecode for the program. The resulting file is larger, but itcan be executed directly, even if the ocamlrun command is notinstalled. Moreover, the “custom runtime” mode enables staticlinking of OCaml code with user-defined C functions, as described inchapter 19.
Unix:
Never use the strip command on executables produced by ocamlc -custom, this would remove the bytecode part of the executable.
Unix:
Security warning: never set the “setuid” or “setgid” bits on executables produced by ocamlc -custom, this would make them vulnerable to attacks.
- -dependocamldep-args
- Compute dependencies, as the ocamldep command would do. The remainingarguments are interpreted as if they were given to the ocamldep command.
- -dllib-llibname
- Arrange for the C shared library dlllibname.so(dlllibname.dll under Windows) to be loaded dynamicallyby the run-time system ocamlrun at program start-up time.
- -dllpathdir
- Adds the directory dir to the run-time search path for sharedC libraries. At link-time, shared libraries are searched in thestandard search path (the one corresponding to the -I option).The -dllpath option simply stores dir in the producedexecutable file, where ocamlrun can find it and use it asdescribed in section 11.3.
- -for-packmodule-path
- Generate an object file (.cmo)that can later be includedas a sub-module (with the given access path) of a compilation unitconstructed with -pack. For instance,ocamlc -for-pack P -c A.mlwill generate a..cmo that canlater be used with ocamlc -pack -o P.cmo a.cmo.Note: you can still pack a module that was compiled without-for-pack but in this case exceptions will be printed with the wrongnames.
- -g
- Add debugging information while compiling and linking. This option isrequired in order to be able to debug the program with ocamldebug(see chapter 16), and to produce stack backtraces whenthe program terminates on an uncaught exception (seesection 11.2).
- -i
- Cause the compiler to print all defined names (with their inferredtypes or their definitions) when compiling an implementation (.mlfile). No compiled files (.cmo and .cmi files) are produced.This can be useful to check the types inferred by thecompiler. Also, since the output follows the syntax of interfaces, itcan help in writing an explicit interface (.mli file) for a file:just redirect the standard output of the compiler to a .mli file,and edit that file to remove all declarations of unexported names.
- -Idirectory
Add the given directory to the list of directories searched forcompiled interface files (.cmi), compiled object code files .cmo,libraries (.cma) and C libraries specified with -cclib -lxxx.By default, the current directory is searched first, then the standardlibrary directory. Directories added with -I are searched after thecurrent directory, in the order in which they were given on the command line,but before the standard library directory. See also option -nostdlib. If the given directory starts with +, it is taken relative to thestandard library directory. For instance, -I +unix adds thesubdirectory unix of the standard library to the search path.
-implfilename
- Compile the file filename as an implementation file, even if itsextension is not .ml.
- -intffilename
- Compile the file filename as an interface file, even if itsextension is not .mli.
- -intf-suffixstring
- Recognize file names ending with string as interface files(instead of the default .mli).
- -labels
- Labels are not ignored in types, labels may be used in applications,and labelled parameters can be given in any order. This is the default.
- -linkall
- Force all modules contained in libraries to be linked in. If thisflag is not given, unreferenced modules are not linked in. Whenbuilding a library (option -a), setting the -linkall option forces allsubsequent links of programs involving that library to link all themodules contained in the library. When compiling a module (option-c), setting the -linkall option ensures that this module willalways be linked if it is put in a library and this library is linked.
- -make-runtime
- Build a custom runtime system (in the file specified by option -o)incorporating the C object files and libraries given on the commandline. This custom runtime system can be used later to executebytecode executables produced with theocamlc -use-runtimeruntime-name option.See section 19.1.6 for more information.
- -match-context-rows
- Set the number of rows of context used for optimization duringpattern matching compilation. The default value is 32. Lower valuescause faster compilation, but less optimized code. This advancedoption is meant for use in the event that a pattern-match-heavyprogram leads to significant increases in compilation time.
- -no-alias-deps
- Do not record dependencies for module aliases. Seesection 8.9 for more information.
- -no-app-funct
- Deactivates the applicative behaviour of functors. With this option,each functor application generates new types in its result andapplying the same functor twice to the same argument yields twoincompatible structures.
- -noassert
- Do not compile assertion checks. Note that the special formassert false is always compiled because it is typed specially.This flag has no effect when linking already-compiled files.
- -noautolink
- When linking .cmalibraries, ignore -custom, -cclib and -ccoptoptions potentially contained in the libraries (if these options weregiven when building the libraries). This can be useful if a librarycontains incorrect specifications of C libraries or C options; in thiscase, during linking, set -noautolink and pass the correct Clibraries and options on the command line.
- -nolabels
- Ignore non-optional labels in types. Labels cannot be used inapplications, and parameter order becomes strict.
- -nostdlib
- Do not include the standard library directory in the list ofdirectories searched forcompiled interface files (.cmi), compiled object code files(.cmo), libraries (.cma), and C libraries specified with-cclib -lxxx. See also option -I.
- -oexec-file
- Specify the name of the output file produced by thecompiler. Thedefault output name is a.out under Unix and camlprog.exe underWindows. If the -a option is given, specify the name of the libraryproduced. If the -pack option is given, specify the name of thepacked object file produced. If the -output-obj option is given,specify the name of the output file produced.If the -c option is given, specify the name of the objectfile produced for the next source file that appears on thecommand line.
- -opaque
- When the native compiler compiles an implementation, by default itproduces a .cmx file containing information for cross-moduleoptimization. It also expects .cmx files to be present for thedependencies of the currently compiled source, and uses them foroptimization. Since OCaml 4.03, the compiler will emit a warning if itis unable to locate the .cmx file of one of those dependencies. The -opaque option, available since 4.04, disables cross-moduleoptimization information for the currently compiled unit. Whencompiling .mli interface, using -opaque marks the compiled .cmiinterface so that subsequent compilations of modules that depend on itwill not rely on the corresponding .cmx file, nor warn if it isabsent. When the native compiler compiles a .ml implementation,using -opaque generates a .cmx that does not contain anycross-module optimization information.
Using this option may degrade the quality of generated code, but itreduces compilation time, both on clean and incrementalbuilds. Indeed, with the native compiler, when the implementation ofa compilation unit changes, all the units that depend on it may needto be recompiled – because the cross-module information may havechanged. If the compilation unit whose implementation changed wascompiled with -opaque, no such recompilation needs to occur. Thisoption can thus be used, for example, to get faster edit-compile-testfeedback loops.
- -openModule
- Opens the given module before processing the interface orimplementation files. If several -open options are given,they are processed in order, just as ifthe statements open!Module1;;…open!ModuleN;;were added at the top of each file.
- -output-obj
- Cause the linker to produce a C object file instead ofa bytecode executable file.This is useful to wrap OCaml code as a C library,callable from any C program. See chapter 19,section 19.7.5. The name of the output object filemust be set with the -o option.This option can also be used to produce a C source file (.c extension)or a compiled shared/dynamic library (.so extension, .dll under Windows).
- -pack
- Build a bytecode object file (.cmo file) and its associated compiledinterface (.cmi) that combines the objectfiles given on the command line, making them appear as sub-modules ofthe output .cmo file. The name of the output .cmo file must begiven with the -o option. For instance,
- ocamlc -pack -o p.cmo a.cmo b.cmo c.cmo
generates compiled files p.cmo and p.cmi describing a compilationunit having three sub-modules A, B and C, corresponding to thecontents of the object files a.cmo, b.cmo and c.cmo. Thesecontents can be referenced as P.A, P.B and P.C in the remainderof the program.
- -pluginplugin
- Dynamically load the code of the given plugin(a .cmo, .cma or .cmxs file) in the compiler. plugin must exist inthe same kind of code as the compiler (ocamlc.byte must loadbytecode plugins, while ocamlc.opt must load native code plugins),and extension adaptation is done automatically for .cma files (to .cmxsfiles if the compiler is compiled in native code).
- -ppcommand
- Cause the compiler to call the given command as a preprocessorfor each source file. The output of command is redirected toan intermediate file, which is compiled. If there are no compilationerrors, the intermediate file is deleted afterwards.
- -ppxcommand
- After parsing, pipe the abstract syntax tree through the preprocessorcommand. The module Ast_mapper, described inchapter 24:Ast_mapper,implements the external interface of a preprocessor.
- -principal
- Check information path during type-checking, to make sure that alltypes are derived in a principal way. When using labelled argumentsand/or polymorphic methods, this flag is required to ensure futureversions of the compiler will be able to infer types correctly, evenif internal algorithms change.All programs accepted in -principal mode are also accepted in thedefault mode with equivalent types, but different binary signatures,and this may slow down type checking; yet it is a good idea touse it once before publishing source code.
- -rectypes
- Allow arbitrary recursive types during type-checking. By default,only recursive types where the recursion goes through an object typeare supported.Note that once you have created an interface using thisflag, you must use it again for all dependencies.
- -runtime-variantsuffix
- Add the suffix string to the name of the runtime library used bythe program. Currently, only one such suffix is supported: d, andonly if the OCaml compiler was configured with option-with-debug-runtime. This suffix gives the debug version of theruntime, which is useful for debugging pointer problems in low-levelcode such as C stubs.
- -stop-afterpass
- Stop compilation after the given compilation pass. The currentlysupported passes are: parsing, typing.
- -safe-string
- Enforce the separation between types string and bytes,thereby making strings read-only. This is the default.
- -short-paths
- When a type is visible under several module-paths, use the shortestone when printing the type’s name in inferred interfaces and error andwarning messages. Identifier names starting with an underscore orcontaining double underscores _ incur a penalty of +10 when computingtheir length.
- -strict-sequence
- Force the left-hand part of each sequence to have type unit.
- -strict-formats
- Reject invalid formats that were accepted in legacy formatimplementations. You should use this flag to detect and fix suchinvalid formats, as they will be rejected by future OCaml versions.
- -unboxed-types
- When a type is unboxable (i.e. a record with a single argument or aconcrete datatype with a single constructor of one argument) it willbe unboxed unless annotated with [@@ocaml.boxed].
- -no-unboxed-types
- When a type is unboxable it will be boxed unless annotated with[@@ocaml.unboxed]. This is the default.
- -unsafe
- Turn bound checking off for array and string accesses (the v.(i) ands.[i] constructs). Programs compiled with -unsafe are thereforeslightly faster, but unsafe: anything can happen if the programaccesses an array or string outside of its bounds.Additionally, turn off the check for zero divisor in integer divisionand modulus operations. With -unsafe, an integer division(or modulus) by zero can halt the program or continue with anunspecified result instead of raising a Division_by_zero exception.
- -unsafe-string
- Identify the types string and bytes, thereby making strings writable.This is intended for compatibility with old source code and should notbe used with new software.
- -use-runtimeruntime-name
- Generate a bytecode executable file that can be executed on the customruntime system runtime-name, built earlier withocamlc -make-runtimeruntime-name.See section 19.1.6 for more information.
- -v
- Print the version number of the compiler and the location of thestandard library directory, then exit.
- -verbose
- Print all external commands before they are executed,in particular invocations of the C compiler and linker in -custom mode.Useful to debug C library problems.
- -vmthread
- Deprecated since OCaml 4.08.0. Compile or link multithreaded programs,in combination with the VM-level threads library described inchapter 28.
- -version or -vnum
- Print the version number of the compiler in short form (e.g. 3.11.0),then exit.
- -wwarning-list
Enable, disable, or mark as fatal the warnings specified by the argumentwarning-list.Each warning can be enabled or disabled, and each warningcan be fatal or non-fatal.If a warning is disabled, it isn’t displayed and doesn’t affectcompilation in any way (even if it is fatal). If a warning isenabled, it is displayed normally by the compiler whenever the sourcecode triggers it. If it is enabled and fatal, the compiler will alsostop with an error after displaying it. The warning-list argument is a sequence of warning specifiers,with no separators between them. A warning specifier is one of thefollowing:
- +num
- Enable warning number num.
- -num
- Disable warning number num.
- @num
- Enable and mark as fatal warning number num.
- +num1..num2
- Enable warnings in the given range.
- -num1..num2
- Disable warnings in the given range.
- @num1..num2
- Enable and mark as fatal warnings inthe given range.
- +letter
- Enable the set of warnings corresponding toletter. The letter may be uppercase or lowercase.
- -letter
- Disable the set of warnings corresponding toletter. The letter may be uppercase or lowercase.
- @letter
- Enable and mark as fatal the set of warningscorresponding to letter. The letter may be uppercase orlowercase.
- uppercase-letter
- Enable the set of warnings correspondingto uppercase-letter.
- lowercase-letter
Disable the set of warnings correspondingto lowercase-letter. Warning numbers and letters which are out of the range of warningsthat are currently defined are ignored. The warnings are as follows.
1
- Suspicious-looking start-of-comment mark.
- 2
- Suspicious-looking end-of-comment mark.
- 3
- Deprecated synonym for the ’deprecated’ alert
- 4
- Fragile pattern matching: matching that will remain complete evenif additional constructors are added to one of the variant typesmatched.
- 5
- Partially applied function: expression whose result has functiontype and is ignored.
- 6
- Label omitted in function application.
- 7
- Method overridden.
- 8
- Partial match: missing cases in pattern-matching.
- 9
- Missing fields in a record pattern.
- 10
- Expression on the left-hand side of a sequence that doesn’t have typeunit (and that is not a function, see warning number 5).
- 11
- Redundant case in a pattern matching (unused match case).
- 12
- Redundant sub-pattern in a pattern-matching.
- 13
- Instance variable overridden.
- 14
- Illegal backslash escape in a string constant.
- 15
- Private method made public implicitly.
- 16
- Unerasable optional argument.
- 17
- Undeclared virtual method.
- 18
- Non-principal type.
- 19
- Type without principality.
- 20
- Unused function argument.
- 21
- Non-returning statement.
- 22
- Preprocessor warning.
- 23
- Useless record with clause.
- 24
- Bad module name: the source file name is not a valid OCaml module name.
- 25
- Deprecated: now part of warning 8.
- 26
- Suspicious unused variable: unused variable that is boundwith let or as, and doesn’t start with an underscore (_)character.
- 27
- Innocuous unused variable: unused variable that is not bound withlet nor as, and doesn’t start with an underscore (_)character.
- 28
- Wildcard pattern given as argument to a constant constructor.
- 29
- Unescaped end-of-line in a string constant (non-portable code).
- 30
- Two labels or constructors of the same name are defined in twomutually recursive types.
- 31
- A module is linked twice in the same executable.
- 32
- Unused value declaration.
- 33
- Unused open statement.
- 34
- Unused type declaration.
- 35
- Unused for-loop index.
- 36
- Unused ancestor variable.
- 37
- Unused constructor.
- 38
- Unused extension constructor.
- 39
- Unused rec flag.
- 40
- Constructor or label name used out of scope.
- 41
- Ambiguous constructor or label name.
- 42
- Disambiguated constructor or label name (compatibility warning).
- 43
- Nonoptional label applied as optional.
- 44
- Open statement shadows an already defined identifier.
- 45
- Open statement shadows an already defined label or constructor.
- 46
- Error in environment variable.
- 47
- Illegal attribute payload.
- 48
- Implicit elimination of optional arguments.
- 49
- Absent cmi file when looking up module alias.
- 50
- Unexpected documentation comment.
- 51
- Warning on non-tail calls if @tailcall present.
- 52 (see 9.5.2)
- Fragile constant pattern.
- 53
- Attribute cannot appear in this context
- 54
- Attribute used more than once on an expression
- 55
- Inlining impossible
- 56
- Unreachable case in a pattern-matching (based on type information).
- 57 (see 9.5.3)
- Ambiguous or-pattern variables under guard
- 58
- Missing cmx file
- 59
- Assignment to non-mutable value
- 60
- Unused module declaration
- 61
- Unboxable type in primitive declaration
- 62
- Type constraint on GADT type declaration
- 63
- Erroneous printed signature
- 64
- -unsafe used with a preprocessor returning a syntax tree
- 65
- Type declaration defining a new ’()’ constructor
- 66
- Unused open! statement
- A
- all warnings
- C
- warnings 1, 2.
- D
- Alias for warning 3.
- E
- Alias for warning 4.
- F
- Alias for warning 5.
- K
- warnings 32, 33, 34, 35, 36, 37, 38, 39.
- L
- Alias for warning 6.
- M
- Alias for warning 7.
- P
- Alias for warning 8.
- R
- Alias for warning 9.
- S
- Alias for warning 10.
- U
- warnings 11, 12.
- V
- Alias for warning 13.
- X
- warnings 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 30.
- Y
- Alias for warning 26.
- Z
- Alias for warning 27. The default setting is -w +a-4-6-7-9-27-29-32..42-44-45-48-50-60.It is displayed by ocamlc -help.Note that warnings 5 and 10 are not always triggered, depending onthe internals of the type checker.
-warn-errorwarning-list
- Mark as fatal the warnings specified in the argument warning-list.The compiler will stop with an error when one of these warnings isemitted. The warning-list has the same meaning as forthe -w option: a + sign (or an uppercase letter) marks thecorresponding warnings as fatal, a -sign (or a lowercase letter) turns them back into non-fatal warnings,and a @ sign both enables and marks as fatal the correspondingwarnings. Note: it is not recommended to use warning sets (i.e. letters) asarguments to -warn-errorin production code, because this can break your build when future versionsof OCaml add some new warnings.
The default setting is -warn-error -a+31 (only warning 31 is fatal).
- -warn-help
- Show the description of all available warning numbers.
- -where
- Print the location of the standard library, then exit.
- -file
- Process file as a file name, even if it starts with a dash (-)character.
- -help or —help
- Display a short usage summary and exit.
Contextual control of command-line options
The compiler command line can be modified “from the outside”with the following mechanisms. These are experimentaland subject to change. They should be used only for experimental anddevelopment work, not in released packages.
- OCAMLPARAM (environment variable)
- A set of arguments that will be inserted before or after the arguments fromthe command line. Arguments are specified in a comma-separated listof name=value pairs. A is used to specify the position ofthe command line arguments, i.e. a=x,,b=y means that a=x should beexecuted before parsing the arguments, and b=y after. Finally,an alternative separator can be specified as thefirst character of the string, within the set :|; ,.
- ocaml_compiler_internal_params (file in the stdlib directory)
- A mapping of file names to lists of arguments thatwill be added to the command line (and OCAMLPARAM) arguments.
- OCAML_FLEXLINK (environment variable)
- Alternative executable to use on nativeWindows for flexlink instead of theconfigured value. Primarily used for bootstrapping.
9.3 Modules and the file system
This short section is intended to clarify the relationship between thenames of the modules corresponding to compilation units and the namesof the files that contain their compiled interface and compiledimplementation.
The compiler always derives the module name by taking the capitalizedbase name of the source file (.ml or .mli file). That is, itstrips the leading directory name, if any, as well as the .ml or.mli suffix; then, it set the first letter to uppercase, in order tocomply with the requirement that module names must be capitalized.For instance, compiling the file mylib/misc.ml provides animplementation for the module named Misc. Other compilation unitsmay refer to components defined in mylib/misc.ml under the namesMisc.name; they can also do open Misc, then use unqualifiednames name.
The .cmi and .cmo files produced by the compiler have the samebase name as the source file. Hence, the compiled files always havetheir base name equal (modulo capitalization of the first letter) tothe name of the module they describe (for .cmi files) or implement(for .cmo files).
When the compiler encounters a reference to a free module identifierMod, it looks in the search path for a file named Mod.cmi or mod.cmiand loads the compiled interfacecontained in that file. As a consequence, renaming .cmi files is notadvised: the name of a .cmi file must always correspond to the nameof the compilation unit it implements. It is admissible to move themto another directory, if their base name is preserved, and the correct-I options are given to the compiler. The compiler will flag anerror if it loads a .cmi file that has been renamed.
Compiled bytecode files (.cmo files), on the other hand, can befreely renamed once created. That’s because the linker never attemptsto find by itself the .cmo file that implements a module with agiven name: it relies instead on the user providing the list of .cmofiles by hand.
9.4 Common errors
This section describes and explains the most frequently encounterederror messages.
- Cannot find file filename
- The named file could not be found in the current directory, nor in thedirectories of the search path. The filename is either acompiled interface file (.cmi file), or a compiled bytecode file(.cmo file). If filename has the format mod.cmi, thismeans you are trying to compile a file that references identifiersfrom module mod, but you have not yet compiled an interface formodule mod. Fix: compile mod.mli or mod.mlfirst, to create the compiled interface mod.cmi. If filename has the format mod.cmo, thismeans you are trying to link a bytecode object file that does notexist yet. Fix: compile mod.ml first.
If your program spans several directories, this error can also appearbecause you haven’t specified the directories to look into. Fix: addthe correct -I options to the command line.
- Corrupted compiled interface filename
- The compiler produces this error when it tries to read a compiledinterface file (.cmi file) that has the wrong structure. This meanssomething went wrong when this .cmi file was written: the disk wasfull, the compiler was interrupted in the middle of the file creation,and so on. This error can also appear if a .cmi file is modified afterits creation by the compiler. Fix: remove the corrupted .cmi file,and rebuild it.
- This expression has type t1, but is used with type t2
- This is by far the most common type error in programs. Type t1 isthe type inferred for the expression (the part of the program that isdisplayed in the error message), by looking at the expression itself.Type t2 is the type expected by the context of the expression; itis deduced by looking at how the value of this expression is used inthe rest of the program. If the two types t1 and t2 are notcompatible, then the error above is produced. In some cases, it is hard to understand why the two types t1 andt2 are incompatible. For instance, the compiler can report that“expression of type foo cannot be used with type foo”, and itreally seems that the two types foo are compatible. This is notalways true. Two type constructors can have the same name, butactually represent different types. This can happen if a typeconstructor is redefined. Example:
- type foo = A | B
- let f = function A -> 0 | B -> 1
- type foo = C | D
- f C
This result in the error message “expression C of type foo cannotbe used with type foo”.
- The type of this expression, t, contains type variablesthat cannot be generalized
Type variables ('a, 'b, …) in a type t can be in eitherof two states: generalized (which means that the type t is validfor all possible instantiations of the variables) and not generalized(which means that the type t is valid only for one instantiationof the variables). In a let binding let name = expr,the type-checker normally generalizes as many type variables aspossible in the type of expr. However, this leads to unsoundness(a well-typed program can crash) in conjunction with polymorphicmutable data structures. To avoid this, generalization is performed atlet bindings only if the bound expression expr belongs to theclass of “syntactic values”, which includes constants, identifiers,functions, tuples of syntactic values, etc. In all other cases (forinstance, expr is a function application), a polymorphic mutablecould have been created and generalization is therefore turned off forall variables occurring in contravariant or non-variant branches of thetype. For instance, if the type of a non-value is 'a list thevariable is generalizable (list is a covariant type constructor),but not in 'a list -> 'a list (the left branch of -> iscontravariant) or 'a ref (ref is non-variant). Non-generalized type variables in a type cause no difficulties insidea given structure or compilation unit (the contents of a .ml file,or an interactive session), but they cannot be allowed insidesignatures nor in compiled interfaces (.cmi file), because theycould be used inconsistently later. Therefore, the compilerflags an error when a structure or compilation unit defines a valuename whose type contains non-generalized type variables. Thereare two ways to fix this error:
- Add a type constraint or a .mli file to give a monomorphictype (without type variables) to name. For instance, instead ofwriting
- let sort_int_list = List.sort Stdlib.compare
- (* inferred type 'a list -> 'a list, with 'a not generalized *)
write
- let sort_int_list = (List.sort Stdlib.compare : int list -> int list);;
- If you really need name to have a polymorphic type, turnits defining expression into a function by adding an extra parameter.For instance, instead of writing
- let map_length = List.map Array.length
- (* inferred type 'a array list -> int list, with 'a not generalized *)
write
- let map_length lv = List.map Array.length lv
- Reference to undefined global mod
This error appears when trying to link an incomplete or incorrectlyordered set of files. Either you have forgotten to provide animplementation for the compilation unit named mod on the command line(typically, the file named mod.cmo, or a library containingthat file). Fix: add the missing .ml or .cmo file to the commandline. Or, you have provided an implementation for the module namedmod, but it comes too late on the command line: theimplementation of mod must come before all bytecode object filesthat reference mod. Fix: change the order of .ml and .cmofiles on the command line. Of course, you will always encounter this error if you have mutuallyrecursive functions across modules. That is, function Mod1.f callsfunction Mod2.g, and function Mod2.g calls function Mod1.f.In this case, no matter what permutations you perform on the commandline, the program will be rejected at link-time. Fixes:
- Put f and g in the same module.
- Parameterize one function by the other.That is, instead of having
- mod1.ml: let f x = ... Mod2.g ...
- mod2.ml: let g y = ... Mod1.f ...
define
- mod1.ml: let f g x = ... g ...
- mod2.ml: let rec g y = ... Mod1.f g ...
and link mod1.cmo before mod2.cmo.
- Use a reference to hold one of the two functions, as in :
- mod1.ml: let forward_g =
- ref((fun x -> failwith "forward_g") : <type>)
- let f x = ... !forward_g ...
- mod2.ml: let g y = ... Mod1.f ...
- let _ = Mod1.forward_g := g
- The external function f is not available
- This error appears when trying to link code that calls externalfunctions written in C. As explained inchapter 19, such code must be linked with C libraries thatimplement the required f C function. If the C libraries inquestion are not shared libraries (DLLs), the code must be linked in“custom runtime” mode. Fix: add the required C libraries to thecommand line, and possibly the -custom option.
9.5 Warning reference
This section describes and explains in detail some warnings:
9.5.1 Warning 9: missing fields in a record pattern
When pattern matching on records, it can be useful to match only fewfields of a record. Eliding fields can be done either implicitlyor explicitly by ending the record pattern with ; _.However, implicit field elision is at odd with pattern matchingexhaustiveness checks.Enabling warning 9 prioritizes exhaustiveness checks over theconvenience of implicit field elision and will warn on implicitfield elision in record patterns. In particular, this warning canhelp to spot exhaustive record pattern that may need to be updatedafter the addition of new fields to a record type.
- type 'a point = {x='a ;y='a}
- let dx { x } = x (* implicit field elision: trigger warning 9 *)
- let dy { y; _ } = y (* explicit field elision: do not trigger warning 9 *)
9.5.2 Warning 52: fragile constant pattern
Some constructors, such as the exception constructors Failure andInvalid_argument, take as parameter a string value holdinga text message intended for the user.
These text messages are usually not stable over time: call sitesbuilding these constructors may refine the message in a futureversion to make it more explicit, etc. Therefore, it is dangerous tomatch over the precise value of the message. For example, untilOCaml 4.02, Array.iter2 would raise the exception
- Invalid_argument "arrays must have the same length"
Since 4.03 it raises the more helpful message
- Invalid_argument "Array.iter2: arrays must have the same length"
but this means that any code of the form
- try ...
- with Invalid_argument "arrays must have the same length" -> ...
is now broken and may suffer from uncaught exceptions.
Warning 52 is there to prevent users from writing such fragile codein the first place. It does not occur on every matching on a literalstring, but only in the case in which library authors expressedtheir intent to possibly change the constructor parameter value inthe future, by using the attribute ocaml.warn_on_literal_pattern(see the manual section on builtin attributes in8.13.1):
- type t =
- | Foo of string [@ocaml.warn_on_literal_pattern]
- | Bar of string
- let no_warning = function
- | Bar "specific value" -> 0
- | _ -> 1
- let warning = function
- | Foo "specific value" -> 0
- | _ -> 1
- > | Foo "specific value" -> 0
- > ^^^^^^^^^^^^^^^^
- > Warning 52: Code should not depend on the actual values of
- > this constructor's arguments. They are only for information
- > and may change in future versions. (See manual section 8.5)
In particular, all built-in exceptions with a string argument havethis attribute set: Invalid_argument, Failure, Sys_error willall raise this warning if you match for a specific string argument.
Additionally, built-in exceptions with a structured argument thatincludes a string also have the attribute set: Assert_failure andMatch_failure will raise the warning for a pattern that uses aliteral string to match the first element of their tuple argument.
If your code raises this warning, you should not change theway you test for the specific string to avoid the warning (forexample using a string equality inside the right-hand-side insteadof a literal pattern), as your code would remain fragile. You shouldinstead enlarge the scope of the pattern by matching on all possiblevalues.
- let warning = function
- | Foo _ -> 0
- | _ -> 1
This may require some care: if the scrutinee may return severaldifferent cases of the same pattern, or raise distinct instances ofthe same exception, you may need to modify your code to separatethose several cases.
For example,
- try (int_of_string count_str, bool_of_string choice_str) with
- | Failure "int_of_string" -> (0, true)
- | Failure "bool_of_string" -> (-1, false)
should be rewritten into more atomic tests. For example,using the exception patterns documented in Section 7.6,one can write:
- match int_of_string count_str with
- | exception (Failure _) -> (0, true)
- | count ->
- begin match bool_of_string choice_str with
- | exception (Failure _) -> (-1, false)
- | choice -> (count, choice)
- end
The only case where that transformation is not possible is if a givenfunction call may raise distinct exceptions with the same constructorbut different string values. In this case, you will have to check forspecific string values. This is dangerous API design and it should bediscouraged: it’s better to define more precise exception constructorsthan store useful information in strings.
9.5.3 Warning 57: Ambiguous or-pattern variables under guard
The semantics of or-patterns in OCaml is specified witha left-to-right bias: a value v matches the pattern p|qif it matches p or q, but if it matches both,the environment captured by the match is the environment captured byp, never the one captured by q.
While this property is generally intuitive, there is at least one specificcase where a different semantics might be expected.Consider a pattern followed by a when-guard:| p when g -> e, for example:
- | ((Const x, _) | (_, Const x)) when is_neutral x -> branch
The semantics is clear:match the scrutinee against the pattern, if it matches, test the guard,and if the guard passes, take the branch.In particular, consider the input (Const a, Const b), wherea fails the test isneutral a, while b passes the testis_neutral b. With the left-to-right semantics, the clause above is_not taken by its input: matching (Const a, Const b)against the or-pattern succeeds in the left branch, it returns theenvironment x -> a, and then the guardis_neutral a is tested and fails, the branch is not taken.
However, another semantics may be considered more natural here:any pair that has one side passing the test will take the branch. With thissemantics the previous code fragment would be equivalent to
- | (Const x, _) when is_neutral x -> branch
- | (_, Const x) when is_neutral x -> branch
This is not the semantics adopted by OCaml.
Warning 57 is dedicated to these confusing cases where thespecified left-to-right semantics is not equivalent to a non-deterministicsemantics (any branch can be taken) relatively to a specific guard.More precisely, it warns when guard uses “ambiguous” variables, that are boundto different parts of the scrutinees by different sides of a or-pattern.