CMSC216 Lab08: Make/Makefiles
- Due: 11:59pm Mon 09-Nov-2026 on Gradescope
- Approximately 1.00% of total grade
CODE DISTRIBUTION: lab08-code.zip
CHANGELOG:
- Wed Nov 4 10:38:10 AM EST 2026
- The original
Makefileprovided for students at the top level had a few bugs in it including referencinglab09instead oflab08. This has been corrected and students can get a fresh copy oflab08-code.zipto get the updates.
1 Rationale
Build systems are essential to program development to automate
repetitive tasks such as compiling code, running tests, and tracking
changes which would necessitate running such tasks. The make build
system is among the oldest build system and is ubiquitous across Unix
systems making it a useful to know a few basics about it.
Associated Reading
Students only need to master the basics of make and its Makefile
format which are discussed in this document. Those wanting a more
complete account should consult the GNU Make Manual as it is the most
widely deployed implementation of make and its manual is thorough.
Grading Policy
Credit for this lab is earned by completing the code/answers in the
Lab codepack and submitting a Zip of the work to Gradescope preferably
via running make submit. Students are responsible to check that the
results produced locally are reflected on Gradescope after submitting
their completed Zip.
Lab Exercises are Free Collaboration and students are encouraged to cooperate on labs. Students may submit work as groups of up to 5 to Gradescope: one person submits then adds the names of their group members to the submission.
No late submissions are accepted for Lab work but the lowest two lab scores for the semester will be dropped including zeros due to missing submissions. See the full policies in the course syllabus.
2 Codepack
The codepack for this exercise is linked at the top of this document. Always download it and unzip/unpack it. It should contain the following files which are briefly described.
| File | Use | Description |
|---|---|---|
makeproblem-demo-little |
Study | Problem 1 Example Makefiles to study |
makeproblem-demo-big |
Study | Problem 1 Example Makefiles to study |
makeproblem-create/Makefile |
EDIT | Problem 1 Template Makefile to complete for problem |
test_makefile.org |
Testing | Problem 1 CODE tests, used in make test-prob2 |
QUESTIONS.txt |
EDIT | Questions to answer: fill in the multiple choice selections in this file. |
QUESTIONS.txt.bk |
Backup | Backup copy of the original file to help revert if needed |
Makefile |
Build | Enables make test and make zip |
testy |
Testing | Test running scripts |
test_lab08.org |
Testing | Tests for this exercise |
gradescope-submit |
Provided | Allows submission from the command line |
3 Problem 1: Background on Makefiles
Building programs often involves compiling separate source files and
eventually combining them through linking to create an executable.
There are often associated tasks such as running automated tests,
creating distribution files, and generating documentation that may be
supported by the build system as well. Among the oldest build systems
still in use is make and its associated Makefiles. This problem
covers the basics of how to create a Makefile.
3.1 Structure of Makefiles
The basic structure of a Makefile involves rules which relate
targets, dependencies, and commands. Simple Makefiles comprise a
list of rules.
# comment above Rule 1
target1 : dependency1A depency1B
command1A
command1B
command1C
# comment above Rule 2
target2 : dependency2A
command2A
command2B
# comment above Rule 3
target3 : dependency3A dependency3B dependency3B
command3A
command3B
When invoked, make target3 will load the contents of the Makefile
and examine the relationship between target3 and its
dependencies. If make determines it is necessary, it may run
command3A, command3B in sequence to "update" target3. In other
cases, make may determine that there is no need to run additional
commands as target3 is already up to date. Similarly, running make
target1 will possibly run command1A, command1B, command1C.
NOTE: Commands associated with a rule MUST BE INDENTED WITH A TAB. This is a notoriously bad "feature" of make which can occasionally cause problems. Be aware: leading whitespace for commands should be TAB characters.
The most common kind of target is a file that should be created such
as a .o file or an executable program. The directory
makeproblem-demo-little has an example Makefile showing this:
1: # Simple Makefile to build program main_prog
2:
3: # first rule in the file is the default: typing `make` is the same as
4: # typing `make main_prog`
5:
6: # rule 1
7: main_prog : main_func.o func_01.o
8: gcc -o main_prog main_func.o func_01.o
9:
10: # rule 2
11: main_func.o : main_func.c
12: gcc -c main_func.c
13:
14: # rule 3
15: func_01.o : func_01.c
16: gcc -c func_01.c
17:
18: # rule 4
19: clean :
20: rm -f *.o
21: rm -f main_prog
The rules that appear are
main_progdepends on themain_func.oandfunc_01.o; the program is created by invoking GCC on these filesmain_func.odepends onmain_func.cwhich is created by running GCCfunc_01.odepends onfunc_01.cand is created by running GCCcleanis a "phony" target with no dependencies which will remove compile artifacts by using thermcommand
When one types make or make main_prog in that directory, the
following will appear:
>> cd makeproblem-demo-little/
>> make
gcc -c main_func.c
gcc -c func_01.c
gcc -o main_prog main_func.o func_01.o
Observe that make detects that the two dependencies for Rule 1 are
incomplete: main_func.o and func_01.o are not present. To create
them, it will generate them as targets according to for the rules that
have them as targets, Rule 2 and Rule 3. After running the commands
for these two rules, the commands for Rule 1 are executed to generate
the program.
3.2 Variables and Shortcuts in Makefiles
Makefiles support a large number of features such as explicit
variables, automatic variables, pattern-based rules, and many
others. A few of these are described in the sample file
makeproblem-demo-little/Makefile-shortcuts. It accomplishes the same
task as the Makefile but utilizes some features which are useful to
know about. The comments in this file describe some of these features.
1: # Simple Makefile to build program main_prog
2:
3: # first rule in the file is the default: typing `make` is the same as
4: # typing `make main_prog`
5:
6: # rule 1
7: main_prog : main_func.o func_01.o
8: gcc -o main_prog main_func.o func_01.o
9:
10: # rule 2
11: main_func.o : main_func.c
12: gcc -c main_func.c
13:
14: # rule 3
15: func_01.o : func_01.c
16: gcc -c func_01.c
17:
18: # rule 4
19: clean :
20: rm -f *.o
21: rm -f main_prog
By default, typing make will search for a file named Makefile but
the following invocation allows using a specific file other than that:
>> make -f Makefile-shortcuts
3.3 Dependency Detection
Makefiles are useful for larger projects to automatically detect
dependencies which must be updated. The example in
makeproblem-demo-big/ shows a "larger" project with more files. Observe
the following:
>> make # COMPILE 1
gcc -c main_func.c
gcc -c func_01.c
gcc -c func_02.c
gcc -c func_03.c
gcc -c func_04.c
gcc -c func_05.c
gcc -c func_06.c
gcc -c func_07.c
gcc -c func_08.c
gcc -c func_09.c
gcc -c func_10.c
gcc -c func_11.c
gcc -c func_12.c
gcc -c func_13.c
gcc -c func_14.c
gcc -c func_15.c
gcc -c func_16.c
gcc -c func_17.c
gcc -c func_18.c
gcc -c func_19.c
gcc -c func_20.c
gcc -o main_prog main_func.o func_01.o func_02.o func_03.o func_04.o func_05.o func_06.o func_07.o func_08.o func_09.o func_10.o func_11.o func_12.o func_13.o func_14.o func_15.o func_16.o func_17.o func_18.o func_19.o func_20.o
>> make # COMPILE 2
make: Nothing to be done for 'all'.
>> rm func_12.o # delete a .o
>> touch func_05.c # make func_05.c look like it has been edited
>> make # COMPILE 3
gcc -c func_05.c # only out of sync or
gcc -c func_12.c # missing targets are regenerated
gcc -o main_prog main_func.o func_01.o func_02.o func_03.o func_04.o func_05.o func_06.o func_07.o func_08.o func_09.o func_10.o func_11.o func_12.o func_13.o func_14.o func_15.o func_16.o func_17.o func_18.o func_19.o func_20.o
The lesson above is in COMPILE 3: make detects that most of the .o
files are in sync with their source files. Only the missing / out of
sync targets have their rules applied to regenerated them and update
the exectuable program.
4 QUESTIONS.txt File Contents
Below are the contents of the QUESTIONS.txt file for the exercise.
Follow the instructions in it to complete the QUIZ and CODE questions
for the exercise.
_________________
LAB08 QUESTIONS
_________________
Exercise Instructions
=====================
Follow the instructions below to experiment with topics related to
this exercise.
- For sections marked QUIZ, fill in an (X) for the appropriate
response in this file. Use the command `make test-quiz' to see if
all of your answers are correct.
- For sections marked CODE, complete the code indicated. Use the
command `make test-code' to check if your code is complete.
- DO NOT CHANGE any parts of this file except the QUIZ sections as it
may interfere with the tests otherwise.
- If your `QUESTIONS.txt' file seems corrupted, restore it by copying
over the `QUESTIONS.txt.bk' backup file.
- When you complete the exercises, check your answers with `make test'
and if all is well. Create a zip file and submit it to Gradescope
with `make submit'. Ensure that the Autograder there reflects your
local results.
- IF YOU WORK IN A GROUP only one member needs to submit and then add
the names of their group on Gradescope.
PROBLEM 1 QUIZ: Questions on Makefiles
======================================
Review the presentation of `Makefile' basics in the lab description
and analyze the examples provided in the demo directories
`makeproblem-demo-little' and `makeproblem-demo-big'. Then answer the
following questions.
Command Execution
~~~~~~~~~~~~~~~~~
Which of the following best describes when the commands for a rule are
run?
- ( ) The commands for all targets in the Makefile are all run every
time make is used
- ( ) Only the commands associated with the target named on the
command line are run; e.g. `make targ5` will run commands associated
with targ5
- ( ) Commands for a given rule execute only if make detects a its
target is needed and then only if the target is missing or older
than its dependencies
Rule Syntax
~~~~~~~~~~~
Which of the following Rules correctly lays out the syntax for target,
dependencies, and commands in a Makefile.
,----
| # RULE A
| target : dependency1 dependency2
| command1
| command2
| command3
|
| # RULE B
| target : dependency1 dependency2
| command1
| command2
| command3
|
| # RULE C
| dependency1 dependency2 : target
| command1
| command2
| command3
|
| # RULE D
| target :
| command1
| command2
| command3
| : dependency1 dependency2
`----
- ( ) RULE A
- ( ) RULE B
- ( ) RULE C
- ( ) RULE D
Variance in Makefiles
~~~~~~~~~~~~~~~~~~~~~
Check ALL that are true about Makefile features
- ( ) Rules may have 0 dependencies
- ( ) Rules may have 0 commands
- ( ) Rules have no more than 1 command
- ( ) Rules have no more than 1 dependency
- ( ) Makefiles can set up explicit variables for use in rules
- ( ) Makefiles provide a variety of automatic variables for use in
rules
- ( ) A Makefile can have deeply nested decencies: targA depends on
targB depends on targC depends on targD etc.
Problem 1 CODE: makeproblem-create
==================================
Complete the template in the subdirectory
`makeproblem-create/Makefile' according to the comments there. The
essential idea is to build the linked list program from an earlier lab
and add a few other targets. Once you add rules for certain targets,
you can test them interactively via commands like `make' and `make
clean' in that directory. You can also run the automated tests of this
via a problem test:
,----
| >> cd lab08-code
| >> make test-prob1 # run tests for Makefile under makeproblem-create
| ...
`----
Follow the instructions at the end of Lab01 if you need a refresher on how to upload your completed exercise zip to Gradescope.