Super Prev Next

Using the compiler

Super Prev Next

Invoking the compiler

The XDS Modula-2 and Oberon-2 compilers are combined together with the make subsystem and an Oberon-2 browser into a single utility, xc. When invoked without parameters, the utility outputs a brief help information.

xc is invoked from the command line of the following form

    xc { mode | option | name }

where name, depending on the operation mode can be a module name, a source file name, or a project file name. See XDS compilers operation modes for a full description of operation modes.

option is a compiler setup directive (See Options). All options are applied to all operands, notwithstanding their relative order on the command line. On some platforms, it may be necessary to enclose setup directives in quotation marks:

    xc hello.mod '-checkindex+'

See Chapter Compiler options and equations for the list of all compiler options and equations.

Super Prev Next

Precedence of compiler options

The xc utility receives its options in the following order:

  1. from a configuration file xc.cfg (See Configuration file)
  2. from the command line (See XDS compilers operation modes)
  3. from a project file (if present) (See Project files)
  4. from a source text (not all options can be used there) (See Source code directives)

At any point during operation, the last value of an option is in effect. Thus, if the equation OBERON was set to .ob2 in a configuration file, but then set to .o2 on the command line, the compiler will use .o2 as the default Oberon-2 extension.

Super Prev Next

XDS compilers operation modes

XDS Modula-2/Oberon-2 compilers have the following operation modes:

Mode Meaning
COMPILE Compile all modules given on the command line
PROJECT Make all projects given on the command line
MAKE Check dependencies and recompile
GEN Generate makefile for all projects
BROWSE Extract definitions from symbol files
HELP Print help and terminate

Both the PROJECT and MAKE modes have two optional operation submodes: BATCH and ALL. Two auxiliary operation submodes — options and EQUATIONS can be used to inspect the set of compiler options and equations and their values.

On the command line, the compiler mode is specified with the "=" symbol followed by a mode name. Mode names are not case sensitive, and specifying an unique portion of a mode name is sufficient, thus

    =PROJECT is equivalent to =p
    =BROWSE  is equivalent to =Bro

Operation modes and options can be placed on the command line in arbitrary order, so the following two command lines are equivalent:

    xc =make hello.mod =all -checknil+
    xc -checknil+ =a =make hello.mod

Super Prev Next


    xc [=compile] { FILENAME | OPTION }

COMPILE is the default mode, and can be invoked simply by supplying xc with a source module(s) to compile. If xc is invoked without a given mode, COMPILE mode is assumed. In order to determine which compiler should be used, xc looks at the extensions of the given source files. The default mapping of extensions is given below :

.mod - Modula-2 implementation module
.def - Modula-2 definition module
.ob2 - Oberon-2 module

For example:

    xc hello.mod

will invoke the Modula-2 compiler, whereas:

    xc hello.ob2

will invoke the Oberon-2 compiler.

The user is able to reconfigure the extension mapping (See Filename extensions). It is also possible to override it from the command line using the options M2 and O2:

    xc hello.mod +o2  (* invokes O2 compiler *)
    xc hello.ob2 +m2  (* invokes M2 compiler *)

Note: In the rest of this manual, the COMPILE mode also refers to any case in which the compiler compiles a source file, regardless of the actually specified mode (which can be COMPILE, MAKE, or PROJECT). For instance, an option or equation, which is stated to affect the compiler behaviour in the COMPILE mode, is relevant to MAKE and PROJECT modes as well.

Super Prev Next

MAKE mode

    xc =make [=batch] [=all] { FILENAME | OPTION }

In the MAKE mode the compiler determines module dependencies using IMPORT clauses and then recompiles all necessary modules. Starting from the files on the command line, it tries to find an Oberon-2 module or a definition and implementaion module for each imported module. It then does the same for each of the imported modules until all modules are located. Note that a search is made for source files only. If a source file is not found, the imported modules will not be appended to the recompile list. See section Make strategy for more details.

When all modules are gathered, the compiler performs an action according to the operation submode. If the BATCH submode was specified, it creates a batch file of all necessary compilations, rather than actually compiling the source code.

If the ALL submode was specified, all gathered files are recompiled, otherwise XDS recompiles only the necessary files. The smart recompilation algorithm is described in Smart recompilation.

Usually, a Modula-2 program module or an Oberon-2 top-level module is specified on the command line. In this case, if the LINK equation is set in either configuration file or xc command line, the linker will be invoked automatically in case of successful compilation. This feature allows you to build simple programs without creating project files.

Super Prev Next


    xc =project [=batch] [=all] { PROJECTFILE | OPTION }

The PROJECT mode is essentially the same as the MAKE mode except that the modules to be ‘made’ are provided in a project file. A project file specifies a set of options and a list of modules. See Project files for further details. As in the MAKE mode, ALL and BATCH submodes can be used.

If a file extension of a project file is omitted, XDS will use an extension given by the equation PRJEXT (.prj by default).

It may be necessary to compile a single module in the environment specified in a project file. It can be accomplished in the COMPILE operation mode using with the PRJ equation:

    xc -prj=myproject MyModule.mod

See also

Super Prev Next

GEN mode

    xc =gen { PROJECTFILE | OPTION }

The GEN operation mode allows one to generate a file containing information about your project. The most important usage is to generate a linker response file (See Building a program).

This operation mode can also be used to obtain additional information about your project, e.g. a list of all modules, import lists, etc.

A so-called template file, specified by the TEMPLATE equation, is used in this mode. A template file is a text file, some lines of which are marked with a certain symbol. All the lines which are not marked are copied to the output file verbatim. The marked lines are processed in a special way. See Template files for more information.

The compiler creates a file with a name specified by the equation MKFNAME. If the equation is empty, the project file name is used. A file name is then concatenated with the extension specified by the equation MKFEXT.

Super Prev Next


    xc =browse { MODULENAME | OPTION }

The BROWSE operation mode allows one to generate a pseudo definition module for an Oberon-2 module. In this mode, the compiler reads a symbol file and produces a file which contains declarations of all objects exported from the Oberon-2 module, if a format resembling Modula-2 definition modules.

The configuration option BSDEF specifies the extension of a generated file. If this option is not set, then the default extension (.odf) will be used.

Options BSCLOSURE and BSREDEFINE can be used to control the form of a generated file. Note: the BSTYLE equation (described in Creating a definition) is ignored in this operation mode, and the browse style is always set to DEF.

The MAKEDEF option (See Creating a definition) provides an alternative method of producing pseudo definition modules, preserving so-called exported comments if necessary.

Super Prev Next

ALL submode

In both PROJECT and MAKE modes, the compiler checks the time stamps of the files concerned and recompiles only those files that are necessary (See Smart recompilation). If the ALL submode was specified, the time stamps are ignored, and all files are compiled.

Super Prev Next

BATCH submode

In the BATCH submode, the compiler creates a batch file of all necessary compilations, rather than actually calling the compilers and compiling the source code.

A batch file is a sequence of lines beginning with the compiler name, followed by module names to recompile.

The compiler creates a batch file with a name determined by either:

  1. The compiler option BATNAME
  2. The project file name (if given)
  3. The name out (if the name could not be determined by the above).

The name is then concatenated with the batch file extension specified by the equation BATEXT (.bat by default).

See also

Super Prev Next

OPTIONS submode

The OPTIONS submode allows you to inspect the values of options which are set in the configuration file, project file and on the command line. It can be used together with COMPILE, MAKE, and PROJECT modes.

The following command line prints (to the standard output) the list of all defined options, including all pre-declared options, all options declared in the configuration file, in the project file my.prj and on the command line (xyz option):

    xc =options -prj=my.prj -xyz:+

In the PROJECT mode options are listed for each project file given on the command line.

See also the EQUATIONS submode.

Super Prev Next


The EQUATIONS submode allows you to inspect the values of equations which are set in the configuration file, project file and on the command line. It can be used together with COMPILE, MAKE, and PROJECT modes.

See also the OPTIONS submode.

Super Prev Next

Files generated during compilation

When applied to a file which contains a module name, the compilers produce the following files.

Super Prev Next

Modula-2 compiler

When applied to a definition module, the Modula-2 compiler produces a symbol file(name.sym). The symbol file contains information required during compilation of a module which imports the module name.

When applied to an implementation module or a top level module, the Modula-2 compiler produces an object file (name.obj).

Super Prev Next

Oberon-2 compiler

For all compiled modules, the Oberon-2 compiler produces a symbol file (name.sym) and an object file (name.obj). The symbol file(name.sym) contains information required during compilation of a module which imports the module name. If the compiler needs to overwrite an existing symbol file, it will only do so if the CHANGESYM option is set ON.

Super Prev Next

Command line Generated files
xc Example.def Example.sym
xc Example.mod Example.obj
xc Win.ob2 +CHANGESYM Win.sym

Super Prev Next

Control file preprocessing

An XDS compiler may read the following control files during execution:

All these files are preprocessed during read according to the following rules:

A control file is a plain text file containing a sequence of lines. The backslash character ("\") at the end of a line denotes its continuation.

The following constructs are handled during control file preprocessing:

A directive has the following syntax (all keywords are case independent):

Directive = "!" "NEW" SetOption | SetEquation
          | "!" "SET" SetOption | SetEquation
          | "!" "MESSAGE" Expression
          | "!" "IF" Expression "THEN"
          | "!" "ELSIF" Expression "THEN"
          | "!" "ELSE"
          | "!" "END".
SetOption   = name ( "+" | "-" ).
SetEquation = name "=" string.

The NEW directive declares a new option or equation. The SET directive changes the value of an existent option or equation. The MESSAGE directive prints Expression value to the standard output. The IF directive allows to process or skip portions of files according to the value of Expression. IF directives may be nested.

Expression  = Simple [ Relation Simple ].
Simple      = Term { "+" | OR Term }.
Relation    = "=" | "#" | "<" | ">".
Term        = Factor { AND Factor }.
Factor      = "(" Expression ")".
            | String
            | NOT Factor
            | DEFINED name
            | name.
String      = "'" { character } "'"
            | '"' { character } '"'.

An operand in an expression is either string, equation name, or option name. In the case of equation, the value of equation is used. In the case of option, a string "TRUE" or "FALSE" is used. The "+" operator denotes string concatenation. Relation operators perform case insensitive string comparison. The NOT operator may be applied to a string with value "TRUE" or "FALSE". The DEFINED operator yields "TRUE" if an option or equation name is declared and "FALSE" otherwise.

See also section The system module COMPILER.

Super Prev Next

Project files

A project file has the following structure:

    {!module {FileName}}

Setup directives define options and equations that all modules which constitute the project should be compiled with. See also Options and Control file preprocessing.

Every line in a project file can contain only one setup directive. The character "%" indicated a comment; it causes the rest of a line to be discarded. Note: the comment character can not be used in a string containing equation setting.

Each FileName is a name of a file which should be compiled, linked, or otherwise processed when a project is being built, e.g. a source file, an additional library, a resource file (on Windows), etc. The compiler processes only Modula-2 and Oberon-2 source files. The type of a file is determined by its extension (by default Modula-2/Oberon-2 source files extension is assumed). Files of other types are taken into account only when a template file is processed (see Template files).

The compiler recursively scans import lists of all specified Modula-2/Oberon-2 source modules and builds the full list of modules used in the project. Thus, usually, a project file for an executable program would contain a single !module directive for the file which contains the main program module and, optionally, several !module directives for non-source files.

At least one !module directive should be specified in a project file.

A project file can contain several LOOKUP equations, which allow you to define additional search paths.

XDS compilers give you complete freedom over where to set options, equations and redirection directives. However, it is recommended to specify only those settings in the configuration and redirection files which are applied to all your projects, and use project files for all project-specific options and redirection directives.

Figure 2. A Sample Project File

    -lookup = *.mod = mod
    -lookup = *.sym = sym; $(XDSDIR)/sym/C
    % check project mode
    !if not defined mode then
      % by default use debug mode
      !new mode = debug
    % report the project mode
    !message "Making project in the " + mode + " mode"
    % set options according to the mode
    !if mode = debug then
       - gendebug+
       - checkrange+
       - gendebug-
    % specify template file
    - template = $!/templates/watcom.tem
    !module hello
    !module hello.res

Given the sample project file shown on Figure 2. A Sample Project File, the compiler will search for files with .mod and .sym extensions using search paths specified in the project file before paths specified in a redirection file.

A project file is specified explicitly in the PROJECT and GEN operation modes. In these modes, all options and equations are set and then the compiler proceeds through the module list to gather all modules constituting a project (See Make strategy).

In the MAKE and COMPILE operation modes, a project file can be specified using the PRJ equation. In this case, the module list is ignored, but all options and equations from the project file are set.

The following command line forces the compiler to compile the module hello.mod using options and equations specified in the project file hello.prj:

    xc hello.mod -prj=hello.prj

Super Prev Next

Make strategy

This section concerns MAKE, PROJECT, and GEN, operation modes. In these modes, an XDS compiler builds a set of all modules that constitute the project, starting from the modules specified in a project file (PROJECT and GEN) or on the command line (MAKE).

The MAKE mode is used in the following examples, but the comments also apply to the PROJECT and GEN modes.

First, the compiler tries to find all given modules according to the following strategy:

Starting from the given files, the compiler tries to find an Oberon-2 source module or Modula-2 definition and implementation modules for each imported module. It then tries to do the same for each of the imported modules until all the possible modules are located. For each module, the compiler checks correspondence between the file name extension and the kind of the module.

Super Prev Next

Smart recompilation

In the MAKE and PROJECT modes, if the ALL submode was not specified, an XDS compiler performs smart recompilation of modules which are inconsistent with the available source code files. The complier uses file modification time to determine which file has been changed. For each module the decision (to recompile or not) is made only after the decision is made for all modules on which it depends. A source file is (re)compiled if one or more of the following conditions is true:

Modula-2 definition module
Modula-2 implementation module
Modula-2 program module
Oberon-2 module

When the VERBOSE option is set ON, the compiler reports a reason for recompilation of each module. Note: if an error occured during compilation of a Modula-2 definition module or an Oberon-2 module, all its client modules are not compiled at all.

Super Prev Next

Template files

A template file is used to build a "makefile" in the PROJECT and GEN operation modes, if the option MAKEFILE is ON / "MAKEFILE" is a historical name; a linker or library manager response file may be built as well./ .

The compiler copies lines from a template file into the output file verbatim, except lines marked as requiring further attention. A single character (attention mark) is specified by the equation ATTENTION (default is ’!’)

A template file is also subject to preprocessing.

A marked line (or template) has the following format /The same syntax is used in the LINK equation./ :

    Template  = { Sentence }.
    Sentence  = Item { "," Item } ";" | Iterator.
    Item      = Atom | [ Atom | "^" ] "#" [ Extension ].
    Atom      = String | name.
    String    = '"' { character } '"'
              | "'" { character } "'".
    Extension = [ ">" ] Atom.
    Iterator  = "{" Set ":" { Sentence } "}".
    Set       = { Keyword | String }
    Keyword   = DEF | IMP | OBERON | MAIN
              | C | HEADER | ASM | OBJ.

name should be a name of an equation. Not more than three items may be used in a sentence. A first item in a sentence is a format string, while others are arguments.

The XDS distribution contains a template file xc.tem which can be used to produce a linker response file.

Super Prev Next

Using equation values

In the simplest form, a template line may be used to output a value of an equation. For example, if the template file contains the line

     ! "The current project is %s.\n",prj;

and the project prj\test.prj is processed, the output will contain the line

    The current project is prj\test.prj.

Note: the line

    ! prj;

is valid, but may produce unexpected results under systems in which the backslash character ("\") is used as a directory names separator (e.g. OS/2 or Windows):

    prj     est.prj

because "\t" in a format string is replaced with the tab character. Use the following form instead:

    ! "%s",prj;

Super Prev Next

File name construction

The "#" operator constructs a file name from a name and an extension, each specified as an equation name or literal string. A file is then searched for according to XDS search paths and the resulting name is substituted. For example, if the file useful.lib resides in the directory ’../mylibs’ and the redirection file contains the following line:

    *.lib = /xds/lib;../mylibs

the line

    ! "useful"#"lib"

will produce


If the modifier ">" is specified, the compiler assumes that the file being constructed is an output file and creates its name according to the strategy for output files (See Redirection file and the OVERWRITE option).

The "#" operator is also used to represent the current value of an iterator. The form in which a name or extension is omitted can be used in an iterator only.

The form "^#" may be used in a second level iterator to represent the current value of the first level iterator.

Super Prev Next


Iterators are used to generate some text for all modules from a given set. Sentences inside the first level of braces are repeated for all modules of the project, while sentences inside the second level are repeated for all modules imported into the module currently iterated at the first level. A set is a sequence of keywords and strings. Each string denotes a specific module, while a keyword denotes all modules of specific kind.

The meaning of keywords is as follows:

Keyword Meaning
DEF Modula-2 definition module
IMP Modula-2 implementation module
MAIN Modula-2 program module or Oberon-2 module marked as MAIN
OBERON Oberon module
ASM assembler source text
OBJ object file

A keyword not listed above is treated as filename extension. Sentences are repeated for all files with that extension which are explicitly specified in the project file using !module directives (see Project files). This allows, for instance, additional libraries to be specified in a project file:


    -template = mytem.tem
    !module Sample.mod
    !module mylib.lib

      .  .  .
    ! "%s","libxds"#"lib"
    ! { lib: "+%s",#; }
    ! "\n"
      .  .  .

generated file:
      .  .  .
      .  .  .

Super Prev Next


Consider a sample project which consists of a program module A, which imports modules B and C, and B, in turn, imports D (all modules are written in Modula-2):

               / \
              B   C

The following examples illustrate template files usage:

This template line lists all project modules for which source files are available:

    ! { imp oberon main: "%s ",#; }

For the sample project, it would generate the following line:

    A.mod B.mod C.mod D.mod

To output both definition and implementation modules, the following lines may be used:

    ! { def : "%s ",#; }
    ! { imp oberon main: "%s ",#; }

The output would be:

    B.def C.def D.def A.mod B.mod C.mod D.mod

The last template line may be used to list all modules along with their import:

    ! { imp main: "%s\n",#; { def: "  %s\n",#; } }

The output: