Next: , Previous: Filenames, Up: Top   [Contents][Index]


3 Using the Mercury compiler

The Mercury compiler is called ‘mmc’ (for “Melbourne Mercury Compiler”). Some of its options (e.g. ‘-c’, ‘-o’, and ‘-I’) have a similar meaning to that in other compilers.

(Note that on Microsoft Windows systems, the name ‘mmc’ is also used by the executable for the Microsoft Management Console. To avoid the name clash on these systems, you can either invoke the Mercury compiler by the alternative name ‘mercury’, or adjust your PATH to ensure that the bin directory precedes the Windows system directory.)

Arguments to ‘mmc’ may be either file names (ending in ‘.m’), or module names, with ‘.’ (rather than ‘__’) as the module qualifier. For a module name such as ‘foo.bar.baz’, the compiler will look for the source in the file named foo.bar.baz.m. To make the compiler look for a module in another file, use ‘mmc -f sources-files’ to generate a mapping from module name to file name, where sources-files is the list of source files in the directory (see Output options).

Arguments to ‘mmc’ may also be in ‘@file’. The ‘@file’ argument is replaced with arguments representing the contents of the file. This argument processing is done recursively. The contents of the ‘@file’ is split into arguments one per line in the file.

There are two ways to compile a program that consists of a single source file. The first way, which works only when targeting C, is to issue the command

mmc filename.m

The second way, which works regardless of target language, is to issue the command

mmc --make filename

There are also two ways to build programs that consist of more than one source file: using Mmake (see Using Mmake), which only works when targeting C, or using ‘mmc --make’.

We strongly recommend that programmers use ‘mmc --make’ rather than invoking ‘mmc’ directly, because ‘mmc --make’ is generally easier to use and avoids unnecessary recompilation.

When targeting C on systems that do not require an executable file extension, ‘mmc’ will put the executable into a file called filename; on systems (such as Windows) that use .exe as the file extension for executables, ‘mmc’ will put the executable into a file called filename.exe.

When targeting C#, ‘mmc’ will generate a process assembly called filename.exe. On Windows, this process assembly can be run directly. On non-Windows systems, ‘mmc’ will also generate a shell script called filename that invokes the CLI execution environment on the process assembly. (See the file README.CSharp included in the Mercury distribution for further details.)

When targeting Java, ‘mmc’ will package up all of the class files for the executable into a Java archive (JAR) named filename.jar. It will also generate a launcher that invokes the program using the Java interpreter. If you are using the Windows command line interpreter ‘cmd.exe’, this launcher will be a batch file called filename.bat. Otherwise, the launcher will be a shell script called filename. Java runtime flags can be set using ‘mmc’’s ‘--java-runtime-flags’ or ‘--java-runtime-flag’ options. Such Java runtime flags will be included in the generated launcher shell script or batch file. You may override any runtime flags set at (Mercury) compile time by setting the variable MERCURY_JAVA_OPTIONS in the environment. Classpath settings made using ‘mmc’’s ‘--java-classpath’ option will also be included in the generated launcher shell script or batch file.

If you use Mmake or ‘mmc --make’, then you do not need to understand the details of how the Mercury implementation goes about building programs. Thus you may wish to skip the rest of this chapter.

To compile a source file to object code via C without creating an executable, use the command

mmc -c filename.m

Since targeting C is the default, this tells ‘mmc’ to generate C code, and then invoke the configured C compiler to translate that to object code. ‘mmc’ puts the generated C code into a file called module.c and the generated object code into a file called module.o, where module is the name of the Mercury module defined in filename.m. If the source file contains nested modules, then each submodule will get compiled to separate C and object files.

Before you can compile a module, you must make the interface files for the modules that it imports (directly or indirectly). You can create the interface files for one or more source files using the following commands:

mmc --make-short-int filename1.m filename2.m …
mmc --make-priv-int filename1.m filename2.m …
mmc --make-int filename1.m filename2.m …

The first command builds (or rebuilds) the ‘.int3’ file of each module contained in the named source files. The second command builds (or rebuilds) the ‘.int0’ file of each module contained in the named source files. (Note that only modules that have submodules need ‘.int0’ files.) The third command builds (or rebuilds) both the ‘.int’ and ‘.int2’ file of each module contained in the named source files.

If you are going to compile with ‘--intermodule-optimization’ enabled, then you also need to create the optimization interface files.

mmc --make-opt-int filename1.m filename2.m …

If you are going to compile with ‘--transitive-intermodule-optimization’ enabled, then you also need to create the transitive optimization files.

mmc --make-trans-opt filename1.m filename2.m …

After you have made all the interface files, one way to create an executable for a multi-module program is to compile all the modules at the same time using the command

mmc filename1.m filename2.m …

This will by default put the resulting executable in filename1, though you can use the ‘-o filename’ option to specify a different name for the output file, if you so desire.

The other way to create an executable for a multi-module program is to compile each module separately using ‘mmc -c’, and then link the resulting object files together. The linking is a two stage process.

First, you must create and compile an initialization file, which is a C source file containing calls to automatically generated initialization functions contained in the C code of the modules of the program:

c2init module1.c module2.c … > main-module_init.c,
mgnuc -c main-module_init.c

The ‘c2init’ command line must contain the name of the C file of every module in the program. The order of the arguments is not important. The ‘mgnuc’ command is the Mercury GNU C compiler; it is a shell script that invokes the configured C compiler with the options appropriate for compiling the C programs generated by Mercury. (In the early days of the Mercury project, the configured C compiler was almost always GCC, which is why the name of the script is what it is, but the script itself will work with clang or MSVC as well.)

You then link the object code of each module with the object code of the initialization file to yield the executable:

ml -o main-module module1.o module2.o … main_module_init.o

ml’, the Mercury linker, is another shell script that invokes a C compiler with options appropriate for Mercury, this time for linking. ‘ml’ also pipes any error messages from the linker through ‘mdemangle’, the Mercury symbol demangler, so that any error messages refer to predicate and function names from the Mercury source code rather than to the names used in the intermediate C code.

The above command puts the executable in the file main-module. The same command line without the ‘-o’ option would put the executable into the file a.out.

mmc’ and ‘ml’ both accept a ‘-v’ (verbose) option. You can use that option to see what is actually going on. For the full set of options of ‘mmc’, see Invocation.


Next: , Previous: Filenames, Up: Top   [Contents][Index]