Sudar
Sudar

Reputation: 19992

Dynamic conditions in makefile

I maintain a fairly complex makefile for Arduino.

In the makefile, I have target to build *.hex file from *.cpp file. After the *.hex file is generated, I want to check whether the hex size of the file is less than the flash memory of the microcontroller.

To do that, I have added another target called verify_size which touches a *.sizeok file if the hex size is less.

Following is the relevant code

$(TARGET_HEX).sizeok: $(TARGET_HEX)
ifneq ($(strip $(HEX_MAXIMUM_SIZE)),1)
ifeq ($(shell expr `$(call avr_size,$(TARGET_HEX)) | grep Program | awk '{print $$2}'` '<' $(HEX_MAXIMUM_SIZE)), 1)
    touch $@
endif
else
    @$(ECHO) Maximum Hex size is not specified. Make sure the hex file that you are going to upload is less than microcontrollers flash memory
endif

verify_size:    $(TARGET_HEX) $(TARGET_HEX).sizeok

The problem I am facing is that when the makefile is run for the very first time, I get a error saying that the hex file doesn't exist.

After some debugging I found that makefile first goes through the entire file before executing it. When it does this initial pass, the hex file not created yet and therefore the statements which does the parsing of hex file is not executed at all.

Is there a way by which I add dynamic conditions in makefile so that I can find the size of the hex file that was just generated?

Edit:

Based on @beta 's suggestion I changed the code to

$(OBJDIR)/%.hex: $(OBJDIR)/%.elf $(COMMON_DEPS)
    $(OBJCOPY) -O ihex -R .eeprom $< $@
    @$(ECHO)
    $(call avr_size,$<,$@)
ifneq ($(strip $(HEX_MAXIMUM_SIZE)),)
    if [ `$(SIZE) $@ | awk 'FNR == 2 {print $$2}'` -le $(HEX_MAXIMUM_SIZE) ]; then touch [email protected] ; fi
else
    @$(ECHO) Maximum Hex size is not specified. Make sure the hex file that you are going to upload is less than microcontrollers flash memory
endif

and it is working. But there is one small issue though.

In the above code, I am using a variable defined in makefile $(SIZE). But when this shell script executes, the value is not replaced. Instead it just replaces it with an empty value.

It works if I hardcode the value, but I am not able to use the value of the variable defined in makefile. Is it possible to access it?

Edit2:

I have posted a separate question for variable expansion issue.

Upvotes: 0

Views: 1327

Answers (1)

Beta
Beta

Reputation: 99094

If HEX_MAXIMUM_SIZE hasn't been set, Make should not update the sizeok file, and we shouldn't have a rule that can't actually rebuild its target. And we should update the sizeok file only when we rebuild the hex file. So instead of a rule for $(TARGET_HEX).sizeok, let's just make it a command within the $(TARGET_HEX) rule. (You haven't shown us avr_size, so I can't figure out your method for measuring the size of the hex file, so I'll just use ls and assume you aren't using pathological file names.)

$(TARGET_HEX): %.hex : %.cpps
    # Commands to build the target file
    if [ `ls -l $@ | awk '{print $$5}'` -le $(HEX_MAXIMUM_SIZE) ]; then touch [email protected] ; fi

Now we can add a condition, in case HEX_MAXIMUM_SIZE hasn't been set correctly:

$(TARGET_HEX): %.hex : %.cpps
    # Commands to build the target file
ifneq ($(strip $(HEX_MAXIMUM_SIZE)),1)
    if [ `ls -l $@ | awk '{print $$5}'` -le $(HEX_MAXIMUM_SIZE) ]; then touch [email protected] 
else
    @echo Maximum Hex size is not specified. Make sure that $@ is small enough for the microcontroller\'s flash memory.
endif

EDIT:

This may take a few iterations. Replace this line:

if [ `$(SIZE) $@ | awk 'FNR == 2 {print $$2}'` -le $(HEX_MAXIMUM_SIZE) ]; then touch [email protected] ; fi

with this:

$(SIZE) $@ | awk 'FNR == 2 {print $$2}'

and tell us the result.

Upvotes: 1

Related Questions