In this first part of a three part article, Frank and Karel explore their motivation for writing a new programming “make tool”, the organization of the system itself and where you can get a copy. Part 2 of the article will cover the icmake grammer and the final part will show examples of its use.
3.1. The top-level programs.

At the top-level of icmake two programs are found. icmake itself and icmun. The program `icmake' is the monitor program, monitoring the execution of anicmake-script. The program `icmun' is an unassembler, showing the contents of the compiled icmake script in a human-readable form. Normally, icmun is not used: it serves mainly as a debugging tool (although we've used icmun also for instructional purposes, showing people some basic notions of assembly-language programming).


The icmake program monitors the execution of an icmake script, and acts therefore as an interface between the user and nested-level icmake programs. Normally, the nested-level icmake programs are not started explicitly at the command-line, but are called by icmake itself.

ICCE Make Utility Version 6.00

Icmake may be invoked unsing one of the two following command lines:

icmake [flags] asciifile [binaryfile] [arguments]


icmake [flags] -i asciifile [arguments]

The two invocation modes differ in the fact that the first invocation (without the i flag) makes it possible to specify explicitly the name of the compiled icmake file (the “binaryfile”). The second mode uses a predefined name for the compiled icmake file. In this form the name of the asciifile is used, having the extension “.bim”.

With both invocation modes the “flags”, the two consecutive hyphens and the arguments are optional. The arguments are passed to the makefile and can be inspected there. The flags are used for requesting specific actions of icmake. The specification of the asciifile is obligatory in both invocations: this file is the make script, which is interpreted by icmake and defines the actions to be performed.

Whenever program from the icmake-family is started without arguments, a help summary is displayed.

When icmake is activated without any arguments, the help shows among other things the flags which are recognized by icmake. In that case, something like the following table below will appear on the screen:

The following flags are recognized:

-b. When this flag is used, no recency test is performed. Rather, the binary make file is executed immediately `as is'. When this flag is absent, icmake compiles the input file (.im file) into a binary file (.bim file) if the input file is more recent.

-c. When this flag is used, the ascii input file is compiled to a binary makefile, but is not executed. The compilation occurs irrespective to the recency of the input file and the binary file.

-i file. This option specifies file as the input file for icmake and stops the further processing of the arguments. In this case the nam of the binary makefile (.bim file) is equal to the name of the input file receiving the extension .bim. The default input file extension, .im, is not supplied by icmake when this flag is given: the specified name is taken literally.

-p. When this option is used, only the icmake preprocessor is activated. The output of the preprocessor is sent to a file having the same name as the input file, but having the extension .pim. When this flag is absent, icmake's preprocessor still generates a .pim file. However, this file is deleted after the compilation-phase.

-q. When this option is used, icmake operates quietly. I.e., the copyright banner is not displayed.

--. By default, the first non-flag argument on the command line is the input file, for which the extension .im is assumed. When a second non-flag argument is given, then this name is used for the binary file (.bim file). The processing of arguments stops only when two consecutive hyphens are encountered. All arguments which follow the—flag can be inspected by the icmake-file.

Note that the—flag is not required when icmake is activated with the -i flag.

The asciifile specification is obligatory. This is the icmake source file which will be compiled and tested by icmake. Icmake assumes a default extension .im. E.g., the command line:

icmake test will activate icmake to process the icmake sourcefile test.im. Note however that the command line:

icmake -i test will start icmake to process the makefile test. The presence of the -i flag prevents icmake from supplying an extension.

The binaryfile specification is optional. When given, icmake uses this file as the binary intermediate file in the process of making. Extension .bim is the default. By default icmake uses the basename of the asciifile and extension .bim.

Following the binaryfile specification, several arguments to the makefile itself may be given. However, before any extra arguments are specified two consecutive hyphens are needed. Following these hyphens extra arguments may follow which will be passed to the icmake dependent programs. As described above, the delimiting two hyphens are not necessary when the -i flag is used.

The icmake specification file is written as a C program, and contains a main() function which receives some of the arguments specified on the command line. The first argument is always the name of the binairy make file (normally having the .bim extension). Remaining arguments are the arguments that follow the two hyphens. The hyphens themselves are not included in the series of arguments which are passed to main() (The user-defined function main() is described below).


Icmun is mainly used in developing icmake. The icmun program is an unassembler for the compiled icmake file created by icmake. Icmun produces an assembly-like listing of the instructions contained in the compiled makefile. Normally it is hardly ever used. More information about icmun is beyond the scope of this article, but can be found in the icmake documentation, which may be obtained from, e.g., beatrix.icce.rug.nl.

The nested-level programs.

The following programs are icmake's `nested-level' programs. Normally these programs are not started at the command-line, but are started as child- or overlay-processes of icmake itself.

The preprocessor icm-pp.

Icm-pp is the preprocessor of the icmake compiler (described in the next section). This program scans the icmake source file for preprocessor directives (e.g., #include, see the section on the preprocessor directives below). and takes appropriate actions when they are encountered. Icm-pp writes an output file in which the preprocessor directives have been `expanded'. This (temporary) file is used thereupon by the icmake compiler.

The compiler icm-comp.

The stage following the preprocessing is the compilation. The icmake compiler is called icm-comp, and this program translates an icmake source file, generated by icm-pp, into a binary format and performs error checking. The resulting binary file contains opcodes, much like the output file of a compiler of a programming language. When a binary makefile is generated, the intermediate output file of the preprocessor is no longer needed and is removed.

The executor icm-exec.

Icm-exec is the executor of the binary makefile generated by icm-comp. In this phase the compiled icmake file is read. It contains opcodes which are interpreted, thus executing the commands defined in the icmake source file: lists of files are built, files are compared by dates, and other actions may be taken.

Executable makefiles under Linux (Unix)

Under the Linux (UNIX) operating system it is possible to create makefiles for icmake which are themselves executable. As an example, this could result in a setup in which an icmakefile “backup” exists, which can simply be started as:


In such a setup the same effect may be achieved by creating an icmakefile backup.im, which is then started with the command:

icmake backup

The former form is certainly simpler to use, and requires an executable icmake script called `backup'. To create an executable makefile, the following steps should be taken:

  1. The makefile can be given a suitable name. This name is later used to invoke the process which executes the makefile. For this reason, the name backup may be preferred to backup.im.

  2. The makefile is made executable using the UNIX chmod program: chmod +x backup

    This labels the file backup as an executable program. Furthermore, the makefile may be placed in a directory pointed to by the PATH environment. E.g., the makefile may be placed in a user's private bin directory.

  3. The following line is added as the first line in the icmake source file:

    #!/usr/local/bin/icmake -qi

This line informs the operating system that, when executing this file, the program /usr/local/bin/icmake should be started, using the flags -qi and then appending the name of the icmake file. As discussed before, the flag -q suppresses icmake's copyright banner, while the flag -i causes icmake to take the following file argument as the literal input file instead of supplying the default extension .im.

Note that this line must contain a full reference, including the path, to the program icmake. In this example this path is taken to be /usr/local/bin.

The compiled icmake file (.bim file) is placed by icmake in the same directory as the icmake source This directory must therefore be accessible to the user invoking the makefile. If the icmake script and the associated .bim file is to be accessible system-wide, the icmake script could be installed by root. Using the example of the backup script again, root could install the “backup” script using the following command in the directory where the “backup” script is stored:

icmake -c backup

This will merely result in a compilation of “backup”, thus generating backup.bim.

Frank B. Brokken, ICCE, Department of Education Universtiy of Groningen. Groningen, the Netherlands.

K. Kubat, ICCE, Department of Education Universtiy of Groningen. Groningen, the Netherlands.