Linux – Defining Macros on the Command Line And In The Makefile ,Working on linux using gcc, writing c code

cgcclinuxmakefile

I have a file named: Makefile and a main.c file
i am doing the next code in the main.c file

int main(int argc, char *argv[])
{

    //if 0 then it is default scheduling which is Round Robin.
    //if 1 then the scheduling will be Round Robin.
    //if 2 then the scheduling will be Priority based.
    //if 3 then both scheduling are acceptable, and we decide to use Round Robin.
    int scheduling = 0; 
    #ifdef SCHED_RR
            printf("SCHED_RR is defined\n");
            #ifdef SCHED_PB
                    printf("and also SCHED_PB is defined\n");
                    scheduling = 3;
            #else
                    scheduling = 1;
            #endif
    #elseif SCHED_PB
            printf("SCHED_PB is defined\n")
            scheduling = 2;
    #endif

    printf("the number of the scheduling is %d\n",scheduling);
    printf("bye bye\n");

    return 0;

}//main

as you can see i am checking if a macro has been defined and which one.
now i want to run the program with my Makefile doing the next command line

make some_var=SCHED_RR

this pseudo command (because i don't know how to really do it) is meant to predefine the macro SCHED_RR
also i want to be able to write the command

make some_var=SCHED_PB

and

make some_var1=SCHED_RR some_var2=SCHED_PB

the last one is for the case that someone would want to predefine both scheduling

now my problem is: i don't know how and where to write it in my Makefile
and also how to write it in the command line?

this is my Makefile which of course shows that my real program is bigger
so where and what should i add to this make file

OBJS = \
    bio.o\
    console.o\
    exec.o\
    file.o\
    fs.o\
    ide.o\
    ioapic.o\
    kalloc.o\
    kbd.o\
    lapic.o\
    log.o\
    main.o\
    mp.o\
    picirq.o\
    pipe.o\
    proc.o\
    spinlock.o\
    string.o\
    swtch.o\
    syscall.o\
    sysfile.o\
    sysproc.o\
    timer.o\
    trapasm.o\
    trap.o\
    uart.o\
    vectors.o\
    vm.o\



# Cross-compiling (e.g., on Mac OS X)
#TOOLPREFIX = i386-jos-elf-

# Using native tools (e.g., on X86 Linux)
#TOOLPREFIX = 

# Try to infer the correct TOOLPREFIX if not set
ifndef TOOLPREFIX
TOOLPREFIX := $(shell if i386-jos-elf-objdump -i 2>&1 | grep '^elf32-i386$$' >/dev/null 2>&1; \
    then echo 'i386-jos-elf-'; \
    elif objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \
    then echo ''; \
    else echo "***" 1>&2; \
    echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \
    echo "*** Is the directory with i386-jos-elf-gcc in your PATH?" 1>&2; \
    echo "*** If your i386-*-elf toolchain is installed with a command" 1>&2; \
    echo "*** prefix other than 'i386-jos-elf-', set your TOOLPREFIX" 1>&2; \
    echo "*** environment variable to that prefix and run 'make' again." 1>&2; \
    echo "*** To turn off this error, run 'gmake TOOLPREFIX= ...'." 1>&2; \
    echo "***" 1>&2; exit 1; fi)
endif

# If the makefile can't find QEMU, specify its path here
#QEMU = 

# Try to infer the correct QEMU
ifndef QEMU
QEMU = $(shell if which qemu > /dev/null; \
    then echo qemu; exit; \
    else \
    qemu=/Applications/Q.app/Contents/MacOS/i386-softmmu.app/Contents/MacOS/i386-softmmu; \
    if test -x $$qemu; then echo $$qemu; exit; fi; fi; \
    echo "***" 1>&2; \
    echo "*** Error: Couldn't find a working QEMU executable." 1>&2; \
    echo "*** Is the directory containing the qemu binary in your PATH" 1>&2; \
    echo "*** or have you tried setting the QEMU variable in Makefile?" 1>&2; \
    echo "***" 1>&2; exit 1)
endif


CC = $(TOOLPREFIX)gcc
AS = $(TOOLPREFIX)gas
LD = $(TOOLPREFIX)ld
OBJCOPY = $(TOOLPREFIX)objcopy
OBJDUMP = $(TOOLPREFIX)objdump
#CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -O2 -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer
CFLAGS = -fno-pic -static -fno-builtin -fno-strict-aliasing -Wall -MD -ggdb -m32 -Werror -fno-omit-frame-pointer
CFLAGS += $(shell $(CC) -fno-stack-protector -E -x c /dev/null >/dev/null 2>&1 && echo -fno-stack-protector)
ASFLAGS = -m32 -gdwarf-2 -Wa,-divide
# FreeBSD ld wants ``elf_i386_fbsd''
LDFLAGS += -m $(shell $(LD) -V | grep elf_i386 2>/dev/null)

xv6.img: bootblock kernel fs.img
    dd if=/dev/zero of=xv6.img count=10000
    dd if=bootblock of=xv6.img conv=notrunc
    dd if=kernel of=xv6.img seek=1 conv=notrunc

xv6memfs.img: bootblock kernelmemfs
    dd if=/dev/zero of=xv6memfs.img count=10000
    dd if=bootblock of=xv6memfs.img conv=notrunc
    dd if=kernelmemfs of=xv6memfs.img seek=1 conv=notrunc

bootblock: bootasm.S bootmain.c
    $(CC) $(CFLAGS) -fno-pic -O -nostdinc -I. -c bootmain.c
    $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c bootasm.S
    $(LD) $(LDFLAGS) -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o
    $(OBJDUMP) -S bootblock.o > bootblock.asm
    $(OBJCOPY) -S -O binary -j .text bootblock.o bootblock
    ./sign.pl bootblock

entryother: entryother.S
    $(CC) $(CFLAGS) -fno-pic -nostdinc -I. -c entryother.S
    $(LD) $(LDFLAGS) -N -e start -Ttext 0x7000 -o bootblockother.o entryother.o
    $(OBJCOPY) -S -O binary -j .text bootblockother.o entryother
    $(OBJDUMP) -S bootblockother.o > entryother.asm

initcode: initcode.S
    $(CC) $(CFLAGS) -nostdinc -I. -c initcode.S
    $(LD) $(LDFLAGS) -N -e start -Ttext 0 -o initcode.out initcode.o
    $(OBJCOPY) -S -O binary initcode.out initcode
    $(OBJDUMP) -S initcode.o > initcode.asm

kernel: $(OBJS) entry.o entryother initcode kernel.ld
    $(LD) $(LDFLAGS) -T kernel.ld -o kernel entry.o $(OBJS) -b binary initcode entryother
    $(OBJDUMP) -S kernel > kernel.asm
    $(OBJDUMP) -t kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernel.sym

# kernelmemfs is a copy of kernel that maintains the
# disk image in memory instead of writing to a disk.
# This is not so useful for testing persistent storage or
# exploring disk buffering implementations, but it is
# great for testing the kernel on real hardware without
# needing a scratch disk.
MEMFSOBJS = $(filter-out ide.o,$(OBJS)) memide.o
kernelmemfs: $(MEMFSOBJS) entry.o entryother initcode fs.img
    $(LD) $(LDFLAGS) -Ttext 0x100000 -e main -o kernelmemfs entry.o  $(MEMFSOBJS) -b binary initcode entryother fs.img
    $(OBJDUMP) -S kernelmemfs > kernelmemfs.asm
    $(OBJDUMP) -t kernelmemfs | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > kernelmemfs.sym

tags: $(OBJS) entryother.S _init
    etags *.S *.c

vectors.S: vectors.pl
    perl vectors.pl > vectors.S

ULIB = ulib.o usys.o printf.o umalloc.o uthread.o

_%: %.o $(ULIB)
    $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^
    $(OBJDUMP) -S $@ > $*.asm
    $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym

_forktest: forktest.o $(ULIB)
    # forktest has less library code linked in - needs to be small
    # in order to be able to max out the proc table.
    $(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o
    $(OBJDUMP) -S _forktest > forktest.asm

mkfs: mkfs.c fs.h
    gcc -DVarName=$(VarName) -m32 -Werror -Wall -o mkfs mkfs.c

UPROGS=\
    _cat\
    _echo\
    _forktest\
    _grep\
    _init\
    _kill\
    _ln\
    _ls\
    _mkdir\
    _rm\
    _sh\
    _stressfs\
    _usertests\
    _wc\
    _zombie\
    _main\

fs.img: mkfs README $(UPROGS)
    ./mkfs fs.img README $(UPROGS)

-include *.d

clean: 
    rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
    *.o *.d *.asm *.sym vectors.S bootblock entryother \
    initcode initcode.out kernel xv6.img fs.img kernelmemfs mkfs \
    .gdbinit \
    $(UPROGS)

# make a printout
FILES = $(shell grep -v '^\#' runoff.list)
PRINT = runoff.list runoff.spec README toc.hdr toc.ftr $(FILES)

xv6.pdf: $(PRINT)
    ./runoff
    ls -l xv6.pdf

print: xv6.pdf

# run in emulators

bochs : fs.img xv6.img
    if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi
    bochs -q

# try to generate a unique GDB port
GDBPORT = $(shell expr `id -u` % 5000 + 25000)
# QEMU's gdb stub command line changed in 0.11
QEMUGDB = $(shell if $(QEMU) -help | grep -q '^-gdb'; \
    then echo "-gdb tcp::$(GDBPORT)"; \
    else echo "-s -p $(GDBPORT)"; fi)
ifndef CPUS
CPUS := 1
endif
QEMUOPTS = -hdb fs.img xv6.img -smp $(CPUS) -m 512 $(QEMUEXTRA)

qemu: fs.img xv6.img
    $(QEMU) -serial mon:stdio $(QEMUOPTS)

qemu-memfs: xv6memfs.img
    $(QEMU) xv6memfs.img -smp $(CPUS)

qemu-nox: fs.img xv6.img
    $(QEMU) -nographic $(QEMUOPTS)

.gdbinit: .gdbinit.tmpl
    sed "s/localhost:1234/localhost:$(GDBPORT)/" < $^ > $@

qemu-gdb: fs.img xv6.img .gdbinit
    @echo "*** Now run 'gdb'." 1>&2
    $(QEMU) -serial mon:stdio $(QEMUOPTS) -S $(QEMUGDB)

qemu-nox-gdb: fs.img xv6.img .gdbinit
    @echo "*** Now run 'gdb'." 1>&2
    $(QEMU) -nographic $(QEMUOPTS) -S $(QEMUGDB)

# CUT HERE
# prepare dist for students
# after running make dist, probably want to
# rename it to rev0 or rev1 or so on and then
# check in that version.

EXTRA=\
    mkfs.c ulib.c user.h cat.c echo.c forktest.c grep.c kill.c\
    ln.c ls.c mkdir.c rm.c stressfs.c usertests.c wc.c zombie.c\
    printf.c umalloc.c main.c\
    README dot-bochsrc *.pl toc.* runoff runoff1 runoff.list\
    .gdbinit.tmpl gdbutil\

dist:
    rm -rf dist
    mkdir dist
    for i in $(FILES); \
    do \
        grep -v PAGEBREAK $$i >dist/$$i; \
    done
    sed '/CUT HERE/,$$d' Makefile >dist/Makefile
    echo >dist/runoff.spec
    cp $(EXTRA) dist

dist-test:
    rm -rf dist
    make dist
    rm -rf dist-test
    mkdir dist-test
    cp dist/* dist-test
    cd dist-test; $(MAKE) print
    cd dist-test; $(MAKE) bochs || true
    cd dist-test; $(MAKE) qemu

# update this rule (change rev#) when it is time to
# make a new revision.
tar:
    rm -rf /tmp/xv6
    mkdir -p /tmp/xv6
    cp dist/* dist/.gdbinit.tmpl /tmp/xv6
    (cd /tmp; tar cf - xv6) | gzip >xv6-rev5.tar.gz

.PHONY: dist-test dist

thank you

Best Answer

What you need is

make -e VarName=VarValue

This will export the VarName into the makefile where you can use it as a $(VarName) in the gcc compile statement.

So, in the makefile it would be

gcc -DVarName=$(VarName) -c your_source.c -o your_obj.o

For the "#ifdef" situation you either have to change it to "#if", or use this:

make -e SCHED_PR=1

and in the makefile

ifeq ($(SCHED_PR), 1)
mkfs: .....
    gcc -DSCHED_PR=1  ....
else
mkfs: .....
    gcc ....
endif

In the .c file

#if SCHED_PR

...