Previous: Introduction to mmake, Up: Compiling multi-module programs [Contents][Index]
The second Mercury build tool is mmc --make
,
which, as the name says,
integrates the functionality of a make-like build tool
into the Mercury compiler.
Like mmake
,
mmc --make
needs access
to the module-name-to-file-name map in Mercury.modules
if some module in the program is stored in a file
whose name does not match the module name.
This means that the first step in building an executable
is still usually mmc -f *.m
.
Unlike mmake
,
when mmc --make
is asked to build an executable for a program
given the name of its main module,
it can itself find out the dependencies (importer-imported relationships)
between the modules of the program;
it does not need previously-built files
containing makefile fragments to give it this information.
It therefore has no need for any equivalent of the
mmake main_module.depend
command.
This allows an executable to be built with just these two commands:
mmc -f *.m mmc --make main_module
In this case, the main_module part of the second command is a file name:
specifically, the name of the executable to be built.
However, this non-option argument to mmc --make
is not the name of a file to be compiled;
it is the name of a file to be built.
In general, non-option arguments to mmc --make
should be the names of targets,
in the same sense of make
targets.
Most targets are files to be built, but some are not,
the same way as PHONY
targets in make
do not represent files.
For example, mmc --make main_module.realclean
asks the compiler to delete all the automatically-regenerable files
that are part of the main_module program.
Note that mmc --make
has a subtle advantage over mmake
.
While mmake
uses (because it has to)
module-to-module dependency information that was current
when the relevant modules’ were last (re)compiled
(because that is when their .d files were last updated),
mmc --make
always uses current dependency information,
because it gets that information
from the current versions of the modules’ source files.
Most of the time, the difference does not matter, for one of several reasons:
:- import_module
and :- use_module
declarations;
:- import_module
or :- use_module
declaration cannot lead to obsolete versions of interface files being read
(since they lead to fewer interface files being read);
:- import_module
and :- use_module
declaration is added,
which can lead to obsolete versions of the interface files
of the newly-imported modules being read,
those interface files have a reasonably probability
of being brought up to date
before being needed by the module that added the new import,
due to some other module already depending on them; and
Most of the time, one or more of these mitigating circumstances will apply.
However, sometimes none of them do.
In such cases, using mmake
to build the selected target will fail,
with the failure being caused by mmake
’s reliance
on out-of-date dependency information.
(This could mean e.g. mmake
not knowing that
it must update the .int file of a newly-imported module
before generating target language code for the importing module.)
In pretty much all of the usual scenarios, the attempt to build the target
will cause the out-of-date dependency information to be updated,
so the next attempt to build that same target will succeed.
Nevertheless, the failure of the first attempt is annoying.
Such transient failures won’t happen with mmc --make
,
because it always works with up-to-date dependency information.
For more information on mmc --make
,
please see ZZZ
Previous: Introduction to mmake, Up: Compiling multi-module programs [Contents][Index]