C代写:CS352 Makefile

实现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:

  1. Does my target name exist as a file? If not, I need to run the command
  2. Were any dependencies updated? If so, I need to run the command
  3. 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.