Page 1 of 1
Writing a Makefile
Posted: Tue Apr 19, 2011 2:29 pm
by Rudster816
I cant seem to get a simple makefile up to use for my OS. I have spent a couple hours reading various makefile tutorials and the GNU make documentation, but I have no idea what Im doing wrong.
Code: Select all
# C Compiler
CC = i686-elf-gcc
CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -Wall -Wextra
# Assembler
AA = nasm
AFLAGS =
# Linker
LD = i686-elf-ld
LDFLAGS =
kernel.bin : kernel.c
$(LD) -T linker.ld -o kernel.bin loader.o kernel.o
kernel.o : kernel.c
$(CC) -o kernel.o -c kernel.c $(CFLAGS)
loader.o : loader.s
$(AA) -f elf -o loader.o loader.s
Anytime I run 'make kernel.o' or 'make loader.o', it always runs cc and as, rather than my cross compiler tools. Also when I try to make kernel.bin, it always says "Nothing to be done for 'kernel.bin'.". Obviously it isnt reading my recipes correctly and is using the defaults, but I have no idea why or how to fix this. Im sure the problem is obvious to someone. I have never used make up until now, so Im pretty clueless.
Re: Writing a Makefile
Posted: Tue Apr 19, 2011 3:28 pm
by TylerH
It's := not =.
Also, the point of make is to generalize. You make general rule for a .c's and make just does them for you. And bookmark this:
http://www.gnu.org/s/hello/manual/make/ ... ables.html
For an example of an overcomplicated generalization, here's mine:
Code: Select all
ARCH :=i586
FRMT :=elf
SRCDIRS :=. arch/$(ARCH) init kernel lib mm
INCDIRS :=include include/$(ARCH)
BINDIR :=bin
OBJDIR :=obj
UTLDIR :=util
HEADERS :=$(foreach DIR, $(INCDIRS), $(wildcard $(DIR)/*.h))
SOURCES :=$(foreach DIR, $(SRCDIRS), $(wildcard $(DIR)/*.asm $(DIR)/*.c $(DIR)/*.cpp))
OBJECTS :=$(foreach OBJECT, $(patsubst %.asm, %.o, $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(SOURCES)))), $(OBJDIR)/$(OBJECT))
TARGET :=$(BINDIR)/kernel
.PHONY : all
all : $(TARGET)
./$(UTLDIR)/mbchk $(BINDIR)/kernel
.PHONY : clean
clean :
rm -r $(BINDIR) $(OBJDIR)
.PHONY : doc
doc : all
doxygen $(UTLDIR)/Doxyfile
$(TARGET) : $(OBJECTS)
mkdir -p $(@D)
$(LD) $(LDFLAGS) -o $@ -T $(UTLDIR)/link.ld $+
# Tool Configuration
AS :=$(ARCH)-$(FRMT)-as
ASFLAGS :=-c -mmnemonic=intel -msyntax=intel -mnaked-reg
ASM :=fasm
ASMFLAGS:=-m 262144 -p 1000
CC :=$(ARCH)-$(FRMT)-gcc
CFLAGS :=-c -ffreestanding $(foreach INCDIR, $(INCDIRS), -I$(INCDIR)) -masm=intel -std=c99 -Wall
CXX :=$(ARCH)-$(FRMT)-g++
CXXFLAGS :=-c -ffreestanding -fno-builtin -fno-exceptions -fno-rtti -fno-stack-protector $(foreach INCDIR, $(INCDIRS), -I $(INCDIR)) -masm=intel -nodefaultlibs -nostartfiles -nostdlib -std=c++0x -Wall
LD :=$(ARCH)-$(FRMT)-ld
LDFLAGS :=--warn-unresolved-symbols
# Generic Rules
$(OBJDIR)/%.o : %.S
mkdir -p $(@D)
$(info ==== .S($<) -> .o($@) rule)
@$(AS) $(ASFLAGS) $< $@
$(OBJDIR)/%.o : %.asm
mkdir -p $(@D)
$(info ==== .asm($<) -> .o($@) rule)
@$(ASM) $(ASMFLAGS) $< $@
$(OBJDIR)/%.o : %.c
mkdir -p $(@D)
$(info ==== .c($<) -> .o($@) rule)
@$(CC) $(CFLAGS) $< -o $@
$(OBJDIR)/%.o : %.cpp
mkdir -p $(@D)
$(info ==== .cpp($<) -> .o($@) rule)
@$(CXX) $(CXXFLAGS) $< -o $@
Re: Writing a Makefile
Posted: Tue Apr 19, 2011 4:19 pm
by Rudster816
Turns out that Notepadd++ was saving it in Macintosh format instead of Unix
Set it to Unix and everything works now. Thanks for your help.
Re: Writing a Makefile
Posted: Tue Apr 19, 2011 6:32 pm
by TylerH
Rudster816 wrote:Turns out that Notepadd++ was saving it in Macintosh format instead of Unix
Set it to Unix and everything works now. Thanks for your help.
Nice! About the = vs. := thing: It doesn't have to be :=. I forgot about = because I never use it. Be careful with =, the variables stored with it aren't evaluated until the variable defined with it are used. Whereas with the :=, it saves the current value of the variables.
Ex:
Code: Select all
a := b
# a = ""
b := 4
# a == ""
a = b
# a == 4
b := 3
# a == 3
Re: Writing a Makefile
Posted: Tue Apr 19, 2011 11:52 pm
by Solar
May I advertise the
Makefile tutorial at this point?
Note that = not only defers evaluation to the
first use, but re-evaluates on
every use, which - given a sufficiently badly-written Makefile - can result in surprising performance penalties.
Re: Writing a Makefile
Posted: Wed Apr 20, 2011 1:41 am
by qw
Kernel.bin is not depending on kernel.c but on loader.o and kernel.o:
Code: Select all
kernel.bin : kernel.c
$(LD) -T linker.ld -o kernel.bin loader.o kernel.o
So the rule should read:
Code: Select all
kernel.bin : loader.o kernel.o
$(LD) -T linker.ld -o kernel.bin loader.o kernel.o
Or even better:
Code: Select all
kernel.bin : loader.o kernel.o
$(LD) -T linker.ld -o $@ $^
The
GNU make manual is pretty good. You'll find anything you need to know there.
Re: Writing a Makefile
Posted: Wed Apr 20, 2011 3:41 am
by Solar
Hobbes wrote:The
GNU make manual is pretty good. You'll find anything you need to know there.
Aaahhhh... not really. They describe every single feature of GNU make in there, but fall woefully short of teaching you how to put it all together into a
good Makefile. Especially automatic dependency handling isn't handled well (if at all) in the make manual, because it requires co-operation between make and the compiler used.
Re: Writing a Makefile
Posted: Wed Apr 20, 2011 4:39 am
by qw
Solar wrote:Aaahhhh... not really.
Well, it is a manual, not a tutorial. At least the OP will find answers to the more technical questions. I was pretty happy with it anyway.