Falcata
Falcata

Reputation: 707

Multiple executables from makefile

I am trying to write a makefile that will compile a simple simulated Real time operating system written in c.

The directory structure looks something like this

 **KB**

     SOURCE
     -------
         - Keyboard.c (helper process)
     Incl
     --------
         - Include files needed by keyboard.c

    **CRT**

     SOURCE
     -------
         - crt.c (helper process)
     Incl
     --------
         - Include files needed by crt.c

    **RTX**

    SOURCE
    -------
       - SOURCE Files

    INCLUDE
    --------
       - Include Files

The RTX requires that the helper processes be compiled into two executable, it then uses these executable to run.

I have no idea on how to generate three different executable in the same Makefile, or even on how to include the files in the different include files for even one executable. I've never created a makefile before and am having problems following tutorials online.

Here is what I have so far for the RTX (how do I add in different paths?)

#For RTX Exexutable
OBJS = api.o init_table.o k_rtx.o msg.o pcb.o queue.o user_proc.o main.o

iRTX-G29 : $(OBJS)
    gcc -o iRTX-G29 $(OBJS)

api.o : api.h
    gcc -c api.c
init_table.o : init_table.h
    gcc -c init_table.c
k_rtx.o : unistd.h string.h k_rtx.h
    gcc -c k_rtx.c
main.o : fcntl.h sys/mman.h sys/wait.h stdio.h stdio.h sys/types.h sys/ipc.h sys/shm.h errno.h string.h stdlib.h signal.h k_rtx.h buffer.h global.h
    gcc -c main.c
msg.o : msg.h
    gcc -c msg.c
queue.o : queue.h
    gcc -c queue.c
user_proc.o : user_proc.h
    gcc -c user_proc.c

Any help would be greatly appreciated! Thanks!

Upvotes: 0

Views: 6607

Answers (3)

Beta
Beta

Reputation: 99094

First let's simplify your existing makefile. You have many object rules that have the same form:

msg.o : msg.h
    gcc -c msg.c

A cleaner way to write it is like this:

msg.o : msg.c msg.h
    gcc -c $< -o $@

(I've added the dependency msg.c, put in some automatic variables and specified the name of the output.) Now that all of these object rules look alike, we can make a pattern rule for this, but I'll separate the header dependency for now because main.o doesn't depend on main.h:

api.o : api.h
init_table.o : init_table.h
k_rtx.o : unistd.h string.h k_rtx.h
main.o : fcntl.h sys/mman.h sys/wait.h stdio.h stdio.h sys/types.h sys/ipc.h sys/shm.h errno.h string.h stdlib.h signal.h k_rtx.h buffer.h global.h
msg.o : msg.h
queue.o : queue.h
user_proc.o : user_proc.h

%.o : %.c
    gcc -c $< -o $@

Most of these objects have a header dependency, so we can separate those out and make it a little shorter:

api.o init_table.o k_rtx.o msg.o queue.o user_proc.o : %.o : %.h

k_rtx.o : unistd.h string.h
main.o : fcntl.h sys/mman.h sys/wait.h stdio.h stdio.h sys/types.h sys/ipc.h sys/shm.h errno.h string.h stdlib.h signal.h k_rtx.h buffer.h global.h

%.o : %.c
    gcc -c $< -o $@

This will work within RTX/, but to get it to work when executed in the parent directory, we have to change a couple of things. I'll assume that there is a danger of filename collision (i.e. there is a main.c in RTX/, and a different main.c in CRT/, so we mustn't get the main.os mixed up). So let's keep the RTX object files in RTX/ (and I'll take main.o out of the object list for convenience, and omit the sys/*** dependencies because I don't know where you keep sys/). And this answer is getting long, so I'll fold in the other executables and a master target to build them all:

# This is the first target, so it will be the default: run "make", and you'll get this.
.PHONY: all
all: iRTX-G29 iCRT-G29 iKBD-G29
    @echo all done

#For RTX Executable
RTX_OBJS = $(addprefix RTX/, api.o init_table.o k_rtx.o msg.o pcb.o queue.o user_proc.o)
iRTX-G29 : $(RTX_OBJS) RTX/main.o

# This is a little clumsy, but it can't (easily) be helped.
RTX/k_rtx.o : RTX/unistd.h RTX/string.h
RTX/main.o : $(addprefix RTX/, fcntl.h stdio.h stdio.h errno.h string.h stdlib.h signal.h k_rtx.h buffer.h global.h)

#Now we can throw in the CRT and Keyboard executables:

CRT_OBJS = $(addprefix CRT/, this.o that.o theOther.o)
iCRT-G29 : $(CRT_OBJS) CRT/main.o

CRT/this.o: CRT/whatever.h

KBRD_OBJS = $(addprefix SOURCE/, red.o green.o blue.o)    
iKBD-G29 : $(KBRD_OBJS) SOURCE/main.o

SOURCE/green.o: SOURCE/chlorophyll.h

# Now for the stuff common to all three

iRTX-G29 iCRT-G29 iKBD-G29 :
    gcc -o $@ $^

$(RTX_OBJS) $(CRT_OBJS) $(KBRD_OBJS): %.o : %.h

%.o : %.c
    gcc -c $< -o $@

Upvotes: 4

fghj
fghj

Reputation: 9394

In makefile you can write target that not correspond to real file:

all: executable1 executable2

executable1: a.o b.o
<TAB HERE>gcc -o $@ $^

executable2: c.o d.o
<TAB HERE>gcc -o $@ $^

Upvotes: 1

thiton
thiton

Reputation: 36049

I have no idea on how to generate three different executable in the same Makefile, or even on how to include the files in the different include files for even one executable.

This is the perfect time to start using automake. Sarah George has written a good tutorial.

Upvotes: 0

Related Questions