0%

Makefile in Nachos

Structure

In code directory, there are Makefile.common and Makefile.dep, and in code’s sub directory, there are usually Makefile and Makefile.local.

Makefile

In Makefile, it simply includes:

include Makefile.local
include ../Makefile.common

Makefile.local

In Makefile.local, there are SFILES, CCFILES, INCPATH and DEFINES.

  • CCFILES : CC files generating Nachos in the current directory.
  • INCPATH : The directory of header files.
  • DEFINES : Macro Define, use += because it’s a string.

Makefile.dep

Makefile.dep defines the environment using Nachos. I’m using Linux, so just look at below:

# 386, 386BSD Unix, or NetBSD Unix (available via anon ftp from agate.berkeley.edu)
ifeq ($(uname),Linux)
HOST_LINUX=-linux
HOST = -DHOST_i386 -DHOST_LINUX
CPP=/lib/cpp
CPPFLAGS = $(INCDIR) -D HOST_i386 -D HOST_LINUX
arch = unknown-i386-linux
ifdef MAKEFILE_TEST
GCCDIR = /usr/local/mips/bin/decstation-ultrix-
LDFLAGS = -T script -N
ASFLAGS = -mips2
endif
endif

GCCDIR is the directory of gcc MIPS compiler.

And in the last few lines:

arch_dir = arch/$(arch)
obj_dir = $(arch_dir)/objects
bin_dir = $(arch_dir)/bin
depends_dir = $(arch_dir)/depends

Taking threads directory for example, there is a directory called arch, within which there are dec-alpha-osf , dec-mips-ultrix , sun-sparc-sunos , unknown-i386-linux . I’m using Linux, so just look at unknown-i386-linux . The bin stores the executable file (nachos), the depends stores dependence files (like xxxx.d), and the objects stores object files (like xxxx.o).

In threads directory, when make, there will be a link file named nachos linked to arch/unknown-i386-linux/bin/nachos .

Makefile.common

The most complex file. First it includes Makefile.dep, then vpath tells gnu make where to look for certain files.

vpath %.cc  ../network:../filesys:../vm:../userprog:../threads:../machine
vpath %.h ../network:../filesys:../vm:../userprog:../threads:../machine
vpath %.s ../network:../filesys:../vm:../userprog:../threads:../machine

It means if some files are not found in the current directory when compiling, it will look into these directories.

s_ofiles = $(SFILES:%.s=$(obj_dir)/%.o)
c_ofiles = $(CFILES:%.c=$(obj_dir)/%.o)
cc_ofiles = $(CCFILES:%.cc=$(obj_dir)/%.o)

The three tells where .o files generated by .s, .cc and .c are.

And below is how the executable files are generated:

$(program): $(ofiles)
$(bin_dir)/% :
@echo ">>> Linking" $@ "<<<"
$(LD) $^ $(LDFLAGS) -o $@
ln -sf $@ $(notdir $@)

$(obj_dir)/%.o: %.cc
@echo ">>> Compiling" $< "<<<"
$(CC) $(CFLAGS) -c -o $@ $<

$(obj_dir)/%.o: %.c
@echo ">>> Compiling" $< "<<<"
$(CC) $(CFLAGS) -c -o $@ $<

$(obj_dir)/%.o: %.s
@echo ">>> Assembling" $< "<<<"
$(CPP) $(CPPFLAGS) $< > $(obj_dir)/tmp.s
$(AS) -o $@ $(obj_dir)/tmp.s
rm $(obj_dir)/tmp.s

Below is the dependence files,

s_dfiles = $(SFILES:%.s=$(depends_dir)/%.d)
c_dfiles = $(CFILES:%.c=$(depends_dir)/%.d)
cc_dfiles = $(CCFILES:%.cc=$(depends_dir)/%.d)

dfiles = $(cc_dfiles) $(c_dfiles) $(s_dfiles)

$(depends_dir)/%.d: %.cc
@echo ">>> Building dependency file for " $< "<<<"
@$(SHELL) -ec '$(CC) -MM $(CFLAGS) $< \
| sed '\''s@$*.o[ ]*:@$(depends_dir)/$(notdir $@) $(obj_dir)/&@g'\'' > $@'

$(depends_dir)/%.d: %.c
@echo ">>> Building dependency file for" $< "<<<"
@$(SHELL) -ec '$(CC) -MM $(CFLAGS) $< \
| sed '\''s@$*.o[ ]*:@$(depends_dir)/$(notdir $@) $(obj_dir)/&@g'\'' > $@'

$(depends_dir)/%.d: %.s
@echo ">>> Building dependency file for" $< "<<<"
@$(SHELL) -ec '$(CPP) -MM $(CPPFLAGS) $< \
| sed '\''s@$*.o[ ]*:@$(depends_dir)/$(notdir $@) $(obj_dir)/&@g'\'' > $@'

lab2

Preparation

If you want to modify some files, you’d better do it in other directory with the files associated with Makefile and Makefile.local copied, then it will compile the file you modified dependently first.

So copy Makefile , Makefile.local scheduler.cc , scheduler.h and arch in threads to lab2, and in arch just keep the unknown-i386-linux and within make the three folders empty.

Method 1

Change Makefile.local to make sure the changed or to be changed .h files will found when compiling:

INCPATH += -I../lab2 -I../threads -I../machine

Because I put lab2 in front of threads, so it will go to lab2 first then to the threads directory.

Then make. It compiles successfully:

>>> Linking arch/unknown-i386-linux/bin/nachos <<<
g++ -m32 arch/unknown-i386-linux/objects/main.o arch/unknown-i386-linux/objects/list.o arch/unknown-i386-linux/objects/scheduler.o arch/unknown-i386-linux/objects/synch.o arch/unknown-i386-linux/objects/synchlist.o arch/unknown-i386-linux/objects/system.o arch/unknown-i386-linux/objects/thread.o arch/unknown-i386-linux/objects/utility.o arch/unknown-i386-linux/objects/threadtest.o arch/unknown-i386-linux/objects/synchtest.o arch/unknown-i386-linux/objects/interrupt.o arch/unknown-i386-linux/objects/sysdep.o arch/unknown-i386-linux/objects/stats.o arch/unknown-i386-linux/objects/timer.o arch/unknown-i386-linux/objects/switch-linux.o -o arch/unknown-i386-linux/bin/nachos
ln -sf arch/unknown-i386-linux/bin/nachos nachos

Use touch to change the modification time of file scheduler.h (It won’t change the contents), then make :

../Makefile.dep:29: Linux
>>> Building dependency file for scheduler.cc <<<
../Makefile.dep:29: Linux
>>> Compiling scheduler.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/scheduler.o scheduler.cc

Only scheduler.cc is recompiled, while others not associated with scheduler.h are not recompiled.

If touch scheduler.h in threads?

root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# touch ../threads/scheduler.h
root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# make
../Makefile.dep:29: Linux
>>> Building dependency file for ../machine/timer.cc <<<
>>> Building dependency file for ../machine/sysdep.cc <<<
>>> Building dependency file for ../machine/interrupt.cc <<<
>>> Building dependency file for ../threads/synchtest.cc <<<
>>> Building dependency file for ../threads/threadtest.cc <<<
>>> Building dependency file for ../threads/thread.cc <<<
>>> Building dependency file for ../threads/system.cc <<<
>>> Building dependency file for ../threads/synch.cc <<<
>>> Building dependency file for scheduler.cc <<<
>>> Building dependency file for ../threads/main.cc <<<
../Makefile.dep:29: Linux
>>> Compiling ../threads/main.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/main.o ../threads/main.cc

We see that all source files associated with scheduler.h in directory machine and threads are all recompiled.

If a file doesn’t include scheduler.h , but it includes a file that includes scheduler.h , it will be recompiled too. So we can use grep to find them, and copy them to lab2.

In threads directory, type grep scheduler.h * , and get:

grep: arch: Is a directory
Binary file nachos matches
scheduler.cc:#include "scheduler.h"
scheduler.h:// scheduler.h
system.h:#include "scheduler.h"

We see system.h includes scheduler.h , so we look into system.h by grep system.h * :

grep: arch: Is a directory
main.cc:#include "system.h"
Binary file nachos matches
scheduler.cc:#include "system.h"
synch.cc:#include "system.h"
synchtest.cc:#include "system.h"
system.cc:#include "system.h"
system.h:// system.h
thread.cc:#include "system.h"
threadtest.cc:#include "system.h"

So we only need to copy: system.h , main.cc , synch.cc , synchtest.cc , system.cc , thread.cc and threadtest.cc .

Now lab2 has:

arch      Makefile.local  scheduler.h   system.cc  threadtest.cc
main.cc nachos synch.cc system.h
Makefile scheduler.cc synchtest.cc thread.cc

Firstly, we update the time of scheduler.h , then make :

root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# touch scheduler.h
root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# make
../Makefile.dep:29: Linux
>>> Building dependency file for synchtest.cc <<<
>>> Building dependency file for threadtest.cc <<<
>>> Building dependency file for thread.cc <<<
>>> Building dependency file for system.cc <<<
>>> Building dependency file for synch.cc <<<
>>> Building dependency file for scheduler.cc <<<
>>> Building dependency file for main.cc <<<
../Makefile.dep:29: Linux
>>> Compiling main.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/main.o main.cc
..........................................
>>> Compiling scheduler.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/scheduler.o scheduler.cc
..........................................
>>> Compiling synch.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/synch.o synch.cc
..........................................
>>> Compiling system.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/system.o system.cc
....
>>> Compiling thread.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/thread.o thread.cc
..........................................
>>> Compiling threadtest.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/threadtest.o threadtest.cc
..........................................
>>> Compiling synchtest.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/synchtest.o synchtest.cc
..........................................
>>> Linking arch/unknown-i386-linux/bin/nachos <<<
g++ -m32 arch/unknown-i386-linux/objects/main.o arch/unknown-i386-linux/objects/list.o arch/unknown-i386-linux/objects/scheduler.o arch/unknown-i386-linux/objects/synch.o arch/unknown-i386-linux/objects/synchlist.o arch/unknown-i386-linux/objects/system.o arch/unknown-i386-linux/objects/thread.o arch/unknown-i386-linux/objects/utility.o arch/unknown-i386-linux/objects/threadtest.o arch/unknown-i386-linux/objects/synchtest.o arch/unknown-i386-linux/objects/interrupt.o arch/unknown-i386-linux/objects/sysdep.o arch/unknown-i386-linux/objects/stats.o arch/unknown-i386-linux/objects/timer.o arch/unknown-i386-linux/objects/switch-linux.o -o arch/unknown-i386-linux/bin/nachos
ln -sf arch/unknown-i386-linux/bin/nachos nachos

Then touch scheduler.h in threads directory, then make to see if anything changes:

root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# touch ../threads/scheduler.h
root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# make
../Makefile.dep:29: Linux
>>> Building dependency file for ../machine/timer.cc <<<
>>> Building dependency file for ../machine/sysdep.cc <<<
>>> Building dependency file for ../machine/interrupt.cc <<<
../Makefile.dep:29: Linux
>>> Compiling ../machine/interrupt.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/interrupt.o ../machine/interrupt.cc
...........................
>>> Compiling ../machine/sysdep.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/sysdep.o ../machine/sysdep.cc
.......
>>> Compiling ../machine/timer.cc <<<
g++ -m32 -g -Wall -Wshadow -m32 -I../lab2 -I../threads -I../machine -DTHREADS -DHOST_i386 -DHOST_LINUX -DCHANGED -c -o arch/unknown-i386-linux/objects/timer.o ../machine/timer.cc
.........
>>> Linking arch/unknown-i386-linux/bin/nachos <<<
g++ -m32 arch/unknown-i386-linux/objects/main.o arch/unknown-i386-linux/objects/list.o arch/unknown-i386-linux/objects/scheduler.o arch/unknown-i386-linux/objects/synch.o arch/unknown-i386-linux/objects/synchlist.o arch/unknown-i386-linux/objects/system.o arch/unknown-i386-linux/objects/thread.o arch/unknown-i386-linux/objects/utility.o arch/unknown-i386-linux/objects/threadtest.o arch/unknown-i386-linux/objects/synchtest.o arch/unknown-i386-linux/objects/interrupt.o arch/unknown-i386-linux/objects/sysdep.o arch/unknown-i386-linux/objects/stats.o arch/unknown-i386-linux/objects/timer.o arch/unknown-i386-linux/objects/switch-linux.o -o arch/unknown-i386-linux/bin/nachos
ln -sf arch/unknown-i386-linux/bin/nachos nachos

Well I get this result, because I didn’t compile it first after I copy all these files, but if I do it a second time:

root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# touch ../threads/scheduler.h
root@iZbp1iqmvkj69470qn1vpvZ:~/OS/lab2# make
../Makefile.dep:29: Linux
make: 'arch/unknown-i386-linux/bin/nachos' is up to date.

It shows that it has nothing to do with the file in scheduler.h in threads directory if we change anything in scheduler.h in the current directory, lab2 .

Method 2

Change Makefile.local :

INCPATH += -I- -I../lab2 -I../threads -I../machine

Just make . Needn’t copy a bunch of files associated with scheduler.h .