Utilities

From NitrOS-9
Jump to: navigation, search

Introduction

The OS-9 Level 2 Development System includes three utilities:

  • Make: Helps maintain the current version of software by keeping track of modifications to program source to determine the need for recompiling, reasssembling, or relinking files.
  • Touch: Updates the modification date of specified files.
  • Virtual Disk Driver/RAM Disk Driver: Creates a high-speed storage system in your computer's RAM that simulates a disk drive.

Make Utility

The make utility helps maintain the current version of software. It uses built-in knowledge of OS-9 compilers, file types, and file naming conventions to maintain up-to-date versions of your programs as you develop them. By keeping track of modifications to program source, make can determine the need to recompile, reassemble, and/or relink the files necessary to create an object file.

Using Make

The syntax for make is as follows:

    make options target1 [target2] [macros]

The target1 argument specifies the program that make is to create. Make accepts multiple arguments (target2, target3, ..., and so on). The macros argument lets you specify macros that make uses when creating the new target program.

The options argument can be one of the following:

-? Displays the usage of make.
-b Turns off built-in rules governing implicit file dependencies. Use this option if you are quite explicit about your makefile dependencies and do not want make to assume anything.
-d Turns on the make debugger and gives a complete listing of the macro definitions, a listing of the files as it check the dependency list, and all the file modification dates.
-f[=]path Specifies path as the makefile. If you omit this option, make searches for the file named makefile in the current directory.
-f Causes make to use the standard input instead of a makefile.
-i Ignores errors. If you omit this option, make stops execution if an error code is returned after executing a command line in a makefile.
-n Displays commands to standard output but does not execute them.
-s Executes command without echo (silent mode). If you omit this option, make echoes commands in the makefile to standard output.
-t Touches the files. <code.Make</code> opens the file for update and then closes it. This updates the modification dates without executing the commands.
-u Causes make to execute the makefile commands.
-x uses the cross-compiler/assembler.
-z Reads a list of make targets from standard input.
-z=path Reads a list of make targets from path.

You can include options on the command line when you run make or include them in the makefile. You can also define one or more macros on a command line instead of a makefile or to override a macro definition in a makefile. Enclose in quotes any macro definitions that contain spaces or other delimiters. See the following section "Macros".

Examples

    make -f/dd/source/test.make -i test

This make command creates a program called {test} using the makefile /dd/source/test.make. Make ignores any errors that occur.

    make -s myprog

Make uses the file makefile in the current directory as the makefile for the program myprog. Make does not echo commands during execution.

What is a Makefile?

A makefile is a special type of procedure file that describes the dependencies between files that make up the target program. The makefile contains a sequence of entries that specifies dependencies and commands to resolve those dependencies. A dependency entry begins with the target name of the file or module following by a colon (:). This is then following by a list of files that are prerequisite to building the target file. This is called a dependency list.

In addition to the dependency entry, the makefile can contain commands on how to update a particular target file (if it needs to be updated). Makes updates a target file on if it depends on files that are newer than the target file. If make cannot find the file, it assumes a date of -01/00/00 00:00, indicating that the file needs updating. If you do not specify update instructions, make attempts to create a command line to perform the operation. Make recognizes a command line because it begins with one or more spaces.

The following is a simple makefile:

program: xxx.r yyy.r
   cc xxx.r yyy.r -xf=program
xxx.r: xxx.c /dd/defs/os9defs.h
   cc xxx.c -r
yyy.r: yyy.c /dd/defs/os9defs.h
    cc yyy.c -r

This makefile specifies that the target file program is made up of two relocatable files (.r suffix): xxx.r and yyy.r. These files are dependent on xxx.c and yyy.c, respectively, and both files are dependent on the file os9defs.h.

If either xxx.c or /dd/defs/os9defs.h has a more recent modification date than xxx.r, make executes the command cc xxx.c -r. Likewise, if either yyy.c or /dd/defs/os9defs.h has a more recent modification date than yyy.r, make executes the command cc yyy.c -r. If either of the former commands is executed, make also executes the command cc xxx.y yyy.r -xf=program.

Built-in Rules and Definitions

Make uses the following conventions when determining file types or in definiing its rules:

Source Files Files with a suffix or either .a, .c, .f, or .p are source files in assembly, C, Fortran, and Pascal, respectively.
Relocatable Files Make determines a file to be relocatable if it has the suffix .r. Relocatable files are made from source files and are assembled or compiled, if necessary, during a make.
Object Files Make determines a file to be an object file if the file does not have a suffix. An object file is make from relocatable files and linked, if necessary, during a make.
Default Compiler Make's default compiler is cc.
Default Assembler Make's default assembler is the Relocatable Macro Assembler (RMA).
Default Linker Make's default linker is cc. You should only use the default linker with programs that use cstart.r.
Default Directory Make uses the current directory (.) for all files.

Macros

You can use macros within a makefile or on the command line. Use the following form to specify a macro:

    macro-name=expansion

Make then substitutes every occurrence of macro-name with the expansion.

Macro names are prefixed with the dollar sign character ($). If you want to specify a macro name longer than a single character, you must enclose the name in parentheses. For example, $R refers to the macro R and $(PFLAGS) refers to the macro PFLAGS. The macro names $(B) and $B refer to the same macro, B. The macro name $BR refers to the B macro also, followed by the character R.

Note: If you define a macro in your makefile and then redefine it on the command line, the command line definition overrides the definition in the makefile. You might find this feature useful for compiling with special options.

Special Macros

Make provides the following special macros:

Macro Definition
SDIR=path Make searches the directory, specified by path, for all implicitly defined source files. If you do not define SDIR within the makefile, make searches the current directory.
RDIR=path Make searches the directory, specified by path, for all implicitly defined relocatable files. If you do not define RDIR within the makefile, make searches the current directory.
ODIR=path Make searches the directory, specified by path, for all files that have no suffix or relatively pathlist (object files). The default is the current execution directory.
CFLAGS=options Make uses the specified compiler options to generate command lines.
RFLAGS=options Make uses the specified assembler options to generate command lines.
LFLAGS=options Make uses the specified linker options to generate command lines.

Reserved Macros

Make expands the following macros when a command line associated with a particular file dependency is forked. You might find these macros useful when you need to be explicit about a command line but have a target program with several dependencies. You can use these macros only in a makefile command.

Macro Expands to:
$@ The name of the file to be made by the command
$* The prefix of the file to be made
$? The list of files that were found to be newer than the target file on a given dependency line

Commands

You can specify more than one command for any dependency. Make forks each command separately unless it is continued from the previous command (see Long Lines).

If you start a command line with the @ symbol, make does not echo to standard output. If you start a command line with a hyphen (-), make ignores any error codes returned on that line.

If your system runs out of memory while executing a command, you can redirect the output of make into a procedure file and execute the procedure file.

Do not mix comments and commands.

Comments

You can specify an entire line as a command by placing an asterisk (*) as the first character in that line. You can place comments at the end of a line by preceding the comment with the pound sign character (#).

Make ignores blank lines within a makefile.

Long Lines

If you use lines long than 256 characters or lines wider than your screen, you need to place a space followed by a backslash (\) at the end of each line to be continued. The continuation line must have a space or tab as its first character.

For example:

    Files: aaa.r bbb.r ccc.r ddd.r eee.r fff.r ggg.r \
     hhh.r iii.r jjj.r

Make ignores leading spaces and tabs on non-command lines and continuation lines.

How Make Works

Make starts by using the makefile to set up a table of dependencies. When make encounters a name on the left side of the colon, make first checks to see if it has encountered the name before. If make has, it connects the lists and continues. It treats every item on the right side of the colon as a unique structure.

After reading the entire makefile, make determines the target file (the main file to be made) on the list. It then makes a second pass through the subtable. It looks for object files that have no relocatable files in their dependency lists and for relocatable files that have no source files in their dependency lists.

If make needs to find any source files or relocatable files to complete the dependency lists, it looks for them in the directory specified by the macros SDIR and RDIR (or RDIR's default .). Make looks in these directories for files with the same name as their dependent file. For example, if no source file is found for program.r, make searches the specified directory (RDIR or .) for program.a (or .c, p., .f).

Make does a third pass through the list to get the file dates and compares them. When make finds a file that is newer than its dependent file, it generates the necessary command or executes the command given. Since OS-9 only stores the time down to the closest minute, make remakes a file if its date matches one of its dependents.

Note: When make generates a command line for the linker, it looks at its list and uses the first relocatable file that it finds, but only the first one. For example:

    prog: x.r y.r z.r

generates the following:

    cc x.r

It does not generate cc x.r y.r z.r or cc prog.r

Notes about Make

If an object has more than one dependency, make links the dependency lists together. If the first dependency lists multiple objects, then all the objects on that dependency line share the same set of dependencies. This might or might not be correct, depending on the situation. If the following example, the first makefile is correct, and the second one creates some extra dependencies:

First makefile:

    x.r: defs.h
    x.r y.r z.r: defs2.h

Second makefile:

    x.r y.r z.r: defs2.h
    x.r: defs.h

The first makefile specifies that x.r is dependent on defs.h and defs2.h. It specifies y.r and z.r as dependent on defs2.h.

The second makefile specifies that all three .r files are dependent on defs2.h, and seems to specify only x.r as dependent on defs.h. Because the second makefile lists all three .r files on the same dependency line, they implicity share in any future dependencies for any of the individual files. Therefore, x.r, y.r, and z.r are all implicitly dependent on defs.h.

Note: The make language is very specific. Therefore, you need to be careful when you use dummy files with names line print. Unless a file is specifically an object file or you use the -b option to turn off the implicit rules, use a suffix for your dummy files (i.e. print.file and xxx.h for header files).

Examples of Makefiles

Example 1

    program: xxx.r yyy.r
        cc xx.r yyy.r -xf=program

    xxx.r yyy.r: /dd/defs/os9defs

This example shows a shorter version of the makefile shown earlier in this chapter. This example makes use of make's awareness of file dependencies. Because the makefile makes no mention of C-language file, make looks in the directory specified by the macro definition SDIR=path (in this case, the default of the current directory) and adjusts the dependency list accordingly. Make also generates a command line to compile xxx.r and yyy.r if one or both need updating.

Example 2

    program:

This simple makefile uses only one source file. Make assumes the following from this simple command:

  1. Because program has no suffix, make assumes that it is an object file and therefore needs to rely on relocatable files to be made.
  2. Because there is no dependency list given, make creates an entry in the table for program.r.
  3. After creating an entry for program.r, make creates an entry for a source file connected to the relocatable file.

If make finds the file program.a, it checks the dates on the various files and generates one or both of the following commands, if required:

    rma program.a -o=program.r
    cc program.r

Example 3

    * beginning
    ODIR = /dd/cmds
    RDIR = rels
    UTILS = attr copy load dir backup dsave
    SDIR = ../utils/sources

    utils.files: $(UTILS)
        touch utils.files

    *end

In this example, make looks in the rels directory for attr.r, copy.r, load.r, etc. and looks in ../utils/sources for attr.c, copy.c, load.c, and so on. Make then generates the proper commands to compile and/or link any of the programs that need to be made. If one of the files in the utils directory is made, make forks the command touch util.files to maintain a current overall date.

Example 4

    * beginning
    ODIR = /h0/cmds
    RDIR = rels
    CFILES = domake.c doname.c dodate.c domac.c
    RFILES = domake.r doname.r dodate.r
    R2 = ../test/domac.r
    RFLAGS = -q

    make: (RFILES) (R2) getfd.r
        linker

    $(RFILES): defs.h
    $(R2): defs.h
        cc $*.c -r=../test

    print.file: (CFILES)
        list $? >/p
        touch print.file

    * end

This example is a makefile to create make. This makefile looks for the .r files (listed in RFILES) in the directory specified by RDIR (rels). The only exception is ../test/domac.r, which has a complete pathlist specified.

Even though getfd.r does not have any explicit dependents, make checks its dependency on getfd.a. All of the source files are found in the current directory.

Notice that you can use this makefile to make listings as well. By typing make print.file on the command line, make expands the macro $? to mean all ofthe files that were updated since the last time print.file was updated. If you keep a dummy file called print.file in your current directory, it only prints the newly made file. If no print.file exists, make prints all the files.

Example 5

See the makefile in the SOURCES directory of Disk 2 in the OS-9 Level 2 Development System. This complete makefile is for use with the updn.a and lsit.a examples in Chapter 11 of the "Relocatable Macro Assembler" section of this manual.

Touch Utility

The touch utility updates the last modification date of a file. This command is especially useful when used inside a makefile with make. Associated with every file is the date that the file was last modified. The touch utility simply opens a file and closes it, thereby updating the time that the file was last modified with the current date.

If touch cannot find the specified file, it creates the file with the current date as the modification date.

The syntax for touch is:

    touch options filename

The options include any of the following:

-? Displays the usage of touch
-c Does not create file if touch cannot find the specified file
-q Does not stop execution if an error occurs
-x Searches the execution directory for the file
-z Reads the filenames from the standard input
-z=path Reads the filenames from path

Examples

    touch -c /h0/doc/program

Touch searches for the specified file but does not create it if it does not exist.

    touch -cz

Touch reads the filenames from standard input. If it cannot find a specified file, touch does not create it. [CTRL][BREAK] at the beginning of a line signals touch to terminate.

    touch -z=filelist

Touch reads filenames from filelist, a file containing one filename on each line.

Virtual Disk/RAM Disk Driver

The Virtual Disk Driver is a high-speed, general storage/retrieval system that uses your computer's memory to simulate a fast disk device. You can use the VDD to store frequently used files (such as OS9Defs) and programs to cut down on floppy disk access time. The Virtual Disk Driver uses two to six pages of system address space and allocates the amount of RAM specified in the description (R0).

The VDD system consists of two modules: R0 (the VDD description) and RAM (the driver).

Initializing VDD

You can initialize the Virtual Disk Device by issuing an I$Attach call for R0 or by opening or creating a file on R0. You can also use iniz to perform the I$Attach call. The syntax for iniz is as follows:

    iniz r0

Note: Do not use I$Open and I$Create to initialize VDD even though they both do an implicit I$Attach, because the I$Close call does an implicit I$Detach. If an I$Attach call is not made before the file is opened, all data in the RAM disk is lost when the file is closed.

When VDD is initialized, it obtains information about the total amount of memory it is to allocate and the system memory block size from the descriptor. VDD then initializes Sector 0, the bit map, and the root directory. Once the RAM disk is initialized, you can treat R0 like any other disk device.

R0 is a standard RBF device descriptor. You can choose the amount of RAM used by VDD by changing the default sectors per track (module offset $1B). To do so, use the debugger or reassemble R0 with the desired alteration. The size that VDD uses can be changed by altering the number of surfaces (module offset $19).

Your development diskette contains three versions of R0, a 96 kilobyte version, a 128 kilobyte version, and a 192 kilobyte version. You can only use one version at a time.