实现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 files 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 -ldrwxr-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 testMaketarget: depen1 depen2echo targetdepen1: file.cecho depen1depen2: depen1echo depen2
I can run the following
% ./mymake testMakeExecuting: echo depen1depen1Executing: echo depen2depen2Executing: echo targettarget
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, lets try specifying a target on the command line:
% ./mymake testMake depen2Executing: echo depen1depen1Executing: echo depen2depen2
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 wont 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 dont 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: target2echo 1target2: target3echo 2target3: target1echo 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, cant 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
.