COMS 3157 Advanced Programming

Recitation 2: Git, Make, and C Preprocessor

2.1 Make and Git

Adapted from Fall 2015, Midterm 1.

Consider the following shell session, answer the inline questions:

$ ls
Makefile  foo.c  foo.h  main.c

$ cat Makefile
CC=gcc

main: main.o foo.o

foo.o: foo.c foo.h

main.o: main.c foo.h

$ git init
(output redacted)

$ git add *

$ git commit -m "Commit 1"

$ make
gcc -c -o main.o main.c
gcc -c -o foo.o foo.c
gcc main.o foo.o -o main

$ echo "// Some comment" >> main.c          # Append some comment to main.c

$ make

(( 2.1.1. What commands are run here? ))

$ touch main.o

$ make

(( 2.1.2. What commands are run here? ))

$ echo "// Some comment" >> foo.h           # Append some comment to foo.h

$ echo "// Another comment" >> main.c       # Append another comment to main.c

$ make

(( 2.1.3. What commands are run here? ))

$ touch grass

$ git add main.c grass

$ git status

(( 2.1.4.1. What files are listed under "Changes to be committed"? ))
(( 2.1.4.2. What files are listed under "Changes not staged for commit"? ))
(( 2.1.4.3. What files are listed under "Untracked files"? ))

$ pwd
/home/j-hui/repo1

$ cd ..

$ git clone repo1 repo2
Cloning into 'repo2'...
done.

$ cd repo2

$ ls

(( 2.1.5. What files are in working directory of repo2? ))

$ make

(( 2.1.6. What commands are run here? ))

$ cd ../repo1

$ git commit -m "Commit 2"

$ cd ../repo2

$ touch main.c

$ git status

(( 2.1.7.1. What files are listed under "Changes to be committed"? ))
(( 2.1.7.2. What files are listed under "Changes not staged for commit"? ))
(( 2.1.7.3. What files are listed under "Untracked files"? ))

$ git log

(( 2.1.8. List all commit messages in the log, starting from most recent. ))

Solutions

Try running everything yourself on CLAC, starting with these commands:

$ mkdir repo1
$ cd repo1
$ cp ~j-hui/cs3157-pub/examples/make-foo/* .

The final cp command copies over Makefile, foo.c, foo.h and main.c to your directory, i.e., repo1.

2.2 Separate compilation

Adapted from Spring 2022, Midterm 1.

Consider the following shell session, which tries to build and run a program:

$ ls
main.c  myadd.c  myadd.h

$ cat myadd.h
int add(int x, int y);

$ cat main.c
#include <stdio.h>
#include "myadd.h"

int main(void) {
    printf("%d\n", add(3000, 157)); // should print 3157
}

$ gcc -c myadd.c        # COMPILE MYADD

$ gcc -c main.c         # COMPILE MAIN

$ gcc myadd.o main.o    # LINK

$ ./a.out               # EXECUTE

We do this for 7 different versions of myadd.c. Your job is to find which of these commands, if any, fail. Write COMPILE MYADD, COMPILE MAIN, LINK, or EXECUTE to indicate the FIRST command that fails, or 3157 if none of them fail and the program successfully prints 3157.

2.2.1

int add(int x, int y) {
  return x + y;
}

2.2.2

#include "myadd.h"

int add(int x, int y) {
    return x + y;
}

2.2.3

#include "main.c"

int add(int x, int y) {
    return x + y;
}

2.2.4

float add(float x, float y) {
    return x + y;
}

2.2.5

#include "myadd.h"

float add(float x, float y) {
    return x + y;
}

2.2.6

#include "myadd.h"

int sub(int x, int y) {
    return x - y;
}

2.2.7

#include "myadd.h"
#define foo add

int foo(int x, int y) {
    return x + y;
}

Solutions

You can check out the solutions on CLAC, by cloning them with:

git clone ~j-hui/cs3157-pub/examples/myadd-3157

In that repo, you will find subdirectories for each part; run make in each directory to automatically compile, link, and execute according to the commands specified in question.