Quick links for this challenge
Quick links to reference sections
These tend not to vary much from challenge to challenge.
- Getting Started - downloading, unzipping, etc.
- Code Structure -
src
,include
, etc. - Compiling The Code
- Testing The Code
- Autograder
- General Information and Project Policies
- Academic Honesty
- Gradescope
- Submission
Overview
The purpose of this challenge is help you become more familiar with writing makefiles. You only task is to write the Makefile. That’s it.
Learning Objectives
- Writing your own
Makefile
- Defining
make
variables - Using one or more
make
functions - Using
make
for tasks beyond compiling / software construction
How big is this challenge?
You need to fill in a Makefile
. Our solution required about 15 non-blank
lines of text. The tricky part is using make
variables, functions, and
a couple of kinds of rules, in some ways you’ve not seen before.
Getting Started
To get started, follow these steps:
- Download the starter code.
- Unzip the
project-make-makefile.zip
with the following commandunzip -d PROJECT project-make-makefile.zip
. This will create a new directory calledPROJECT
. You can replacePROJECT
with a directory name of your choice. cd
into thePROJECT
directory and investigate the project.
If you follow the above steps correctly, you should have the following folder structure after unzipping (assuming the project name is “PROJECT”):
PROJECT/
include/
input/
lib/
obj/
src/
test/
Makefile
After you have the code extracted you should go ahead and
investigate. You can run make
from the command line and your
project will build and produce a potential error results. See more
information below.
Code Structure
This exercise contains the following important folders:
- include: This is where we keep C header files. Header files are used in C to share definitions across many C source files. That said, for this project, this directory will not be used.
- input: This is where any input files that you need to work with will be stored.
All input files will have a
.in
extension. - lib: This is where we keep any libraries that we might use. It will often be empty.
- obj: This folder is used for object files that are generated from the C compilation process. This folder is initially empty until you compile your code. You may actually make use of this folder in this project.
- output: This is where any output files generated will be stored.
All output files need to have a
.out
extension. This folder will need to be created by your Makefile (mkdir output
). - src: This is the source folder where all source code resides.
For this project, you won’t be changing anything in this folder.
- copysome.c: This is the sole source file for the program that you will need to compile.
- test: This is the test folder where you can find all of the
public unit tests - if any are given.
- test.cpp: This file contains all the public google tests.
Technically, this file is written in C++, but you can edit it as though it were C,
since the content of this class is fundamental enough to largely be in the intersection
of C and C++.
This exists for your use, use it as you wish for more formal/automated testing.
That said, it probably won’t be much use for this project,
and you would need to compile it yourself or add a rule to the Makefile.
Since it stands alone, the command
gcc test/test.cpp -o make_makefile_test -lstdc++ -lgtest -lgtest_main -lpthread
should do the trick (probably even contains more flags than necessary).
- test.cpp: This file contains all the public google tests.
Technically, this file is written in C++, but you can edit it as though it were C,
since the content of this class is fundamental enough to largely be in the intersection
of C and C++.
This exists for your use, use it as you wish for more formal/automated testing.
That said, it probably won’t be much use for this project,
and you would need to compile it yourself or add a rule to the Makefile.
Since it stands alone, the command
- Makefile - this is a “build” file. This file is used to compile your code. This time, THIS is where all your work goes. And this is what you submit to the auto-grader.
Testing The Makefile
The natural way to casually test the Makefile is to just run make
and see if it compiles copysome.c
and generates the executable copysome
.
You can also check the output
directory
and see if all the files are generated with the correct number of lines copied.
You will similarly want to test make -e NUMLINES=20
or something
(that’ll make more sense after reading the instructions).
TODO
Requirements
So the only thing you need to do is write the Makefile, but this makefile
needs to do a number of things by default (make
) or if given the target
all
(make all
). Here are the things, which should each be their own
target, connected as necessary using pre-requisites.
1. Compile src/copysome.c
into an executable copysome
, if necessary.
Pretty self explanatory, you have a sole source file src/copysome.c
,
and need to use it to produce an executable named copysome
(at the PROJECT directory level).
You should one rule to build obj/copysome.o
from src/copysome.c
,
and another rule to build copysome
from obj/copysome.o
. This is
just good practice to get used to, though it’s not absolutely necessary
in this small project.
2. Create the output
directory, if necessary.
Note that the output
directory does not exists by default. The Linux
command mkdir -p
will be useful for this Make target.
3. Run copysome
on all input files
copysome
takes arguments in the form ./copysome [-n num_lines] [in_file] [out_file]
The Makefile should have a variable NUMLINES
that is set to 10.
(One can override the value of this variable with -e NUMLINES=[num_lines]
,
e.g, -e NUMLINES=20
.)
And so for each file input/[file_name].in
, an associated file named
output/[file_name].out
should be produced that contains the first
NUMLINES
lines of [file_name].in
. Note that the rule here should
be a pattern rule (see the slides!). Also, this rule needs both
copysome
and output
as additional pre-requisites (why?).
4. You should also provide a clean
target.
This target should delete the output
folder and everything in it,
as well as your .o
file(s).
Tips/Specific Points
TABS! For the love of all that is good, beware the fact that Makefiles need tabs (not spaces). We highly recommend you try and make whitespace characters visible in the editor of your choice.
Also, beware that a Makefile must be named exactly Makefile
with no extension. Some
systems “helpfully” add a .txt
if you don’t watch out for it.
The Makefile
should be placed in the top directory of the project (not in src
).
We want to emphasise the simplicity and power of the makefile rule structure. The basic rules are of the form:
[rule_name/output]: [dependencies]
[commands]
(Notice that tab before [commands]
!)
This is generally seen in the form of compiling files, such as:
challenge_test: test/test.cpp
gcc test/test.cpp -o challenge_test -lstdc++ -lgtest -lgtest_main -lpthread
(Where you could have the all
rule claim challenge_test
as a dependency,
or invoke make challenge_test
directly.)
But commands in Makefiles are not restricted to compilation commands. An example is a clean
rule:
clean:
rm -f output/*.out
rm -f copysome obj/copysome.o
(So make clean
will not recursively consider any dependencies,
but will invoke the rm
commands.)
In this challenge you will also find use for pattern rules, which have the form:
output_pattern: input_pattern
commands
where output_pattern
and input_pattern
have a %
in them. For example, to
build a .xyz
file from a .abc
file:
%.xyx: %.abc
commands
You will also find use for at least one static pattern rule, which restricts a pattern rule to apply to specific outputs:
outputs: output_pattern: input_pattern
commands
Your Makefile should not assume any specific .in
files exist. Rather, it should process
every .in
file in the input
directory. The wildcard
make function will be helpful for
discovering the input files, and the patsubst
function can help create the names of the
correspinding output files. Our presention described how to describe a dependency for each file in a set
of files determined by previous variable settings in the Makefile (static pattern rule),
which will also be helpful. Other commands that may be useful include mkdir -p
for
guaranteeing the existence of a directory, rm -f
for deleting a file that may or may not
exist in a clean
rule, and likewise rm -rf
for deleting a directory that may or may not exist
and everything in it.
Good Makefile style suggests that each rule should take care of only one kind of action,
but may have dependencies than can ultimately cause other things to happen. Consider,
for example, what is needed in order to run copysome
- it needs to exist, and its
output directory also needs to exist. That suggests possible dependencies in your rule
to run copysome
, etc.
A final reminder. A Makefile is not procedural, i.e., not something that
executes top to bottom. Rules can appear in any order, with the one exception
that the first rule is the default rule (most commonly with the target
all
, meaning “make everything”).
In sum, you don’t need a lot of lines of Makefile “code”, but (as in any programming) they need to be the right lines!
Autograder
The autograder is used to test your code more deeply. If you follow the specifications of this exercise exactly then you should be able to pass all of the tests that you are provided and all of the tests the autograder is using to check your solution.
To run the autograder on your solution you must upload your
Makefile
to Gradescope.
General Information and Project Policies
- Read this entire document. If, after a careful reading, something seems ambiguous or unclear to you, then communicate to the course staff immediately. Start this assignment as soon as possible. Do not wait until the night before the assignment is due to tell us you don’t understand something, as our ability to help you will be minimal.
- For some assignments, it will be useful for you to write additional
C files. Any C file you write that is used by your solution
MUST be in the provided
src
directory. - The course staff are here to help you figure out errors, but not solve them for you. When you submit your solution, be sure to remove all compilation errors from your project. Any compilation errors in your project will cause the autograder to fail, and you will receive a zero for your submission. No Exceptions!
- Reminder:
Academic Honesty
All work that is completed in this assignment is your own. You may talk to other students about the problems you are to solve, however, you may not share code in any way. What you submit *must be your own work.
You may not use any code that is posted on the internet. If you are not sure it is in your best interest to contact the course staff. We will be using software that will compare your code to other students in the course as well as online resources. It is very easy for us to detect similar submissions and will result in a failure for the exercise or possibly a failure for the course. Please, do not do this. It is important to be academically honest and submit your work only. Please review the UMass Academic Honesty Policy and Procedures so you are aware of what this means.
Copying partial or whole solutions, obtained from other students or elsewhere, is academic dishonesty. Do not share your code with your classmates, and do not use your classmates’ code. If you are confused about what constitutes academic dishonesty you should re-read the course policies. We assume you have read the course policies in detail and by submitting this project you have provided your virtual signature in agreement with these policies.
Gradescope
We use Gradescope to run our autograding software and record your grade for these assignments. You may submit this assignment as many times as possible up to the due date. If you encounter a problem with the autograder you should contact the course staff immediately.
Submission
You must submit your Makefile
.
To do this you will need to download the Makefile
from the EdLab environment
to your local machine then upload Makefile
to Gradescope. Gradescope
will run your submission in our autograder environment and give you a
report of what tests passed and which did not. You are welcome to
submit as many times as you would like.
A word of caution: some means of downloading the Makefile
will add a .txt
extension
(why they do this, or why they think that would be a civilised thing to do is beyond me).
The file you submit to Gradescope must be named Makefile
, not Makefile.txt
.
I recommend making extensions visible on your machine to make sure you notice anything off.