Installing SRC Modula-3 on Windows/NT or Windows 95

What's Required

To build SRC Modula-3 for the Windows/NT and Windows 95 platforms, fetch the boot file "boot-NT386.tar.gz". On these platforms, the file "m3cc.tar.gz" is not needed, since "NT386" includes a native code generator.

However, to build SRC Modula-3 on either of these platforms, you will need to have Microsoft Visual C++ (version 2.0 or greater) installed on your system. This is necessary because the release requires a 32-bit C compiler (msvc\bin\cl), a 32-bit linker (msvc\bin\link), a 32-bit librarian (msvc\bin\lib), and the following libraries:

We don't know if there are versions of these libraries in the public domain, or if there are any public domain substitutes for them.

Using Other C Compilers

As of early 1996, we only know that Modula-3 works as distributed on the NT386 platform when used in conjunction with the Microsoft Visual C++ (version 2.0 or version 4.0) compiler and tools. However, here are several potential alternatives:
Microsoft Visual C++
Microsoft provides two ways to get their goods: retail and subscription. The latest retail version of the compiler is 2.0; Egghead offers it for $349. The latest subscription version is 2.2. In December 1995, Microsoft started shipping Visual C++ version 4.0. We don't know about its pricing or availability. At least one person has been able to use Visual C++ version 4.0 to successfully build SRC Modula-3 on Windows/NT.

Watcom C/C++ Compiler
The latest version is 10.5; the MSRP is $350; Marc found it in a mail-order catalogue for $269.

Symantec C++
The latest version is 7.0; Marc found it in a mail-order catalogue for $195.

Borland C++
This seems to be Borland's top-of-the line C compiler. Marc found it in a mail-order catalogue for $329.

Borland Turbo C++, Borland Turbo C++ Visual Edition
These seem to be slimmed-down versions of Borland C++. Unfortunately, they only generate 16-bit targets, so they can't be used with SRC Modula-3.

GNU gcc
A Windows version of the GNU tools (gcc, ranlib, ...). Free. There seem to be GNU versions of most of the tools and libraries. The only thing we have not found are the following libraries: msvcrt.lib, winspool.lib, comdlg32.lib, netapi32.lib. We expect the GNU C runtime should provide a substitute for msvcrt.lib. We don't know about the other three libraries. If you want to investigate this path yourself, the relevant URL's are:
ftp://ftp.cygnus.com/pub/sac/win32/README ftp://ftp.cygnus.com/pub/sac/win32/
We must stress that, except for MS Visual C++ version 2.0 and version 4.0, we haven't verified that any of these compilers can be used to build Modula-3 programs. We have explored the GNU tools the most; there are some indications that they won't work out of the box.

If you get SRC Modula-3 built on either Windows/NT or Windows 95 using a compiler other than Microsoft Visual C++, please send mail to m3-request@src.dec.com to let us know!

Installation Notes

The following notes were taken from a post made by Jerome Collin to the news group comp.lang.modula3 on 27 April, 1996. Jerome's notes have been edited somewhat for clarity.

These notes describe how to build version test-3.5.4-B of the SRC Modula-3 compiler on Windows 95. However, some of the remarks also apply to building the compiler on Windows NT. These notes augment the regular instructions for installing the SRC Modula-3 compiler. They only describe how to install the compiler, not all of the packages that come with the SRC Modula-3 distribution.

  1. First, install Microsoft Visual C++ on your PC. When the installation of the Microsoft Visual C++ compiler was done on our system, some environment variables were not set. We had to add the line
    c:\msdev\bin\vcvars32.bat
    
    to our autoexec.bat file to complete the set-up. This is, of course, for our own site and must be taken as an example, but make sure you can call the "nmake" program of this compiler.

  2. The m3boot.bat and m3ship.bat files in the boot-NT386 directory can lead to problems. Some environment variables are defined at the top of those scripts and used later in those same scripts. As I read on the web, the console process in which a script is executed can run out of memory in which to set these envrironment variables on Windows 95. To fix the problem, simply replace occurences of these variables by the values defined for them at the top of the script, then remove the lines at the top of the script where the variables are defined.

  3. Beta versions of Windows 95 contain a bug that requires the argument to the exec system call to begin and end with literal double-quote characters. But they are no longer needed on Windows 95 or on Windows NT, so unless you're using an old, beta version of Windows 95, you can skip ahead to the next item.

    The file "boot-NT386\quake\src\builtin.c" must be modified. A portion of the ExecuteCommand function in this file looks like this:

    /*
     * These machine-dependent fragments call the system(3) library call (or
     * equivalent) the right way.  Each fragment defines a variable `exit_code'
     * to be non-zero if the call failed.
     */
    
    #ifdef SYSTEM_FOR_WIN32
    
    /*-----------------03/02/95 22:41-------------------
     The correct format is:
            system ("\"cmd1 [[arg11 arg12 ...] [&& cmd2 arg21 arg22 ...]]\"");
    --------------------------------------------------*/
            int exit_code;
            char *cmdSep = "\"";
            int newLen = strlen(real_command) + 2*strlen(cmdSep) + 1;
            char* buffer = NEW_ARRAY(char, newLen);
    
            buffer[0] = '\0';
            strcat(buffer, cmdSep);
            strcat(buffer, real_command);
            strcat(buffer, cmdSep);
    
            exit_code = system(buffer);
    
            Utils_FreeMemory(buffer);
    

    Since we don't need double quotes on Windows 95, almost all the code can be deleted, and the argument to the system call can take the original string, like this:

    /*
     * These machine-dependent fragments call the system(3) library call (or
     * equivalent) the right way.  Each fragment defines a variable `exit_code'
     * to be non-zero if the call failed.
     */
    
    #ifdef SYSTEM_FOR_WIN32
            int exit_code;
            exit_code = system(real_command);
    

  4. When you get the package "boot-NT386", the template file "boot-NT386\m3build\NT386" is the one used at SRC. There is another template called "NT386-EXT that should be used instead. Delete "NT386" and rename "NT386-EXT" as "NT386". The usual modifications for your own site must be done too.

    You should skip the last part of the script in that file, that is, the section "one last thing" (about the last ten lines of the file). This is required to use m3ship without problem.

    Finally, the procedure "install_file" in the template should also be modified. The DOS command "COPY" must be used instead of "cp -r". To give you an example, our own template file is included below.

  5. With the previous modifications, a bootstrap compiler can be built. However, there is another modification to do in the "m3" package (namely, the package produced by unpacking the file "m3.tar.gz" that comes with the distribution). In the directory "m3/src", the "m3makefile" is special. It's a script that runs m3build and m3ship to build every desired package of the SRC Modula-3 distribution. The problem here is that the command separater "&&" on Windows-NT doesn't work on Windows 95. To get around the problem, we had to create a batch file to do the job. This batch file is created just before compiling a package and removed just after it is built.

    Another problem is that the command "rmdir /s" that removes a whole directory is not available on Windows 95. You must use the "deltree /y" command instead. So, you should replace the top of this file by:

    if equal (OS_TYPE, "WIN32")
      SEP   = "&&"  % doesn't work on Windows 95...
      RMDIR = "deltree /y"
      TOUCH = "copy nul >"
    else
      SEP   = ";"
      RMDIR = "rm -rf"
      TOUCH = "cat /dev/null >"
    end
    
    % This is a very special BuildChunk function for Windows 95.  Windows
    % 95 doesn't understand the "&&" by which we can put two commands on
    % the same command line.  What we do instead is to create and run a
    % batch file containnig those commands that we want to be executed.
    % It's not pretty but it works... (Jerome Collin - April 17, 1996)
    
    readonly new_m3build = format ("%s%s%s%s", BIN_USE, SL, "m3build", CR)
    readonly new_m3ship  = format ("%s%s%s%s", BIN_USE, SL, "m3ship", CR)
    
    readonly proc BuildChunk (x) is
      if not stale (x, x)
        % we've already built this chunk
        write ("-- ", x, " done --", CR)
        return
      end
    
      % let'm know what we're doing
      write (CR, "---------------------- building ", x,
                " ----------------------", CR,CR)
    
      > "tmp.bat" in
        local goto_chunk = format ("cd ..%s%s%s", SL, x, CR)
    
        % build and ship the chunk
        write(goto_chunk, new_m3build, new_m3ship)
      
        % If you don't want to delete derived objects as soon as they are
        % installed, comment out the following write.
        write(RMDIR, BUILD_DIR, CR)
      end
    
      % remember that we've built this chunk
      exec ("@", TOUCH, x)
    
      exec("tmp.bat")
      local nothing = unlink_file("tmp.bat")
    end
    

    On systems like Windows/NT where deltree is not available, we recommend the use of "rmdir /s /q" instead.

Of course, you should also select the packages you want to install on your system as usual.

There is maybe another bug or two but it's a good start...

Jerome Collin
April 18, 1996


Here is our own boot-NT386\m3build\templates\NT386 file:

% Copyright (C) 1989, 1992 Digital Equipment Corporation 
% All rights reserved.
% See the file COPYRIGHT for a full description.
%
% Standard configuration file for a 386 box running Windows/NT.
%

%-------------------------------------------------- compilation environment ---

readonly TARGET = "NT386"
readonly DEFAULT_BUILD_DIR = TARGET

include (PLATFORMS)  % get the target-dependent mappings
include (OS_TYPE)    % get the OS-dependent functions

readonly NAMING_CONVENTIONS = "2"
%                                        object files       libraries
%  0=Unix                          =>  .o   .io    .mo       libXX.a
%  1=Unix with a grumpy C compiler =>  .o   _i.o   _m.o      libXX.a
%  2=Windows/NT                    =>  .obj .io    .mo       XX.lib
%

%------------------------------------------------------------- export paths ---
% During the installation, destination directories that do not exists 
% will be created. You need the necessary permissions to do so; otherwise,
% the installation will fail, but can be restarted after you have 
% fixed the permissions.

INSTALL_ROOT = "c:\\modula-3\\"
%-- handy for installations that keep all M3 stuff together

% For Windows (NT and 95), the actual installation still gest done 
% from Unix and thus we use Unix names...
BIN_INSTALL   = INSTALL_ROOT & "bin"                % executables
LIB_INSTALL   = INSTALL_ROOT & "lib"                % libraries
PKG_INSTALL   = INSTALL_ROOT & "pkg"                % packages
DOC_INSTALL   = INSTALL_ROOT & "doc"                % documents
EMACS_INSTALL = INSTALL_ROOT & "elisp"              % emacs lisp code
MAN_INSTALL   = INSTALL_ROOT & "man"                % man pages
HTML_INSTALL  = INSTALL_ROOT & "www"                % public hypertext

% The manual pages normally go in subdirectories man{1,...8} of
% the MAN_INSTALL directory.  If you prefer to have them all in
% a single section, define MAN_SECTION to be that section's name.
% MAN_SECTION = "l"

% On some systems (e.g. AFS) you must install public files in a different
% place from where you use them.  If that is the case for your system,
% specify the "use" location here, otherwise leave them alone.
%
% For Windows (NT and 95) we use the stuff from the mounted unix
% file system.
USE_ROOT = "\\\\unix\\proj\\"

BIN_USE   = BIN_INSTALL       % executables
LIB_USE   = LIB_INSTALL       % libraries
PKG_USE   = PKG_INSTALL       % packages

readonly INSTALL_IMPLS = "TRUE"
% "TRUE"
%    => save all source files during the install
%    => makes debugging easier and browsing more fruitful
% "" (i.e. FALSE)
%    => save only the exported interfaces and templates 
%    => makes the installed system slightly smaller.

readonly NEED_OBJECTS = ""
% "TRUE"
%    => accumulate a list of derived objects in COMPILE_OBJECTS
%    => for building shared libraries in the library_hooks function below
% ""
%    => don't bother

%---------------------------------------------------------------------- X11 ---
% If you have X11R4 installed and would like the X11R4 binding interfaces
% to be built, define the procedure "import_X11R4" to import the libraries
% that are needed.  Otherwise, define "import_X11R4" to be an empty procedure.
%
% If you use the MIT server with DECnet support, you need X11 and dnet,
% otherwise X11 should be enough.
% 
% Since X11R5 is an extension of X11R4, you can use the X11R5 libraries
% instead of X11R4.  However, the Modula-3 binding interfaces have not
% yet been upgraded to X11R5.
%
% "import_X11R4" is called from the X11R4 package.  "import_Motif" is
% called from the motif package.  "import_PEX" is called from the PEX
% package.

proc import_X11R4() is
end

readonly proc import_Motif() is
end

readonly proc import_PEX() is
end

%-------------------------------------------------------------------- emacs ---
% If you have emacs and want to compile ".el" files to ".elc" files,
% fill in the function below.  Otherwise, comment out or delete the
% entire function.  Note, the distributed code assumes gnuemacs version 19
% or later.

readonly proc emacs_compile (el) is
  exec ("emacs -batch -f batch-byte-compile", el)
end

%---------------------------------------------------- C compiler and linker ---
% The following definitions are used to compile and link C modules.
% Note that these definitions can be overridden on the m3build command
% line with "-D".  (e.g.  m3build -DCC=gcc)
%
% These definitions assume you are using MicroSoft Visual C++ 2.0.
%
% _ifdef(a,b,c) == if defined(a) return b else return c
%
% The actual definitions must be kept on one line due to finicky details
% of the bootstrap process.

CC = _ifdef ("CC", CC, [ "c:\\msdev\\bin\\cl", "-D_MT", "-D_DLL", "-D_X86_", "-DWIN32", "-nologo" ])
%--- C compiler with flags for compiling a single ".c" file

LINK = _ifdef ("LINK", LINK, [ "c:\\msdev\\bin\\link", "-debug:mapped,partial", "-debugtype:cv", "-pdb:none", "-align:0x1000", "-ignore:505", "-machine:i386" ])
%--- linker with flags for linking Modula-3
%---  "-pdb:none" enables the use of windbg with the resulting executable.

MAKELIB = _ifdef ("MAKELIB", MAKELIB, [ "c:\\msdev\\bin\\lib", "-debugtype:cv", "-machine:i386" ])
%--- program to build library archives

ASM = _ifdef ("ASM", ASM, [ "c:\\msdev\\bin\\masm386", "/Ml", "/t", "/z" ])
%--- assembler

%------------------------------------------------------------- GNU variants ---
% The two large pieces of GNU software used by the Modula-3 system
% gcc(=m3cc) and gdb(=m3gdb) often require slightly different C compilers
% or flags.  They are specified here.  Note that they may be overridden
% from the m3build command line.
%
% To use the GNU defaults for CC and CFLAGS, specify "*".
%

GNU_CC     = _ifdef ("GNU_CC",     GNU_CC,     CC)
GNU_CFLAGS = _ifdef ("GNU_CFLAGS", GNU_CFLAGS, "")
GNU_MAKE   = _ifdef ("GNU_MAKE",   GNU_MAKE,   "nmake")

%-------------------------------------------------------- Modula-3 compiler ---
% The syntax for the values passed to most of the M3_CONFIG options is
% "@pgm@arg1@...@argn@" where "@" is an arbitrary character.  The
% separator character must begin and end the value.

% Where is the driver?
M3 = LIB_USE & "\\m3.exe"

% What are the standard flags?
M3OPTIONS = [ "-w1", "-why", "-g" ]

M3_CONFIG = [
   "-Y1" & _pack_args (CC),
   "-Y2" & _pack_args (LINK),
   "-Y3" & _pack_args (MAKELIB),

   "-X0@-unfold_nested_procs@",
   % --- the Modula-3 to IL compiler options

   "-z2@msvcrt.lib@kernel32.lib@user32.lib@gdi32.lib@advapi32.lib"
         & "@winspool.lib@comdlg32.lib@netapi32.lib@",
   % --- libraries systematically linked with all programs

   "-z3" & LIB_USE & SL & "report_coverage.obj",
   % --- library linked in programs compiled with "-Z" coverage option

   "-z4" & LIB_USE,

   "-z5" & NAMING_CONVENTIONS,
   % Set the host naming conventions.

   "-z61",
   % Values of "-z6":
   %   "0" => the m3 driver will split library names and pass -L/-l
   %          arguments to the linker
   %   "1" => the m3 driver will pass libraries with full path names
   %   "2" => like "0" except that for shared libraries, the driver
   %          passes -Rdir as well as -Ldir to the linker

   "-zA0",
   % The "-zA" option specifies the maximum size (in megabytes) that Pass0
   % is allowed to reach as a persistent server before the driver kills it.
   % Setting it to zero disables server mode.
   % NOTE: the current compiler is buggy, leave "-zA" alone!

   "-zB@-O2@", % --- pass 1 options implied by "-O"
   "-zC@@",    % --- pass 6 options implied by "-O"
   "-zD@@",    % --- pass 7 options implied by "-O"

   "-zE@-Od@-Zi@",  % --- pass 1 options implied by "-g"
   "-zF@@",         % --- pass 6 options implied by "-g"
   "-zG@@",         % --- pass 7 options implied by "-g"

   "-zH" & NAMING_CONVENTIONS,
   % --- the target's naming conventions

   "-zI" & TARGET,
   % --- the target architecture

   %%  "-zJ11",  -- the C compiler writes its error messages on stdout, sigh.
   "-zJ21",
   "-zJ31",
   % The option "-zJx1" specifies that pass "x" is "noisy", "-zJx0"
   % specifices that it's not.  The default is to assume that passes
   % are not noisy.  The driver collects the standard output of noisy
   % passes in a file and then deletes the file, unless "-keep" or
   % "-verbose" is specified.

   "-zK0",
   % --- Set the value of "-zK" to "1" if you want the m3 driver to
   %     supply -Bdynamic/-Bstatic options to the linker, "0" otherwise.

   "-Bdynamic",
   % --- libraries are shared by default.  If you give -zK1 you should
   %     also provide an initial -Bdynamic or -Bstatic.

   "-zL1"
   % --- Set the value of "-zL" to "1" if you want .M3LINK files produced
   %     for a dynamic loader
]

proc build_standalone() is
   % --- reset the linker to avoid shared libraries.
end

proc build_shared() is
   % --- reset the linker to use shared libraries.
end

% ------------------------------------------------------------------- hooks ---
% These are the "last chance" hooks that are called each time a library
% or program is built.  They might build shared libraries or strip
% executables...

proc before_library_hooks(x) is
end

proc after_library_hooks(x) is
end

proc before_program_hooks(x) is
end

proc after_program_hooks(x) is
end

%---------------------------------------------------------------- bootstrap ---
% These functions are used during the bootstrap process
%

BOOT_OBJS = []
BOOT_LIBS = []

readonly proc boot_import (file) is
  BOOT_LIBS += file
end

readonly proc boot_obj (file) is  BOOT_OBJS += file & ".obj" end
readonly proc boot_io  (file) is  BOOT_OBJS += file & ".io"  end
readonly proc boot_mo  (file) is  BOOT_OBJS += file & ".mo"  end

readonly proc boot_c (file) is
  local c_file = file & ".c"
  local o_file = file & ".obj"
  if stale (o_file, c_file)
    exec (CC, "-Zi", "-c", file & ".c", "> nul:")
  end
  BOOT_OBJS += o_file
end

readonly proc _boot_asm (src, obj) is
  if stale (obj, src)
    exec (ASM, src, ",", obj, ";")
  end
  BOOT_OBJS += obj
end

readonly proc boot_s  (file) is  _boot_asm (file & ".s",  file & ".obj")  end
readonly proc boot_is (file) is  _boot_asm (file & ".is", file & ".io") end
readonly proc boot_ms (file) is  _boot_asm (file & ".ms", file & ".mo") end

readonly proc boot_lib (file) is
  local args = arglist ("@", BOOT_OBJS)
  exec (MAKELIB, "-out:" & file & ".lib", args, "> nul:")
end

readonly proc boot_prog (file) is
  local args = arglist ("@", [BOOT_OBJS, BOOT_LIBS, "msvcrt.lib",
                        "kernel32.lib", "user32.lib", "gdi32.lib",
                        "advapi32.lib", "winspool.lib", "comdlg32.lib",
                        "netapi32.lib" ])
  exec (LINK, "-subsystem:console",
        "-out:" & file & ".exe", "-map:" & file & ".map",  args, "> nul:" )
end

%---------------------------------------------- the rest of the environment ---

include ("COMMON")

%------------------------------------------------------------- installation ---

readonly proc install_file (src, dest, mode) is
  Note_install (src, dest)
  exec ("@copy ", src, dest)	      % Take copy on Windows 95. Jerome Collin
  %  exec("@install -c -m", mode, src, dest)
end

[Modula-3 home page]

m3-request@src.dec.com
Last modified on Thu Aug 22 13:33:03 PDT 1996 by heydon
Copyright (C) 1992, 1996, Digital Equipment Corporation. All rights reserved.
See the COPYRIGHT for a full description.