NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Why muck with the MakeFile?

March 24, 2011
by Ralphxyz
Ralphxyz's Avatar

It seems that a display of maturity as a "programmer" is to use a custom Makefile. Why?

What is the advantage of using a custom Makefile over just using a generic Nerdkits Makefile?

Ok, I like using bretm's $(ProjectName) and adding the "clean" function has benefits to get rid of prior builds and then changing the optimization flags in AVRDUDE can be a necessity. But all of this can be done within the scope of modifying the initialload project Makefile.

I used to be a project manager and have worked with some very talented established programmer and with some really brilliant kids just starting their careers.

One of the topics that would come up often in our progress meetings would be using abstract off beat coding techniques. Thing that would work but only the originator would recognize or know how to deal with (at the moment not six months down the line). I "tried" to enforce the policy that "Just Because You Can Do Something Does Not Mean That You Should".

Now I am not a programmer and every piece of "working" code that I ever contributed to a project was re-written as soon as any programmer got their hands onto it. So I do not really have the mindset of a accomplished programmer but what is it about using complicated (to me) Makefiles. If I make modifications I would hope they simplify the operations making them more generic.

Now I know that most IDEs will also generate Makefiles is this where it starts? You are a learning programmer and your IDE makes these Makefiles for you and you read them and maybe the Make Manual and just start making up your own.

But what is the advantage? I had situations (with my limited abilities) where I could not use anything but the generic Nerdkits Makefile i.e. "it works for me".

I hope this sparks some good discussion as the Makefile is a very interesting tool, I used to build very early versions of Linux by hand before the Make utility got really established so I know the advantage of using a Makefile.

Ralph

March 24, 2011
by hevans
(NerdKits Staff)

hevans's Avatar

Hi Ralph,

You bring up a lot of great points here, and I do hope that lots of people jump in or at least think about the concepts you are bringing up. I will say that as far as NerdKits goes the idea behind having each project have its own custom Makefile is strictly an educational one. Mucking with makefiles and at least understanding what they are useful for is a really great thing to know. Once people have a handle on the low level workings, then abstracting away and trusting IDEs to do it for you is great.

So really I don't discourage anyone to build their own abstractions around the Makefiles or use IDEs to make life simpler, I just like to encourage people not to start there since then they are only familiar with the abstractions.

Humberto

March 24, 2011
by Noter
Noter's Avatar

When it comes to coding, I change makefiles to streamline the build process or otherwise increase my productivity. In particular, I don't like to have to edit a makefile everytime I set up a new program directory. I copy files from another program that I'm going to use as a start into a new directory, rename the .c file, and go. No editing of the makefile is needed to get started if I have setup my makefile to scan the directory and find the .c files instead of me naming them/it in the file. I guess I'm just lazy.

Likewise in the lib directory, I don't want to have to edit the makefile when I add a new module. I also like using a library .a file so that I don't have to go back and edit my program makefiles to add the new .o's to them. Now that's really lazy.

I don't know if you follow all of that but in the end, it makes building easier so I can concentrate more on coding instead of editing those pesky makefiles.

Another thing I prefer is to separate my compile/links from avrdude loads. I typically make small changes to the code and do a quick compile to check for errors but in no way am I ready to blast it onto the chip. Taking little steps and fixing errors as you go is a lot easier than coding the whole thing up and then looking at a list of 100(s) or more errors. So I make a separate 'program' procedure in the makefile to put it on the chip. I guess I don't type so well either because I get a lot of errors as I go along.

It is a pain to have to study and learn about makefiles just to be able to fix them up so I don't have to edit them all the time but in the end it's worth it to me. It's also nice to be able to look at any makefile and know exactly what is going on.

As far as technique, I always support which ever one gives the most effecient and effective utilization of the resource, machine or man. Some of those abstract off beat coding techniques result in better performance which translates into increased earnings/savings for the company. In my world, whoever came up with the wierd but good stuff had the task of educating/tutoring/supporting the rest of the team. Overall it was win/win for everyone with good levels of moral, enthusiasm, and ambition. It was also self regulating because if the tradeoff was breakeven and if the wizzard didn't want to do the educating/tutoring/supporting, they would stick with conventional methods. Nothing's perfect but it was close.

At the end of the day, a person really has to love to learn to be successful in a technical career. That's always been my favorite aspect of it, never getting bored, always new stuff to figure out and master. I am an old retired guy having spent my working years in the software arena and now I am having a blast with these mcu's. The nerdkit has been a tremendous help in getting started, it's about the neatest thing I've come across since moving to the farm. And my pic, it's from a long time ago but it reminds me of being young everytime I see it so I keep it around. ;-)

May 15, 2013
by dvdsnyd
dvdsnyd's Avatar

Noter, I know this is an old thread, but would you post your makefile? I would like to study it. The concept of separating the compiling and linking intrigues me. It would be nice to be able to do quick compiles to make sure syntax is correct.

Thanks, David

May 16, 2013
by Noter
Noter's Avatar

This is my current make file. "make" or "make program" compiles and downloads. "make compile" compiles only. "make clean" removes temp files and "make fuse" sets fuse values. I keep a lot of values ready to go and just uncomment the appropriate one for the project I am working on. It scans the directory for the .c file and makes it. If there is more than one .c it will attempt to make each one it finds so I never have more than one .c in the directory. It's just because I'm lazy and don't want to change the program name every time I copy it to a new project.

PGMR_COM_PORT=/dev/ttyUSB0 #PGMR_COM_BAUD=115200 PGMR_COM_BAUD=38400

MCU=atmega328p
#MCU=atmega168
#MCU=attiny85

#F_CPU=20000000UL
#F_CPU=18432000UL
#F_CPU=16000000UL
F_CPU=14745600UL
#F_CPU=8000000UL

APP_BAUD=115200L
#APP_BAUD=38400L
#APP_BAUD=9600L

#   external crystal and preserve eeprom on chip erase, no brown out
# ATmega328P
LFUSE = F7
HFUSE = D4
EFUSE = FD
LOCK = FF

#   internal 8mhz and preserve eeprom on chip erase
# ATmega328P
#LFUSE = E2
#HFUSE = D4
#EFUSE = FD
#LOCK = FF

all: $(patsubst %.c,%.pgm,$(wildcard *.c))

program: $(patsubst %.c,%.pgm,$(wildcard *.c))

compile: $(patsubst %.c,%.hex,$(wildcard *.c))

.SECONDARY:

%.o: %.c ../libnerdkits/libNerdKit.a ../libNoter/libNoter.a Makefile
    avr-gcc -g -Os -Wall -mmcu=$(MCU) -mcall-prologues \
        -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm \
        -I/home/paul/AVR \
        -Wl,-Map=$@.map \
        $< -o $@ ../libnerdkits/libNerdKit.a ../libNoter/libNoter.a \
        -DF_CPU=$(F_CPU) -DBAUD=$(APP_BAUD)

%.ass: %.o
    avr-objdump -S -d $< > $@

%.hex: %.o %.ass
    avr-objcopy -j .text -j .data -O ihex $< $@
    avr-size -A $(*F).hex

%.pgm: %.hex
    avrdude -C ../libnerdkits/avrdude.rs -c NANOISP -p $(MCU) -b $(PGMR_COM_BAUD) -P $(PGMR_COM_PORT) \
        -U flash:w:$<:a

clean: 
    -rm *.o *.hex *.ass *.map *.c~ Makefile~

fuse:
    avrdude -C ../libnerdkits/avrdude.rs -c NANOISP -p $(MCU) -b $(PGMR_COM_BAUD) -P $(PGMR_COM_PORT) -e \
    -U lfuse:w:0X$(LFUSE):m \
    -U hfuse:w:0X$(HFUSE):m \
    -U efuse:w:0X$(EFUSE):m \
    -U lock:w:0X$(LOCK):m
May 16, 2013
by Noter
Noter's Avatar

Missed that 1st line ...

PGMR_COM_PORT=/dev/ttyUSB0
#PGMR_COM_BAUD=115200
PGMR_COM_BAUD=38400

MCU=atmega328p
#MCU=atmega168
#MCU=attiny85

#F_CPU=20000000UL
#F_CPU=18432000UL
#F_CPU=16000000UL
F_CPU=14745600UL
#F_CPU=8000000UL

APP_BAUD=115200L
#APP_BAUD=38400L
#APP_BAUD=9600L

#   external crystal and preserve eeprom on chip erase, no brown out
# ATmega328P
LFUSE = F7
HFUSE = D4
EFUSE = FD
LOCK = FF

#   internal 8mhz and preserve eeprom on chip erase
# ATmega328P
#LFUSE = E2
#HFUSE = D4
#EFUSE = FD
#LOCK = FF

all: $(patsubst %.c,%.pgm,$(wildcard *.c))

program: $(patsubst %.c,%.pgm,$(wildcard *.c))

compile: $(patsubst %.c,%.hex,$(wildcard *.c))

.SECONDARY:

%.o: %.c ../libnerdkits/libNerdKit.a ../libNoter/libNoter.a Makefile
    avr-gcc -g -Os -Wall -mmcu=$(MCU) -mcall-prologues \
        -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm \
        -I/home/paul/AVR \
        -Wl,-Map=$@.map \
        $< -o $@ ../libnerdkits/libNerdKit.a ../libNoter/libNoter.a \
        -DF_CPU=$(F_CPU) -DBAUD=$(APP_BAUD)

%.ass: %.o
    avr-objdump -S -d $< > $@

%.hex: %.o %.ass
    avr-objcopy -j .text -j .data -O ihex $< $@
    avr-size -A $(*F).hex

%.pgm: %.hex
    avrdude -C ../libnerdkits/avrdude.rs -c NANOISP -p $(MCU) -b $(PGMR_COM_BAUD) -P $(PGMR_COM_PORT) \
        -U flash:w:$<:a

clean: 
    -rm *.o *.hex *.ass *.map *.c~ Makefile~

fuse:
    avrdude -C ../libnerdkits/avrdude.rs -c NANOISP -p $(MCU) -b $(PGMR_COM_BAUD) -P $(PGMR_COM_PORT) -e \
    -U lfuse:w:0X$(LFUSE):m \
    -U hfuse:w:0X$(HFUSE):m \
    -U efuse:w:0X$(EFUSE):m \
    -U lock:w:0X$(LOCK):m
May 16, 2013
by dvdsnyd
dvdsnyd's Avatar

Thanks Noter, This looks great. I will have to do some research and figure out how it works...

So when you run "make compile" do you have to have the programmer plugged into the microcontroller, like you would normally when you are compiling and downloading the program into flash memory?

Thanks Dave

May 16, 2013
by Noter
Noter's Avatar

The microcontroller only needs to be connected for the step that runs avrdude which is 'make' or 'make program' in my file. I do a lot of compiles as I write a program and don't program the chip until I'm ready to test.

May 18, 2013
by dvdsnyd
dvdsnyd's Avatar

Thanks again Noter, I will have to play around with this. Looks really neat. Thanks again for sharing!

July 15, 2013
by edb
edb's Avatar

Noter (or other makefile guru): The makefile above returns this error:

"makefile:50: *** missing separator.  Stop."

As I interpret this, it seems to suggest that line 50 is missing a character.
Here's line 49 and 50 from Noter's makefile:

%.ass: %.o
    avr-objdump -S -d $< > $@

After attempting to sort through the GNU make web page, I managed to figure out that there are some variables and some escape characters being used and there is something about secondary and I'm starting to get a headache. Any body seen this before? Suggestions (other than aspirin)? Thanks -- Ed.

July 15, 2013
by Noter
Noter's Avatar

In make files indented lines must be indented with a tab character instead of spaces. This site looses the tab and puts in spaces during upload so when you copy it you need to go through the file and fix the indented lines to use tabs.

July 17, 2013
by edb
edb's Avatar

Thanks Noter. I've read that somewhere in the Forum, but must have forgotten.

Post a Reply

Please log in to post a reply.

Did you know that you can use printf and scanf functions to talk to your computer from your USB NerdKit? Learn more...