CSCI 4061: HW01 Compiling C Programs, Makefiles
- Due: 11:59pm Mon 2/01/2021 on Gradescope
- Approximately 0.83% of total grade
CODE DISTRIBUTION: hw01-code.zip
- Download the code distribution every HW
- See further setup instructions below
CHANGELOG: Empty
1 Rationale
Accessing a computer's capabilities via the command line is an essential tool in a computer scientist's toolkit. When logging into a remote system, non-graphical tools are the faster and often only option to interact. These exercises will gain you basic familiarity with editing short shell scripts on a Unix system to automate basic tasks. It will also review how to edit basic C programs, compile them, and run them.
Completing this HW will familiarize students with the following.
- cd, ls, rm
- gcc to compile C programs
- make and Makefiles
1.1 Associated Reading
Basic knowledge of C programming and the Unix command line is assumed already. If this is your first time working with such things, follow the instructions closely and ask a LOT of questions. This HW is meant to be self-describing so it is likely you won't need too much extra reading but use your best judgment.
Unix Environment
Most coursework will be done in a Unix environment. It's a good idea to find an efficient way to access such environments to support your workflow. The following tutorial offers some options such as remote access and local installations to suite several situations.
Command Line Work
Our textbooks deal with shell commands only tangentially so are not a great source for this set of exercises. Information on shell programming is distributed throughout the texts associated with various topics so they are not good for a beginning text
Instead, try Ryan's Tutorials: Linux Tutorial for a reasonably concentrated introduction of command line tricks and shell programming.
C Programming
If this is your first time working with C, find a tutorial online to work through. If you are coming form another programming language, you may want to search for a tailored tutorial such as
c programming for java programmers
Makefiles
This HW will teach you the basics of make and Makefiles on its own but it is a deep and powerful to solve a certain class of problems. The manual for GNU make is an extensive source of information on it. You may wish to peruse it for additional details.
1.2 Grading Policy
Credit for this HW is earned by taking the associate Quiz which is
linked under Gradescope
. The quiz will ask similar questions as
those that are present in the QUESTIONS.txt
file and those that
complete all answers in QUESTIONS.txt
should have no trouble with
the quiz.
See the full policy in the syllabus.
2 Download Code and Setup
Most HWs come with some code that you need to use, which is linked at the top of the HW specification in a ZIP file (compressed archive). After downloading the HW code, unzip it and get to work. The files in this HW's zip are
hw01-code |-- collatz Directory with code for Problem 1 | |-- collatz_funcs.c | |-- collatz.h | |-- collatz_main.c | |-- test_collatz.c | |-- test_collatz.org | |-- testy | |-- Makefile | `-- Makefile-commented |-- mat-product Directory with code for Problem 2 | |-- free_matrix.c | |-- mat.h | |-- op_main.c | |-- outer_product.c | |-- test_outer_product.org | |-- testy | `-- Makefile CREATE this file `-- QUESTIONS.txt Fill with answers, paste into Gradescope
Here is an example terminal session illustrating the use of the
unzip
utility to unpack the provided zip.
# Print the working directory >> pwd /home/kauffman # Most terminals/shells start in your home directory # I downloaded hw01-code.zip to the Downloads folder so I'll change # there. You may need to change to a different directory >> cd Downloads # There is the zip along with a few other things >> ls entr-3.8.tar.gz eradman-entr-592856d50559 hw01-code.zip # The unzip command will upack the contents of hw01-code.zip into a # usable folder >> unzip hw01-code.zip Archive: hw01-code.zip creating: hw01-code/ creating: hw01-code/collatz/ inflating: hw01-code/collatz/Makefile inflating: hw01-code/collatz/Makefile-commented inflating: hw01-code/collatz/collatz_main.c inflating: hw01-code/collatz/collatz_test.c inflating: hw01-code/collatz/coll inflating: hw01-code/collatz/collatz.h inflating: hw01-code/collatz/collatz.c inflating: hw01-code/QUESTIONS.txt creating: hw01-code/mat-product/ inflating: hw01-code/mat-product/op_main.c inflating: hw01-code/mat-product/test_outer_product.c inflating: hw01-code/mat-product/mat.h inflating: hw01-code/mat-product/free_matrix.c inflating: hw01-code/mat-product/outer_product.c # The folder hw01-code was created, change there >> ls entr-3.8.tar.gz eradman-entr-592856d50559 hw01-code hw01-code.zip >> cd hw01-code >> pwd /home/kauffman/Downloads/hw01-code # These are files and directories relevant to hw01 >> ls collatz mat-product QUESTIONS.txt
3 What to Understand
Ensure that you understand
- The basic structure of a
Makefile
, the notion of target, dependency, and commands. - The idea that a
Makefile
can detect changes and only rebuild targets that depend on changed files. - Common conventions such as
make clean
andmake test
4 Questions
The file QUESTIONS.txt
contains a series of questions about basic
Unix shell navigation and C compilation. You should open
QUESTIONS.txt
in your favorite text editor and fill in answers to
each Problem and part. Specific instructions for each problem are in
subsequent sections.
________________ HW01 QUESTIONS ________________ - Name: (FILL THIS in) - NetID: (THE kauf0095 IN kauf0095@umn.edu) Write your answers to the questions below directly in this text file. HW quiz questions will be related to the questions in this file. PROBLEM 1: Compile and Run via make =================================== Unzip the provided zip file and change into the `hw01-code/collatz' directory. (A) Compiling and Running a C Program ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The directory `collatz' contains a small C program that computes sequences of numbers according to the following convention: ,---- | For an input number N | - If N is even, set N to N / 2 | - If N is odd, set N to 3*N + 1 `---- A variety of folks have conjectured that this sequence always reaches 1 (see <https://en.wikipedia.org/wiki/Collatz_conjecture>) but and the code provide in the `collatz' directory terminates when this happens. We will simply be using the code here to refresh on compiling and running code. Issue the following compilation command to compile the program then run it starting the sequence at 17. Show your results. ,---- | > gcc -o coll collatz_funcs.c collatz_main.c `---- (B) Use of Makefiles ~~~~~~~~~~~~~~~~~~~~ Compiling more than a few C files together is tedious if one must do so with individual `gcc' invocations. Instead, compiling and linking the files in a larger project is the purvey of a build system. On Unix, `make' is the classic tool used to automate the build process. Instructions on what needs compiling and how to do so are written into a file, traditionally called a `Makefile'. `make' itself is a program which will read through the `Makefile' and execute the commands contained within. Several features are present in `make': - Users specify what needs to be done but `make' will figure out the order to do them in to avoid redundancy. - `make' will only recompiled programs if the source code has changed. If no changes have been made, it may report `Nothing to do' or `So-and-so is already up to date'. - `make' has many shortcuts built into it for common C compilation tasks so that files can be short. However, it can be used to automate many other types of task such as posting HTML pages associated with HWs. Below is a sample `Makefile' that is present in the `collatz' directory. It can be used to build the collatz program and has extensive comments to explain some of what is happening in the file. Study this carefully and ask questions of the lab staff if needed. ,---- | # Makefile to create the collatz programs. To use, type | # > make | # Which will create the collatz_main program. Alternatively | # > make collatz_main | # will also create the collatz_main program. | # | # To create and run the test program use | # > make test | # | # Makefiles are divided into "rules" comprised of target, | # dependencies, and commands to execute to finish the target. | # | # target : dependency1 dependency2 | # command1 | # command2 | # @command3 which is not printed | # command4 | # | # Some targets are files to create like the "collatz_main" program or | # "collatz_main.o" file. Other targets are "virtual" which specify | # commands to run such as 'clean'. Some targets like 'test' are a | # combination of creating files and running commands: 'make test' will | # ensure several programs are created before running the automated | # tests. | | CFLAGS = -Wall -g # variable holding options to the c compiler | CC = gcc $(CFLAGS) # variable holding the compilation command | | collatz_main : collatz_funcs.o collatz_main.o collatz.h # collatz_main is a program, depends on two files, is default target | $(CC) -o collatz_main collatz_funcs.o collatz_main.o # when the other files are ready, compile collatz_main | @echo collatz_main is ready # issue a report that the program is ready | | collatz_main.o : collatz_main.c collatz.h # collatz_main.o depends on two source files | $(CC) -c collatz_main.c # compile only, don't link yet | | collatz_funcs.o : collatz_funcs.c collatz.h # collatz.o depends on collatz.c and collatz.h | $(CC) -c $< # compile, use shortcut $< which becomes "collatz.c" | | test_collatz : test_collatz.c collatz_funcs.o collatz.h # builds a test program for collatz functions | $(CC) -o $@ $^ | | test : test_collatz collatz_main # runs automated tests, builds required programs first | @chmod u+x testy # ensures that the 'testy' script is executable | ./testy test_collatz.org $(testnum) # runs automated tests | | clean: # No dependencies: clean is the de facto cleanup target | @echo Cleaning up object files # Report what's happening | rm -f *.o collatz_main # Remove all the .o files and programs | | clean-tests: # target to remove temporary files associated with testing | @echo Removing temporary test files | rm -f *.o test_collatz test-results `---- Type the command `make' and paste the results of this command below. Run the program that results from this compilation and show it below. (C) Makefile Targets ~~~~~~~~~~~~~~~~~~~~ The default target in a Makefile is the first one to appear but other targets can also be reference explicitly. Two common targets we will make use of are - `make clean' : remove all compiled files (and programs) - `make test' : run some automated tests associated with the project Run these two commands and explain how they relate to the commands that appear in the `Makefile'. Note that many assignments in this class will feature some sort of testing target which will run automated tests of the correctness of a program. (D) Testing Code ~~~~~~~~~~~~~~~~ Throughout the course we will utilize a small testing framework called 'testy' which is provided with the HW code. This script is what actually runs tests and reports results when one types `make test' as evidenced by the output of make: ,---- | > make test # build and run tests | gcc -Wall -g -c collatz_funcs.c # compiling code | ... | ./testy test_collatz.org # run the 'testy' script on the tests in 'test_collatz.org' | ============================================================ | == testy test_collatz.org : collatz_func.c and collatz_main.c tests | ... `---- By default results, testy reports testing failures and puts verbose output in files that are noted while it runs. for example Test 1 fails and the results for the failure are showing the file indicated: ,---- | > make test | ... | 1) collatz_next(1) : FAIL -> results in file 'test-results/collatz-01-result.tmp' | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `---- These results can be examined in any text editor. One quick way to examine them in a terminal is with the `less' text viewer. Try typing ,---- | > less test-results/collatz-01-result.tmp `---- Useful keybindings in `less' are ------------------------------------------------ Key Effect in less ------------------------------------------------ q quit less and return to the terminal spacebar scroll down a page u scroll up a page j scroll down one line k scroll up one line ------------------------------------------------ There are a few tricks associated with 'testy' that are worth knowing. To run individual tests for debugging purposes one can set the `testnum' environment variable. ,---- | > make test testnum=5 | ... | > make test testnum=12 | ... `---- If several tests are to be run, quote the test numbers as in the following. By default, only summary output is shown on the screen. If the `SHOW' environment variable is set, then any failures are printed immediately. ,---- | > make test testnum='3 5 12' | ... | > make test testnum='3 5 12' SHOW=1 | ... `---- In space below, paste the results of running the above `make' commands in a terminal. (E) Compile based on Changes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Build systems are useful because they usually detect changes to files in a project and then recompile only those files that are dependent on the changes. This saves time on large projects with many files as not everything needs to be recompiled. One can simulate a editing a file with the `touch' command which changes the 'timestamp' a file to look like it has been modified recently though its contents will not actually change. Issue the following sequence of commands and explain why each `make' compiles a different set of files. ,---- | > make clean | | > make | | > make # intentional repeat | | > touch collatz_funcs.c # simulate edit of collatz_funcs.c | | > make | | > rm collatz_main | | > make | | > touch collatz_main.c # simulate edit of collatz_main.c | | > make | | > make # intentional repeat `---- PROBLEM 2: Create a `Makefile' ============================== Change into the `mat-product' directory. This directory contains several C files. ---------------------------------------------------------------------------------- File Notes ---------------------------------------------------------------------------------- mat.h header file listing project functions outer_product.c function that creates an outer product matrix free_matrix.c function that frees memory associated with a heap matric op_main.c main function which uses two C files above testy test running script test_outer_product.org automated tests for outer_product.c ---------------------------------------------------------------------------------- For this problem, create a `Makefile' that will build the project executables and run tests. The following make targets should be available. - `make': build the `op_main' executable which is dependent on functions in `op_main.c, outer_product.c, free_matrix.c' - `make test': builds the `op_main' program AND runs the automated tests. - `make clean': removes all `.o' files and all programs associated with the project. Ensure that Object files are built from each C file to enable efficient separate compilation and linking as is the case in the `collatz/Makefile'. A demonstration of the Makefile behavior is below. ,---- | > make | gcc -Wall -g -c op_main.c | gcc -Wall -g -c outer_product.c | gcc -Wall -g -c free_matrix.c | gcc -Wall -g -o op_main op_main.o outer_product.o free_matrix.o | | > ./op_main 3 1.1 2.2 3.3 2 1.1 2.2 | 1.21 2.42 | 2.42 4.84 | 3.63 7.26 | | > make clean | rm -f *.o op_main | | > ./op_main 3 1.1 2.2 3.3 2 1.1 2.2 | bash: ./op_main: No such file or directory | | > make test | gcc -Wall -g -c op_main.c | gcc -Wall -g -c outer_product.c | gcc -Wall -g -c free_matrix.c | gcc -Wall -g -o op_main op_main.o outer_product.o free_matrix.o | ./testy test_outer_product.org | ============================================================ | == testy test_outer_product.org : Tests for outer_product.c and op_main.c | == Running 5 / 5 tests | 1) Singleton vectors : ok | 2) Small vectors 1 : ok | 3) Small vectors 2 : ok | 4) Size 1 for x, for y : ok | 5) Medium vectors : ok | ============================================================ | RESULTS: 5 / 5 tests passed | | > make test | ./testy test_outer_product.org | ============================================================ | == testy test_outer_product.org : Tests for outer_product.c and op_main.c | == Running 5 / 5 tests | 1) Singleton vectors : ok | 2) Small vectors 1 : ok | 3) Small vectors 2 : ok | 4) Size 1 for x, for y : ok | 5) Medium vectors : ok | ============================================================ | RESULTS: 5 / 5 tests passed | | > touch free_matrix.c | > make | gcc -g -c free_matrix.c | gcc -g -o op_main op_main.o outer_product.o free_matrix.o | | > ./op_main 3 1.1 2.2 3.3 2 1.1 2.2 | 1.21 2.42 | 2.42 4.84 | 3.63 7.26 | | > rm op_main | | > make test | gcc -Wall -g -o op_main op_main.o outer_product.o free_matrix.o | ./testy test_outer_product.org | ============================================================ | == testy test_outer_product.org : Tests for outer_product.c and op_main.c | == Running 5 / 5 tests | 1) Singleton vectors : ok | 2) Small vectors 1 : ok | 3) Small vectors 2 : ok | 4) Size 1 for x, for y : ok | 5) Medium vectors : ok | ============================================================ | RESULTS: 5 / 5 tests passed `---- Use the `Makefile' provided in the `collatz' directory as a model and paste your resulting `Makefile' below. (Note: there is no C testing file for this project but the tests depend on the `op_main' program as shown in the last few demo lines). Understanding the Code ====================== The focus of this HW is to acquaint you with the utility of Makefiles in efficiently compiling projects, rebuilding based on source changes, and running provided tests. You should gather some of common conventions associated with it such as `make clean'. While it is not essential that you spend significant time understanding all the code in `collatz' and `mat-product', it is fairly elementary C and students wishing to refresh their knowledge of the language and techniques may want to spend some time examining how this code works. Labs may review some of the code in these projects.