UNIX> make -f /home/jplank/cs360/labs/Lab-4-Fakemake/lab-makefileYou may use Libfdr for this assignment.
Your job is to write the program fakemake. Like make, fakemake's job is to help you automate compiling. Unlike make, fakemake limits itself to making one executable, and assumes that you are using gcc to do your compilation.
The syntax of fakemake is as follows:
fakemake [ description-file ]If no description-file is specified, then it assumes that the description file is the file fmakefile. Obviously, if the description file doesn't exist, then the program should exit with an error.
Each line of the description file may be one of six things:
C list-of-filesAll files thus specified should end with .c. Multiple files can be separated by whitespace. The list may be empty, and there can be multiple lines starting with C.
H list-of-filesThe H list is formatted just like the C list, and there can be multiple lines starting with H.
E nameThere can be only one executable name; thus, there can be only one line starting with E. It is an error if there is no E line in the entire description file.
F flagsThese flags will be included right after gcc whenever it is called. As before, the flags are separated by whitespace, and there can be multiple F lines. This can be empty as well.
L list-of-librariesAs before, multiple files should be separated by whitespace. The list may be empty, and there can be multiple lines starting with L. This list is included at the end of the final gcc command that makes the executable.
What fakemake does is compile all the .c files into .o files (using gcc -c), and then compile all the .o files into the final executable. Like make, it doesn't recompile a file if it is not necessary. It uses the following algorithm to decide whether or not to compile the .c files:
Obviously, if a .c or .h file is specified, and it does not exist, fakemake should exit with an error. If there are any compilation errors mid-stream, fakemake should exit immediately. The order of files should be the order specified (this is for compilation and for constructing the final executable).
UNIX> cp ~jplank/cs360/labs/Lab-4-Fakemake/* . UNIX> ls f.c f.h f2.c makefile mysort.fm f.fm f1.c lab.html mysort.c UNIX> make gcc -c -g f.c gcc -c -g f1.c gcc -c -g f2.c gcc -g -o f f.o f1.o f2.o gcc -c -g -I/home/jplank/cs360/include mysort.c gcc -g -o mysort mysort.o /home/jplank/cs360/objs/libfdr.a UNIX> f This is the procedure F1 -- in f1.c This is the procedure F2 -- in f2.c UNIX> mysort < f.c f1(); f2(); main() { } UNIX> make clean rm -f core *.o f mysort UNIX> ls f.c f.h f2.c makefile mysort.fm f.fm f1.c lab.html mysort.c UNIX>So, this directory contains source code for two programs. The first, f, is made up of three C files: f.c, f1.c and f2.c, and one header file: f.h. The second is mysort.c from the Rbtree-1 lecture. The makefile contains a specification of how to make these programs using make. The file f.fm is the fakemake file for making f, and mysort.fm is the fakemake file for making mysort. Try it out, using the fakemake executable in /home/jplank/cs360/labs/Lab-4-Fakemake/fakemake:
UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake fakemake: fmakefile No such file or directory UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm gcc -c -g f.c gcc -c -g f1.c gcc -c -g f2.c gcc -o f -g f.o f1.o f2.o UNIX> touch f.c UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm gcc -c -g f.c gcc -o f -g f.o f1.o f2.o UNIX> rm f UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm gcc -o f -g f.o f1.o f2.o UNIX> touch f.h UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm gcc -c -g f.c gcc -c -g f1.c gcc -c -g f2.c gcc -o f -g f.o f1.o f2.o UNIX> touch f.h UNIX> touch f.o f1.o UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm gcc -c -g f2.c gcc -o f -g f.o f1.o f2.o UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm f up to date UNIX> f This is the procedure F1 -- in f1.c This is the procedure F2 -- in f2.c UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake mysort.fm gcc -c -g -I/home/jplank/cs360/include mysort.c gcc -o mysort -g -I/home/jplank/cs360/include mysort.o /home/jplank/cs360/objs/libfdr.a UNIX> mysort < f.c f1(); f2(); main() { } UNIX> rm f.h UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/fakemake f.fm fmakefile: f.h: No such file or directory UNIX>As you can see, fm works according to the above specification. It only recompiles modules when it needs to. When you're in doubt about what your fakemake should do, see what /home/jplank/cs360/labs/Lab-4-Fakemake/fakemake does and emulate its behavior.
If your program isn't working like mine, modify your-script.sh to perform a "ls -l --full-time" listing right before the fakemake call. Here's an example. First, I run the gradescript on example number 3. It runs correctly, but I still want to see what your-script.sh does:
UNIX> ~jplank/cs360/labs/Lab-4-Fakemake/gradescript 3 Problem 003 is correct. Test: sh -c 'sh your-script.sh > tmp-003-test-stdout.txt 2> tmp-003-test-stderr.txt' Correct output generated with : sh -c 'sh correct-script.sh > tmp-003-correct-stdout.txt 2> tmp-003-correct-stderr.txt' UNIX> cat your-script.sh ge=/home/jplank/cs360/labs/Lab-4-Fakemake/Gradescript-Examples cp $ge/onefile.c . gcc -c onefile.c sleep 1 touch onefile.c rm -f onefile cp $ge/001.fm fmakefile if ./fakemake; then ./onefile fi UNIX> sh your-script.sh gcc -c onefile.c gcc -o onefile onefile.o With a taste of your lips I'm on a ride You're toxic I'm slipping under With a taste of poison paradise UNIX>If you can read the script -- it copies /home/jplank/cs360/labs/Lab-4-Fakemake/Gradescript-Examples/onefile.c to the current directory, compiles it to onefile.o, then sleeps for a second and makes sure that there is no file onefile in the current directory. It then copies the fake-makefile 001.fm from /home/jplank/cs360/labs/Lab-4-Fakemake/Gradescript-Examples and runs fakemake. Since onefile.c should be one second newer than onefile.o, fakemake should recompile onefile.c to onefile.o, and then compile onefile.o to onefile. It should exit correctly, and then the script runs onefile, which, like all the example programs, prints some random lines from Toxic by Britney Spears (a surprisingly good song, if you ask me) in a random order.
Below, I modify your-script so that it does "ls -l --full_time" on the onefile programs:
UNIX> vi your-script.sh UNIX> cat your-script.sh ge=/home/jplank/cs360/labs/Lab-4-Fakemake/Gradescript-Examples cp $ge/onefile.c . gcc -c onefile.c sleep 1 touch onefile.c rm -f onefile cp $ge/001.fm fmakefile ls -l --full-time onefile* # this is the new line if ./fakemake; then ./onefile fi UNIX> sh your-script.sh -rw-r--r-- 1 jplank loci 246 2011-02-09 11:05:36.000000000 -0500 onefile.c -rw-r--r-- 1 jplank loci 1880 2011-02-09 11:05:35.000000000 -0500 onefile.o gcc -c onefile.c gcc -o onefile onefile.o With a taste of your lips I'm on a ride You're toxic I'm slipping under With a taste of poison paradise UNIX>You can see from the long listing that onefile.o is older than oldfile.c by one second.
The test files from 6 through 25 test two-file compilations, and the remainder test header files, libraries, etc.
To execute a string, you use the system() procedure. It executes the given string as if that string is a shell command (sh, not csh, although it shouldn't matter). If it returns -1, then it couldn't execute the command. Otherwise, it returns that exit() value of the command. You should assume that if a program exits with a non-zero value, then there was an error, and you should stop compiling (i.e. your fakemake should exit).