[comp.sources.misc] v03i023: mmake - Make for multiple environments

eric@cs1.wsu.edu (Eric Schneider) (05/19/88)

comp.sources.misc: Volume 3, Issue 23
Submitted-By: "Eric Schneider" <eric@cs1.wsu.edu>
Archive-Name: mmake

I recently got 'emake' from the archives and upone examining it, noted that
there wasn't a chance in heck of getting it to work under MS-DOS(r).  So, I
spent a few hours coming up with the following program which is quite simple
and runs on Unix, and MS-DOS systems.  For any large program which is in the
process of becoming larger, such as adding and deleting source files, header
files, and the like, and also being cross-developed on UNIX and MS-DOS at the
same time - a tool like this is essential.  If I've re-invented the wheel,
don't hesitate to tell me and point me in some nice direction.  I'm not sure
that my way of doing thing is the best, but the program is quite simple and
does do what I need.


			Eric (eric@cs1.wsu.edu.CSNET)

# :>- :>- :>- CUT HERE :>- :>- :>-
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	README
#	mmake.c
# This archive created: Wed May 18 15:19:46 1988
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'README'
then
    echo shar: "will not over-write existing file 'README'"
else
cat << \SHAR_EOF > 'README'
Wed May 18 14:32:38 PDT 1988

Mmake - Support for Makefiles on multiple operating systems and environments.

usage:
	Create a file called "MMakefile", or "mmakefil" on MS-DOS.  This file
	can contain C preprocessor directives such as "#ifdef MSDOS" in order
	to control the make process.  The mmake program is invoked by simply
	typing "mmake <args>".  The arguments to mmake are passed to the C
	preprocessor, or the make program as appropriate.

description:
	This program grew out of the need to support simultaneous development
	on the Un*x operating system and MS-D*S.  Because of the nature of the
	C compilers on each system, it was necessary to maintain two seperate
	Makefiles.  This program allows a single makefile to exist which then
	will expand differently depending on the OS in which it is run.  For
	example the following MMakefile might be used to compile with debug
	enabled.

		/* Makefile w/ Debug */

		#if MSDOS
		DEBUG=-Zi -Od
		PROG=main.exe
		#else
		DEBUG=-g
		PROG=main
		#endif

		CFLAGS= $(DEBUG)

		$(PROG): main.o
			$(CC) -o $(PROG) $(DEBUG) prog.o

	In the msdos environment, the program main.exe will be compiled to
	include symbol table information for the CodeView(r) debugger, and
	in the Unix environment, the standard system debug information will
	be present.


	To build mmake, just compile the mmake.c file and name the output
	mmake, or mmake.exe if in MS-DOS.  No makefile is provided since
	this is a case where a MMakefile would be nice and you can't mmake
	mmake if mmake doesn't exist!

	This program was developed on an HP 9000/840 running HP-UX 1.2.  It
	has also been tested on an IBM AT compatible running PC-DOS 3.3, and
	the MicroSoft C 5.0 compiler.  The make program used on the PC was
	NdMake 4.3.  In addition this program will compile and run under the
	BSD 4.2 or 4.3 operating system.

	If there are any questions, or you have any bugs to report or
	enhancements to suggest, don't hesitate to contact me.


			Eric Schneider, System Manager
			Computer Science Department
			Washington State University
			Pullman, WA  99164-1210

			eric@cs1.wsu.edu (CSNET)
SHAR_EOF
fi
if test -f 'mmake.c'
then
    echo shar: "will not over-write existing file 'mmake.c'"
else
cat << \SHAR_EOF > 'mmake.c'
/*****************************************************************************
 *                                                                           *
 * mmake - Program to support make on multiple systems.  This program takes  *
 *         the file MMakefile and runs the C preprocessor on it.  The result *
 *         is written to Makefile, and then "make" is invoked.  Note that    *
 *         the C preprocessor is only invoked if the file MMakefile is newer *
 *         then Makefile.                                                    *
 *                                                                           *
 *         This program is designed to allow the same makefile to be used on *
 *         unix(r) systems and MS-DOS(r) systems.  In order to make this     *
 *         program portable across systems, it is not very smart about the   *
 *         way it does certain things.  For example, in order to run the     *
 *         C preprocessor, we use a system() call, rather than something     *
 *         line popen() which is not available on MS-DOS.                    *
 *                                                                           *
 *         The file names were chosen so that once mmake has run and created *
 *         Makefile, you can run "make" rather than "mmake" unless MMakefile *
 *         changes.                                                          *
 *                                                                           *
 *         Mmake has no arguments, but certain command line arguments are    *
 *         send to either CPP or make as appropriate.  Any argument which    *
 *         begines with "-D", "-I", or "-U" is sent to CPP.  Any other flags *
 *         are passed unchanged to make.                                     *
 *                                                                           *
 *         The output from the C preprocessor is written to a temporary file *
 *         because this output contains blank lines which will cause make to *
 *         detect a syntax error.  The temporary file is read back in and    *
 *         the blank lines are removed with the result goint to Makefile.    *
 *                                                                           *
 *****************************************************************************/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>

extern int errno;
int temp_flag;
char *temp_name;

main(argc, argv)
int argc;
char **argv;
{
    time_t mmtime, mtime;
    struct stat sb;
    int newer = 0;			/* DOS requires initialization */
    char cpp_command[1024];
    char make_command[1024];
    char *temp_file;
    char line[1024];
    FILE *fpin, *fpout;
    int cleanup();

    temp_flag = 0;			/* Indicates that temp file exists */
    signal(SIGINT,cleanup);

    if (stat("MMakefile", &sb) < 0) {
	perror("MMakefile");
	exit(1);
    } else
	mmtime = sb.st_mtime;

    if (stat("Makefile", &sb) < 0) {
	if (errno == ENOENT)
	    mtime = 0;
	else {
	    perror("Makefile");
	    exit(1);
	}
    } else
	mtime = sb.st_mtime;

    strcpy(cpp_command,"cc -E MMakefile ");
    strcpy(make_command, "make ");

    if (mmtime > mtime) {		/* do we have to run CPP? */
	newer = 1;
	temp_file = mktemp("MMXXXXXX");
    }

    /* Now scan the argument flags and put each in the appropriate
       command line */
    argc--;
    argv++;
    while(*argv) {
	if ((strncmp(*argv,"-D",2) == 0) ||
	    (strncmp(*argv,"-U",2) == 0) ||
	    (strncmp(*argv,"-I",2) == 0)) {
	    strcat(cpp_command, *argv);
	    strcat(cpp_command, " ");
	} else {
	    strcat(make_command, *argv);
	    strcat(make_command, " ");
	}
	argc--;
	argv++;
    }
    strcat(cpp_command, ">");
    if (newer) {
	temp_flag = 1;			/* Say temp file exists */
	temp_name = temp_file;		/* temp file name is temp_name */
	strcat(cpp_command, temp_file);
    } else
	strcat(cpp_command, "Makefile");

    if (newer) {
	if (system(cpp_command) != 0) {
	    fprintf(stderr, "CPP Failed!\n");
	    cleanup();
	}
	if ((fpin = fopen(temp_file, "r")) == NULL) {
	    perror(temp_file);
	    unlink(temp_file);
	    exit(1);
	}
	if ((fpout = fopen("Makefile", "w")) == NULL) {
	    perror("Makefile");
	    cleanup();
	}
	while (fgets(line, sizeof line, fpin)) {
	    if (*line != '\n')
		fputs(line, fpout);
	}
	if (!feof(fpin)) {
	    perror("Makefile");
	    cleanup();
	}
	fclose(fpin);
	fclose(fpout);
	unlink(temp_file);
	temp_flag = 0;			/* Temp file no longer exists */
    }

    return (system(make_command));
}

cleanup()
{
    if (temp_flag)
	unlink(temp_name);
    fprintf(stderr, "Mmake aborted.  %s\n", temp_flag ?
	    "temporary file removed." : "");

    exit(1);
}
SHAR_EOF
fi
exit 0
#	End of shell archive