mlton(1)
π mlton β like, the whole-program compiler for Standard ML, bestie
Okay so this is from the General Commands Manual, and it's about mlton, which is the whole-program compiler for the Standard ML (SML) programming language. Buckle up, she's thorough π
β¨ NAME β¨
mlton β whole-program compiler for the Standard ML (SML) programming language. That's it, that's the girl π
π¦ SYNOPSIS π¦
mlton [option ...] file.{c|mlb|o|sml} [file.{c|o|s|S} ...]
πΈ DESCRIPTION πΈ
So here's the vibe: you run MLton from the command line with a whole lil collection of options, and then you follow that up with a file name plus a list of files that you want to compile, assemble, and link with. Yeah, it's a whole ensemble cast π«Ά
The absolute simplest case? You just run mlton foo.sml, where foo.sml contains a valid SML program, and boom β MLton compiles that program and produces an executable named foo. Iconic, no notes β¨
Lowkey important though: MLton does not support separate compilation, so that program has to be the entire program you wish to compile. Like, the whole thing. No splitting her up π
That said β and this is the slay part β the program totally may refer to signatures and structures defined in the Basis Library. So you're not starting from nothing, bestie π
π§ Bigger programs, bigger energy
Larger programs that span, like, so many files can be compiled with the ML Basis system. In that case, mlton foo.mlb will compile the complete SML program described by the basis foo.mlb, which may specify both SML files and additional bases. See the MLton Guide for the details β she's got lore π
β What the compile-time options actually do
MLton's compile-time options are the main characters here, and they control:
- the name of the output file π
- the verbosity of compile-time messages π£οΈ
- whether or not certain optimizations are performed π
They can also specify which intermediate files are saved, and they can stop the compilation process early at some intermediate pass β in which case, plot twist, compilation can be resumed by passing the generated files to MLton π₯
π File suffixes, iykyk
MLton uses the input file suffix to determine the type of input program. The possibilities are:
.c.mlb.o.s.sml
π Little quality-of-life notes
With no arguments at all, MLton just prints the version number and exits. Short and sweet, love that for her π
Want a usage message? Run MLton with an invalid switch, e.g. mlton -z. Yes, breaking it on purpose is the move π
Noted for the explanation below and also in the usage message: for flags that take a number of choices (e.g. {true|false}), the first value listed is the default. Memorize that, it comes up a lot π
...and that's where part 1 wraps, but don't go anywhere β more mlton coming right up π¦
π οΈ Compile-time options π οΈ
Okay bestie, this is the big one β all the knobs you can turn while compiling. Buckle up π
-align nβ Lines up objects in memory on the alignment you pick (n is4or8). The default? Honestly it depends on the architecture, no cap. π¦-as-opt optionβ Sneaks option through togccwhen it's compiling assembler code. Heads up though: if you actually want the option to reach the assembler, you gotta use gcc's-Wa,syntax. That's just how it is π-cc ccβ Tells MLton which executable to use as the C compiler. And like, it does triple duty β the C compiler also gets called to compile assembly (.sfiles) down to object code (.ofiles), and to link object code into your final executable. Main character energy tbh π-cc-opt optionβ Passes option togccwhen compiling C code. Slay.-codegen {native|x86|amd64|c|llvm}β Picks how you want native object code generated: via amd64 assembly, C code, LLVM code, or x86 assembly. With-codegen native(which is-codegen amd64or-codegen x86), MLton usually compiles faster and generates better code. Bestie, that's the good stuff β¨-const 'name value'β Sets the value of a compile-time constant. Here's the whole list of what you can set, what it defaults to, and what it actually controls:Exn.keepHistory {false|true}β Turns onMLton.Exn.history. Fair warning: setting this totruehas a performance cost β both in the memory that exceptions eat up and in run time β because extra work has to happen at every exception construction, raise, and handle. So like, know what you're signing up for π
-default-ann annβ Sets default ML Basis annotations. Like,-default-ann 'warnUnused true'makes unused variable warnings on by default. Any annotation in an ML Basis file can override these defaults though β defaults aren't the final word π«Ά-default-type typeβ Picks the default binding for a primitive type. For example,-default-type word64makes the top-level typewordand the top-level structureWordin the Basis Library equal toWord64.wordandWord64:WORD, respectively. Same vibe with-default-type intinfβ that makes the top-level typeintand the top-level structureIntequal toIntInf.intandIntInf:INTEGER. Icons only π-disable-ann annβ Ignores the annotation you name in every single ML Basis File. So say you want to see absolutely all the match and unused warnings β you'd compile with-default-ann 'warnUnused true',-disable-ann forceUsed,-disable-ann nonexhaustiveMatch,-disable-ann redundantMatch, and-disable-ann warnUnused. That's the whole combo meal π-export-header fileβ Writes C prototypes out to file for every function in your program that's exported from SML to C. Very demure, very mindful.-ieee-fp {false|true}β Makes the x86 native code generator be all pedantic about following the IEEE floating point standard. By default it is not pedantic, purely because it costs performance. And btw this only does anything with-codegen x86β otherwise it's just sitting there π-inline nβ Sets the inlining threshold the optimizer uses. The threshold is like an approximate measure of how big a procedure's code is. Default is320. Don't ask me to justify it, that's just the number π₯-keep {g|o}β Saves the intermediate files. If you give no-keepargument at all, only the output file survives.gβ keeps the generated.cand.sfiles that get passed to gcc, plus the generated.llfiles passed to llvm-asoβ keeps the object (.o) files
-link-opt optionβ Passes option togccwhen linking. This is your moment to specify library search paths, like-link-opt -Lpath, and libraries to link against, like-link-opt -lfooβ or honestly both at once, like-link-opt '-Lpath -lfoo'. If you want the option to reach the linker itself, you gotta go through gcc's-Wl,syntax, e.g.-link-opt '-Wl,--export-dynamic'. iykyk π§-llvm-asllvm-as β Sets the executable for the LLVM.llto.bcassembler. You can use this to pick a specific version of the tool (e.g.,-llvm-as llvm-as-14). Obsessed with tool versioning fr fr π-llvm-as-opt optionβ Passes option to llvm-as when it's assembling (.llto.bc) LLVM code.-llvm-llcllc β Sets the executable for the LLVM.bcto.osystem compiler. Again, pick your specific tool version if you want (e.g.,-llvm-llc llc-14). π-llvm-llc-opt optionβ Passes option to llc when it's compiling (.bcto.o) LLVM code.-llvm-optopt β Sets the executable for the LLVM.bcto.bcoptimizer. Same deal β specific version if you need it (e.g.,-llvm-opt opt-14). β-llvm-opt-opt optionβ Passes option to opt when it's optimizing (.bcto.bc) LLVM code.-mlb-path-map fileβ Uses file as an ML Basis path map so you can define extra MLB path variables. And here's the cute part: you can use-mlb-path-mapand-mlb-path-varas many times as you want, and variable definitions in later path maps take precedence over earlier ones. Last one wins, periodt π-mlb-path-var 'name value'β Defines one more MLB path variable. Same rules as above: multiple uses of-mlb-path-mapand-mlb-path-varare allowed, and later definitions beat out earlier ones. π-output fileβ Names your final output file. The default name is the input file name with its suffix chopped off and an appropriate, possibly empty, suffix added on. So like, it just does its thing β¨-profile {no|alloc|count|time}β Builds an executable that gathers profiling data. When you run that executable, it spits out anmlmon.outfile. The man page onmlprofexplains how to get the actual info out of that file β go read it, bestie π¦-profile-branch {false|true}β Iftrue, the profiler separately gathers profiling data for each branch of a function definition, case expression, and if expression. Every branch gets its own little spotlight πΈ-profile-stack {false|true}β Iftrue, the profiler gathers profiling data for all functions on the stack, not just the one currently executing. The whole squad, not just the main character π-profile-val {false|true}β Iftrue, the profiler separately gathers profiling data for each (expansive) val declaration. π-runtime argβ Passes arg to the runtime system via@MLton. The argument gets processed before the other@MLtoncommand line switches. You can use-runtimemultiple times and all the arguments get passed in order. If the same runtime switch shows up more than once, the last setting is the one that takes effect. Oh and β you don't need to write the leading@MLtonor the trailing--yourself, those get supplied automatically π«Ά
An argument to -runtime can totally contain spaces, and that makes the runtime treat it as a whole sequence of words. Like, this command line:
mlton -runtime 'ram-slop 0.4' foo.sml
will make foo run as if it had been called like:
foo @MLton ram-slop 0.4 --
Also! An executable created with -runtime stop doesn't process any @MLton arguments at all. Super useful when you're making an executable, e.g. echo, that has to treat @MLton like literally any other command-line argument:
% mlton -runtime stop echo.sml
% echo @MLton --
@MLton --
See? It just hands it right back. Iconic behavior π
-show-basis fileβ Pretty prints to file the basis that your input program defines. So you can actually see it π-show-def-use fileβ Writes def-use info out to file. Every identifier that's defined shows up on a line, and then subsequent lines give you the position of each place it's used. It's giving detective work π-stop {f|g|o|tc}β Tells MLton exactly when to stop doing things.fβ list of files on stdout (only makes sense when the input isfoo.mlb)gβ the generated.cand.sfilesoβ the object (.o) filestcβ stop after type checking
And here's the good part: if you compile with -stop g or -stop o, you can pick compilation right back up by running MLton on the generated .c and .s files or the .o files. Resume-able, we love to see it π
-target {self|...}β Generates an executable that runs on the platform you name. The default isself, which means "compile for the exact machine MLton is running on." If you wanna use any other target, you gotta install a cross compiler first β check the MLton Guide for the details, bestie π-target-as-opt target optionβ Just like-as-opt, it passes option togccwhen assembling β except it only passes it when the target architecture or operating system is target. Conditional vibes β¨-target-cc-opt target optionβ Just like-cc-opt, it passes option togccwhen compiling C code β except it only passes it when the target architecture or operating system is target. π¦-target-link-opt target optionβ Just like-link-opt, it passes option togccwhen linking β except it only passes it when the target architecture or operating system is target. π-verbose {0|1|2|3}β Controls how chatty MLton is about which passes are running. Default is0.0β silent π€«1β calls to compiler, assembler, and linker2β everything in1, plus intermediate compiler passes3β everything in2, plus some data structure sizes π₯
π οΈ Runtime system options π οΈ
Okay bestie, plot twist: executables produced by MLton also take command line arguments that control the runtime system. These arguments are optional, and they occur before the executable's usual arguments. To use these options, the first argument to the executable must literally be @MLton. The optional arguments then follow, must be terminated by --, and are followed by any arguments to the program. The optional arguments are not made available to the SML program via CommandLine.arguments. For example, a valid call to hello-world is:
hello-world @MLton gc-summary fixed-heap 10k -- a b c
In the above example, CommandLine.arguments () = ["a", "b", "c"]. π«Ά
It is allowed to have a sequence of @MLton arguments, as in:
hello-world @MLton gc-summary -- @MLton fixed-heap 10k -- a b c
Run-time options can also control MLton, as in:
mlton @MLton fixed-heap 0.5g -- foo.sml
fixed-heap x{k|K|m|M|g|G}β Use a fixed size heap of size x, where x is a real number and the trailing letter indicates its units:korKβ1024morMβ1,048,576gorGβ1,073,741,824
A value of 0 means to use almost all the RAM present on the machine. The heap size used by fixed-heap includes all memory allocated by SML code, including memory for the stack (or stacks, if there are multiple threads). It does not, however, include any memory used for code itself or memory used by C globals, the C stack, or malloc. π
gc-messagesβ Print a message at the start and end of every garbage collection. ποΈβ¨gc-summaryβ Print a summary of garbage collection statistics upon program termination. πgc-summary-file fileβ Print a summary of garbage collection statistics upon program termination to the file specified by file. πload-world worldβ Restart the computation with the file specified by world, which must have been created by a call toMLton.World.saveby the same executable. See the MLton Guide for details. πmax-heap x{k|K|m|M|g|G}β Run the computation with an automatically resized heap that is never larger than x, where x is a real number and the trailing letter indicates the units as withfixed-heap. The heap size formax-heapis accounted for as withfixed-heap. πmay-page-heap {false|true}β Enable paging the heap to disk when unable to grow the heap to a desired size. πΎno-load-worldβ Disableload-world. This can be used as an argument to the compiler via-runtime no-load-worldto create executables that will not load a world. This may be useful to ensure that set-uid executables do not load some strange world. π«πram-slop xβ Multiply x by the amount of RAM on the machine to obtain what the runtime views as the amount of RAM it can use. Typically x is less than1, and is used to account for space used by other programs running on the same machine. π§stopβ Causes the runtime to stop processing@MLtonarguments once the next--is reached. This can be used as an argument to the compiler via-runtime stopto create executables that don't process any@MLtonarguments. π
π©Ί DIAGNOSTICS π©Ί
MLton's type error messages are not in a form suitable for processing by Emacs. For details on how to fix this, see http://mlton.org/Emacs. π
π SEE ALSO π
mlprof(1) and the MLton Guide. π«Ά
This page is serving mlton(1) manual-page energy, dated December 30, 2024. Periodt. π
π¦ where this page comes from
- arch rolling: mlton 20241230-1 Β· HPND AND MIT
- nixos 26.05: isabelle 2025-2
- nixos 26.05: mlton 20241230
- nixos 26.05: mlton-HEAD
- nixpkgs unstable: isabelle 2025-2
- nixpkgs unstable: mlton 20241230
- nixpkgs unstable: mlton-HEAD
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms