[SOLVED] CPSC2310-Lab 2: Make files

35.99 $

Category:

Description

5/5 - (1 vote)

Lab Objective

  • Learn how to use the Make utility to automate your builds and scripts
  • Learn some basic shell scripting

Introduction

In the past, as you’ve worked on labs and or assignments invariably you’ve typed a compile command incorrectly or misspelled a filename. As your projects grow, you want to move away from manually typing in the gcc/g++ compile commands and begin using automated build tools.

For Linux-like environments, Make is a very common build tool which allows you to compile and link C/C++ programs in a more structured way. Today, we’ll begin with simple Makefiles and build to a general-purpose script which will be applicable to many future C/C++ projects.

For those of you that had me for 1020 or have already had this lab, please read the entire lab because it is not exactly like the previous lab.

For this lab you will be required to create a document consisting of screenshots documenting your work. Your screenshots MUST include the terminal you are using along with your username. I will do my best to mark the places in the lab that require screenshots.  However, this is not guaranteed so be sure to read and follow all directions.

Resources

For a step-by-step tutorial on Makefiles and some information on bash scripting checkout the following links:

https://www.tutorialspoint.com/makefile/

https://www.tutorialspoint.com/unix/unix-what-is-shell.htm

Assignment

Create a folder called Lab2. This is the folder you will use for this part of the lab.  Inside Lab2 create another folder called src and move your functions.c and functions.h in this folder.

SCREENSHOT:

Create a document called Task.doc. Throughout this lab you will be instructed to take screenshots; adding them to Task.doc.

What you should have now is:

A folder called Lab2 – In this folder you should have another folder called src

/Lab2/src

Lab2 should have your driver.c, and a folder src which should have funtions.c, functions.h and task.doc

Because of the above actions you are going to need to change your driver.c file. Figure out what that change is and make it.

In your task.doc file describe what the change was and why you needed it.

As projects get larger and include more source files, it often makes sense to logically separate them into subdirectories to make them easier to manage. Even if you don’t split them up, compiling multiple source files into an executable becomes more involved and error prone process. Especially when multiple files have compiler errors.

This is where the make command is very useful. make allows us to define a script called the makefile which contains instructions on compiling our programs. In the root directory (Lab2) of the code listed above, create a file named makefile by doing the command below:

touch makefile

Touch is a Linux/Unix command that is used to create an empty file with no content.

SCREENSHOT

Make a screenshot of this and copy/paste it in task.doc.

Note that the file MUST be named Makefile or makefile for the make command to identify it.

Makefile Targets and Dependencies

Makefiles are a form of bash script, which is like a programming language for controlling your Linux terminal. It allows us to compile source files and run additional programs like echo, grep, or tar. Consider the following:

MESSAGE=HELLO WORLD!

 

all: build

@echo “All Done”

build:

@echo “${MESSAGE}”

The first thing to notice is that we defined a bash variable at the top of the script. Bash variables are simply string substitutions. Using the $() or ${} operator, we can replace the variable with the defined string. Use ${} with curly braces if you are in between double quotes. This is a pretty straightforward concept, but it’s very powerful. In this instance, we use a variable to define a message we print to the screen.

****************************************************************************

HUGELY IMPORTANT NOTE:

Any code that belongs to a given target must be indented at least one tab character. There is a tab before both of the @echo commands above.

****************************************************************************

 

SCREENSHOT:

Using the file you created using touch, type the above code in the makefile. Create a screenshot and paste it in your document

Now we move on to our first target, the default target all:

A target is simply a named chunk of code our Makefile will try and execute. By default, Make will execute the all: target if it exists. Otherwise, it executes the first target it finds. You can also specify a target from the command line, which means that the following commands are equivalent:

make

make all

 

Next to the target name there is a whitespace separated list of dependencies. When make encounters a target to execute, it will read the dependency list and perform the following actions:

  1. If the dependency is another target, attempt to execute that target
  2. If the dependency is a file that matches a rule, execute that rule

 

This means we can chain multiple targets together.

Run the make command from the terminal and see what is printed to the screen:

make

HELLO WORLD!

All Done!

Notice that the “HELLO WORLD!” is printed first… that’s because the all: target is dependent on the build: target and so it is run first.

Now run the following

make build

SCREENSHOT:

Take a screenshot showing that you ran the make command and make build. Paste the screenshot in your task.doc.

Add a target called tar: that will tar zip everything in the folder, your tar file should be test.tar.gz.

Now add a target called list: that will list all files in the folder. In other words, if I type make list it should list all files in the folder. If I type make tar it will tar all files in the folder creating a file named test.tar.gz. Test your make tar and make list.

SCREENSHOT:

Create a screen shot and copy/paste it in your document.

Now, change the all target to have dependencies of build, tar, and list.

SCREENSHOT:

Test it, create a screenshot, and place it in your document.

For those wondering, echo is a command that just prints its arguments to the terminal. Including the @ symbol in front of the command prevents make from printing the command. Play around with the above file to get a feel for what we are doing. See what happens if you remove the @ symbol.

Making C Programs

The power of the makefile is in this dependency list/rule execution loop. What we want is for our build target to run our gcc compile command. This target should be dependent on our C source files. A powerful feature of make dependencies is that a target will only be executed if its dependencies have changed since the last time you called make. Again:

A target will only be executed if its dependencies have changed since the last time you called make!

Let’s just skip to an example!

Change the name of the previous makefile you created. Use touch and create another makefile. Type the following code in the makefile filling in the C_SRCS and HDRS information.

# Config, just variables

CC=gcc

CFLAGS=-Wall -g

LFLAGS=-lm

TARGET=out

 

# Generate source and object lists, also just string variables

C_SRCS := FILLIN THE C FILES HERE

HDRS := FILL IN THE HEADER FILES

OBJS := driver.o src/functions.o

 

# default target

all: build

@echo “All Done!”

 

# Link all built objects

build: $(OBJS)

$(CC) $(OBJS) -o $(TARGET) $(LFLAGS)

 

# special build rule

%.o: %.c $(HDRS)