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