2. Additional Utilities

2.1 The GenMake Utility

The "GenMake" tool analyses the a module system's interdependencies (in a similar way to the global cross-referencer "M2Cross") and then generates dependency rules for the command line tool "make".
Starting with version 9.1, "GenMake" is able to produce the make file for a fat binary in one run of "GenMake". Command line options specify features equal for all given architecture whereas the default file may be used to specify dertails for each architecture independently.

GenMake can be used like every other tool and is activated with the following syntax:

GenMake [options] module [(> | >>) makefile]

moduleis the name of the main module (without ".MOD" extension!). Note that the capitalization of this parameter must match that of the module name exactly.
makefileGenMake's output goes by default to "standard output", but it can be redirected to a new file using ">" or appended to an existing one using ">>".

options = option [options]
option = (-optionText | -d compileTimeVariable=value)

The "GenMake" tool makes use of the same procedure for analyzing the command line as the compiler itself. All compiler options are interpreted. Compile time variables are treated in the same manner as the compiler does. This ensures that all predefined pragma variables are preset with the same value as during compilation. Therefore, conditions in "IMPORT" statements are evaluated correctly.

For "optionText" any one of the following is also possible:

KEEPASSEMBLER The compiler output (an assembler source or intermediate C file) is stored in a file named .MOD.s (.MOD.c) and then processed by the assembler or C compiler. Otherwise (default) the compiler output is passed via a pipe to the assembler.
ARCH architecture Specifies the code architecture of the target. At the moment "arm64" (default), and "x86_64" are recognized. With no architecture specified in the default file, a thin binary for exactly this architecture is produced. Otherwise the architectures(s) given in the default file are produced.
TOOL With no link script specified, GenMake adds the appropriate Modula2 library for tools (e. g. "libm2lib.a") to the linker command. If this option is not present (default), the according Carbon version of the Modula2 library (e. g. "libm2libcarbon.a") and the carbon framework are linked into the application.
DEBUG With no link script specified, GenMake uses the debug versions of the Modula-2 libraries instead of the normal ones.
SYSLIBROOT path When given, adds option "-syslibroot path" to the linker command. This allows to specify the exact system version you want to link against. This may be necessary for cross development. For details please refer to "man ld".
LINKSCRIPT linkerName Causes the "linkerName" to be used for the name of the linker tool. If this option is omitted GenMake generates, depending on the options "TOOL" and "DEBUGGER" link commands for including the necessary libraries but with no further options.
DEFSCRIPT name Causes the script "name" to be used for the compilation o definition modules. If this option is omitted, the name "Modula2" (by default the compiler) is used.
MODSCRIPT name Causes the script "name" to be used for the compilation o implementation modules. If this option is omitted, the name "Modula2" (by default the compiler) is used.
DEFAULT file Specifies a file in which the names of paths are listed which should be looked through for files of various kinds. This file may also contain information about the code architecture(s) the program should be built for. If "file" ends in ".DAT" this can be omitted when specifying it in this context. If the "DEFAULT" option is not given, the file "GenMake.DAT" in the current folder will be used if present. If it is not, only the current folder is searched. The current folder is searched in any case.

Each line of this file starts with an identifying letter which indicates what kind of file should be looked for in the path specified:
Dfor definition files (.DEF)
Sfor symbol files (.MSYM)
Mfor implementation and program files (.MOD)
Gfor generic definition or implementation files (.GDE .GMO)
Ofor object files (.MOD.o)
Efor linked programs (only once for each architecture)
Afor storing assembler / C files (only once for each architecture)
Cfor storing C files (only once for each architecture); also specifies that C back and is to be used
Bfor system programs like as or gcc; useful for accessing older versions
Rfor "-isysroot" when linking via gcc to specify older SDKs
Tto specify paths for specific architectures. T is followed by one of the following three letters:
A Option is used for Arm 64-bit code
X Option is used for Intel 64-bit code
The architecture specifier is followed by one of the above path specifications.
This option only describes which path(s) are to be used iff the given architecture is to be produced. It does not force this architecture to be produced (see U option below).
Uthe generated make file describes a Universal binary. The given architectures are generated independently and then combined by a "lipo" command. The following characters may follow to U:
A Arm 64-bit code is generated
X Intel 64-bit code is generated
C C back end is used for code generation
Though A and X may occur more than once on one line, only the last architecture specification is used. To specify more then one architecture, U must be used on a separate line for every architecture.
If U is specified only once in the default file, the target is generated with an architecture specific suffix and a "lipo" command with double colon rule is generated in addition to the link command.

With exception to 'U' and 'T' a path name must immediately follow this letter (without intervening space or other separator), and this path specification must end with "/". GenMake searches through the paths exactly in the order they are listed. The current folder is always searched last, unless it is explicitly included in the path file.

A path name may also include shell variables. GenMake transfers path names containing shell variables to the makefile unchanged, i.e. without making any substitutions.

Path names may be followed by an optional name extension, e.g. ".MSYM". Only files with this name extension are looked for by "GenMake" in the given path. If the extension is omitted, the extension normally used for the given kind of file is assumed.

Additionally, the file may contain specifications for compiler options:
A line starting with "-" is directly included in each compilation command. If it is to be used only for a specific architecture it has to be preceded by 'T' and the letter for the architecture.

PROGRESS Outputs a list of modules which could not be opened, along with the names of the modules which referred to them. GenMake writes this output to "standard error output" just before it ends. If this option is not specified, only the names of the modules which were looked at are listed (see below).
If a referenced module is not found it is not taken into consideration in the make rules. This is generally the case for library modules. This means that no warning is issued even if one of the paths to be searched is accidentally omitted from the path file. However GenMake always writes the names of all the modules processed to "standard error output". It is therefore to be recommended always to use the "-PROGRESS" option and then to check whether all the modules desired have been taken into account.

GenMake not only investigates the module sources' interdependencies but also searches the specified folders for symbol and object files which may have resulted from earlier manual compilations. GenMake then generates rules for "make" which cause object and symbol files to be placed automatically in the same folders that existing versions of them were found in. If a symbol or object file does not yet exist for a module, a make rule is generated to place the result of the compilation in the same folder as its respective source.

The result of GenMake's analysis is written to "standard output" in the form of dependency rules for the make tool and a link command containing a list of all the necessary object files.

The "-LINKSCRIPT" Option:
The link command has the following form:
linkerName programName objectFiles

By using the "-LINKSCRIPT" option the name of a script (containing the command actually to execute the linker) can be substituted for "linkerName". This makes it possible using special scripts to append optional libraries to the parameter list generated by GenMake and to adapt it, to the special requirements of the linker in use.

The use of command line options together with a detailed default file is shown in the following example. It generates the make file for the compiler as a universal binary for three architectures.

The default file (Genmake.DAT):
TA-ref Compiler/REFs/a64/
TX-ref Compiler/REFs/x86/
Paths for definition and implementation modules
These paths are equal for all architectures

Paths for object, symbol, assembler, and reference files for arm 64-bit code

Paths for object, symbol, assembler, and reference files for intel 64-bit code

Options for all architectures

The architectures to be used

This file is used in the following command which is executed from the directory just above "Compiler":
genmake -default Genmake.DAT -tool Modula2 >makefile

The option "-default Genmake.DAT" could be omitted, as it is the default; it is given to make the access to the default file visible.

2.2 The M2SymfileDump Utility

M2SymfileDump reads the contents of a symbol file created by the compiler and outputs its internal structure in readable form to "standard output". Its command line has the following syntax:
	M2SymfileDump msymfile
The parameter "msymfile" is the name of a symbol file (the extension ".MSYM" may be omitted).

Most programmers will only be interested in a small part of M2SymfileDump's output: the internal procedure numbering and the various module keys—both that of the symbol file itself and those of the modules it imports.

A procedure's internal number can be found after the text "ExtProcNum:". This number might be of interest when for example a run-time error occurs.

The module keys are always listed at the beginning of M2SymfileDump's output. They are 8-digit hexadecimal numbers enclosed in backslashes ("\"), making them easy to recognize. They might in particular be worth investigating if problems arise when linking a program. As a rule such difficulties are caused by inconsistent module versions, which can easily be rectified by recompiling the relevant modules.

M2SymfileDump can also interpret reference files. In such a case the extension ".MREF" must be included in the file name when specifying it as parameter. At the end of a reference file there is a table associating relative instruction address within a procedure (as displayed for example in the run-time error dialog) and source-code line number. This can be used to find the corresponding line of source code when an error occurs even if the Modula-2 debugger was not installed.

By keeping the assembler files (cf. description of GenMake) the contents of object files can be displayed in readable format. Module keys and procedure numbers (evident as entry points having names beginning with "P_" and "<module name>_" respectively) can be determined from this kind of file as well.

2.3 The Global Cross-Referencer

The program "M2Cross" generates a global cross-reference list, in contrast to the compiler option "-CROSSREFERENCE". A global cross-reference list gives an overview of the specified module's imported identifiers and of all the exported identifiers of the modules it refers to as well, instead of documenting the use of all the identifiers in the specified module only. It is an easy way to get an overall view of the interdependencies of several modules.

So that the list does not become too extensive, only the names of the modules which import each particular identifier are included, and not line numbers indicating where each identifier occurs. If an identifier is exported from a module but not imported by any module at all, this is also noted in the cross-reference list.

The program's command line has the form:

M2Cross [-default path file] firstModule [(> | >>) listingfile]
"firstModule" must be the name of a module (without a ".DEF" or ".MOD" extension). This module and all modules referenced by it (both ".DEF" and ".MOD" files") are then examined. (Of course this presupposes that the names of the files correspond to names of the modules apart from the respective extension ".DEF" or ".MOD".) Normally therefore the name of a program module is given for "firstModule".

As optional parameter a so-called path file can be specified. In such a file the names of the folders are listed which should be looked through for referenced modules. If this path file's name ends with ".DAT", this can be omitted when specifying it as parameter. Omitting this parameter altogether means that only the current folder will be searched for modules.

In the path file each folder to be searched is listed on a line to itself. As well as that, each folder name must be written without quotation marks of any sort, even if the name contains special characters which would make quoting necessary within a shell. Every folder name in the path file must also end in a slash. A path may be absolute (starting with a slash) or relative (starting with a folder or file name). The order in which the folder names are listed is the reverse of that in which the folders will be searched. The current folder need not be listed in the path file; it is always searched first automatically.

While M2Cross is running, as each module is being examined its name is written to standard output. If a module is not found in any of the specified folders, an appropriate warning appears and only the identifiers imported from the module are included in the list. The identifiers this module for its part refers to by and those it exports but which are not used can of course not be determined. This will happen in particular with library modules like TextIO, IOChan etc.—the names of the folders containing them are unlikely to be included in the path file, indeed one will scarcely be interested to know which identifiers these modules import or which of the ones they export are not used.

The cross-reference list is output to standard out, which may be redirected to any file.

A cross-reference list for the program "MAIN" is to be created and saved in the current folder as "MAIN.CROSS". The "MAIN" module used modules from the folders "M2/Folder 1", "M2/MODs" and "M2/DEFs" (where M2 resides in the same directory as MAIN) as well as various library modules in other folders—how these are interrelated is of no particular interest.

First of all a file called "Paths.DAT" is created with the following contents:

	M2/Folder 1/
After changing the current directory to the folder that contains MAIN and launching the program with
M2Cross -default Paths MAIN >cross.txt
messages appear indicating the modules which are being examined; warnings are issued about the library modules because they cannot be found in any of the specified folders.

If a cross-reference list is to be created for only some of the modules of a large program, it is often handy to create a dummy module which imports all the desired modules.

The interdependencies of the three modules A, B and C are to be determined. The following module is created for this purpose and given as the "firstModule" parameter:

	MODULE dummy;
	END dummy.
A cross-reference list for this dummy module documents all the identifiers exported by these three modules as well as all the modules directly or indirectly imported by them.

2.4 Useful Scripts

Besides the tools described above the folder "Modula2/bin/" contains some scripts which perform several often needed tasks.

m2 mymodulecompiles one module. "mymodule.MOD" is expected as input file.
m2link mytoollinks a command line tool from one module. "mytool.o" is expected as input file.
m2linkd mytoollike the above except that the p1 Modula-2 debugger is linked into the tool.
m2build mytoolcompiles and links a command line tool from one module. "mytool.mod" is expected as input file.
m2buildd mytoollike the above except that the p1 Modula-2 debugger is linked into the tool.
m2make mytoolcompiles and links a command line tool from multiple modules. "mytool.mod" is expected as main module.
In detail: GenMake is run forst for the given module, followed by make. The tool is built for the current architecture.

chapter 1 (utilities) start page start page