Writing a Makefile

Programming, for all ages and all languages.
Post Reply
Rudster816
Member
Member
Posts: 141
Joined: Thu Jun 17, 2010 2:36 am

Writing a Makefile

Post 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.
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: Writing a Makefile

Post 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 $@
Rudster816
Member
Member
Posts: 141
Joined: Thu Jun 17, 2010 2:36 am

Re: Writing a Makefile

Post by Rudster816 »

Turns out that Notepadd++ was saving it in Macintosh format instead of Unix #-o

Set it to Unix and everything works now. Thanks for your help.
TylerH
Member
Member
Posts: 285
Joined: Tue Apr 13, 2010 8:00 pm
Contact:

Re: Writing a Makefile

Post by TylerH »

Rudster816 wrote:Turns out that Notepadd++ was saving it in Macintosh format instead of Unix #-o

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
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Writing a Makefile

Post 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.
Every good solution is obvious once you've found it.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Writing a Makefile

Post 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.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re: Writing a Makefile

Post 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.
Every good solution is obvious once you've found it.
User avatar
qw
Member
Member
Posts: 792
Joined: Mon Jan 26, 2009 2:48 am

Re: Writing a Makefile

Post 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.
Post Reply