实现Makefile命令工具,能解析Makefile文件,并且完成编译依赖。
Introduction
Flex your makefile muscles!
Note: All programs on this assignment must be valgrind clean, meaning when run
through valgrind with --leak-check=full
, no errors are detected
whatsoever.
For each problem, you will turn in one file. That file’s name will be the same
as the problem title.
Problem 1. Makefile.p1
For this problem you will write a makefile. Recall this problem from the
midterm:
“Write a bash script named mvqt that will be given a file with a name
following the format NETID-question.txt. It will create and move our file into
a directory called NETID. When given an argument such as “alan-questions.txt”
it creates a directory named alan, and moves alan-questions.txt into
alan/questions.txt. Example: “
% ls -l
-rw-r–r– 1 dpdicken staff 1103 Oct 9 19:47 alan-questions.txt
-rw-r–r– 1 dpdicken staff 1968 Oct 9 19:48 tim-questions.txt
% mvqt alan-questions.txt
% ls -l
drwxr-xr-x 3 dpdicken staff 102 Oct 9 19:48 alan
-rw-r–r– 1 dpdicken staff 1968 Oct 9 19:48 tim-questions.txt
% ls -l alan
-rw-r–r– 1 dpdicken staff 1103 Oct 9 19:47 questions.txt
You will be implementing a Makefile that performs this same operation, but
does so on every file of the given form in the current directory. So, I should
be able to type “make”, and the aforementioned operation should be performed.
Note, file names such as “smith-jones-questions.txt” where to be ignored on
the midterm, that is not the case for this problem, they should be handled as
well.
Turn in your makefile as a file called Makefile.p1.
Problem 2. mymake.c
In this problem, you will be implementing the make utility. It will be a
somewhat watered down version of the actual utility, but it will have the same
core functionality. I will execute my program in the following way:
./mymake makefilename [target]
The first argument will be the name of the makefile we are evaluating. The
second (optional) argument will be the name of the target to evaluate. If this
target is not given, you should evaluate the first target in the file.
Here is an example makefile we could parse
% cat testMake
target: depen1 depen2
echo target
depen1: file.c
echo depen1
depen2: depen1
echo depen2
I can run the following
% ./mymake testMake
Executing: echo depen1
depen1
Executing: echo depen2
depen2
Executing: echo target
target
First, notice how I did not specify a target on the command line so it went
for the first one in the file. Next, notice how it prints out “Executing:
%s\n” every time it executes a command. It runs all three commands associated
with each of the targets. Now, let’s try specifying a target on the command
line:
% ./mymake testMake depen2
Executing: echo depen1
depen1
Executing: echo depen2
depen2
Notice, we started at the target depen2 and worked from there.
Think about how our make file is working, we have targets that have
dependencies. Each dependency either refers to another target or a file on our
computer. The following data structure could be one way to represent it:
We could then use a depth first traversal of this graph to work our way
through our makefile data and check what commands need to be run.
Your job is to parse the database file, build the data structure, traverse it,
and run the necessary commands based on the same rules the make utility uses.
Those rules are:
- Does my target name exist as a file? If not, I need to run the command
- Were any dependencies updated? If so, I need to run the command
- Are any dependency files newer than my target file? If so, run the command
The following won’t need to be implemented: no macros, no .PHONY, no pattern
matching, no automatic variables.
A few points:
- There will always be a line with a command following a target line.
- There will only ever be one command line associated with a target.
- Make sure you don’t execute commands multiple times, maybe keep track of what nodes you have visited.
NOTE THE FOLLOWING
You will be turning in multiple source code files for this program. You should
have at least three source code files (two .c and one .h) and a Makefile to
compile your program. I should be able to type “make” in your submission
directory and have your program compile to an executable called “mymake”. You
should also have a clean target in your makefile, which removes any .o files
and your mymake executable. If you fail to provide a makefile (called
Makefile) that successfully compiles your program, you will receive a 0 on
this problem.
Additionally, there will be extra credit on this problem. Consider the
following makefile:
target1: target2
echo 1
target2: target3
echo 2
target3: target1
echo 3
This has what we call a circular dependency. If you make your program detect
these, you could earn an extra 5 points on this problem (Thats 50%!!!). If you
implement this, the detection should stop the program before running any
commands and print “Circular dependency detected\n” and exit.
Let me know on piazza privately if you implement it.
Problem 3. ec.txt
This is an optional problem for extra credit.
I will be offering five percent extra credit on this assignment. The way you
can earn this is by creating what a past professor of mine deemed “an original
thought.” In his words: Cite an interesting course-related observation (or
observations) that you made while working on the assignment. The observation
should have a good amount of depth to it. If this observation makes me say
“Wow! Thats cool/interesting/noteworthy” I will award you the points.
Sorry, can’t run your answers by me before hand :)
Miscellaneous
Output from your program must match exactly as described/shown in the spec! We
will be using the diff command to compare your output to the output of our
solution, so they must be identical to get credit.
Your code must compile and run on lectura. Make sure your c programs compile
and run without warning or error using gcc -Werror -Wall -g -std=c11
.