0

Im trying with one Makefile to compile many .c files. I have written all the rules and I want to add a rule that says: execute all the rules who depend on .c files.

In reference of : Compile all C files in a directory into separate programs

PROGRAMS := copy.c sec_soft.c
PROGRAMS_NO_EX := $(basename $(PROGRAMS))
PROGRAMS_TO_CREATE := $(PROGRAMS_NO_EX).elf $(PROGRAMS_NO_EX).dump $(PROGRAMS_NO_EX).bin $(PROGRAMS_NO_EX).hex $(PROGRAMS_NO_EX).mem  $(PROGRAMS_NO_EX).coe

RISCV_OPTIONS = -march=rv32if -mabi=ilp32 -o  
RISCV_LINK = $(RISCV_GCC) $(CFLAGS) $< -o $@                            #produces .elf file!
RISCV_OBJDUMP = $(RISCV_PREFIX)objdump -D   $(DFLAGS)                       #produces a dump file to see the assembly code!
RISCV_OBJCOPY = $(RISCV_PREFIX)objcopy -O binary                        #produces a bin file!

ALL_RES = $(PROGRAMS:%.c=%.elf)

%.elf: %.c
    $(info Generating .elf file from files: $(PROGRAMS_NO_EX))
    $(RISCV_LINK)
    $(info Success!)
    $(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.dump: %.elf
    $(info Copying assembly to dump file $(PROGRAMS_NO_EX).dump)
    @$(RISCV_OBJDUMP) $< > $@
    $(info Success!)
    $(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.bin: %.elf
    $(info Generating bin file)
    @$(RISCV_OBJCOPY) $< $@
    $(info Success!)
    $(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.hex: %.bin 
    $(info Generating hex file)
    echo cd $(SCRIPTDIR)
    $(info Running binary to hex >>>)
    python $(SCRIPTDIR)/bin2hex.py -a $(START_ADDRESS) -o $@ $<
    $(info Hex Generation Successful!)
    $(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.mem: %.bin
    $(info Instantiating memory addresses...)
    head -c $$(( $(START_ADDRESS))) /dev/zero | cat - $< | xxd -g1 -c4 | awk '{print $$5$$4$$3$$2}' > $@
    $(info Memory instantiation Successful!)
    $(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)
%.coe: %.bin
    $(info Instantiating memory vector...)
    python $(SCRIPTDIR)/bin2coe.py $< -o $@
    $(info Memory vector instantiation Successful )
    $(info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~)    

all: $(ALL_RES);

But this line ALL_RES = $(PROGRAMS:%.c=%.elf) does not execute all the rules. I was hoping that after generating .elf files then all of the rules below would execute but not.

Im newbie on Makefiles, so please forgive any mistakes.

Thank you in advance

John Liko
  • 17
  • 5
  • `ALL_RES = ...` is a variable definition, it won't run anything. Perhaps you should add it as a rule (single line with the contents `$(ALL_RES):`)? – Some programmer dude May 25 '20 at 14:48
  • Do you want to execute all of the rules, or all of the rules with `.c`. prerequisites, or what? – Beta May 25 '20 at 17:30
  • @Beta Hello thank you for your comment. Yes I wanted to execute all the rules with .c prerequisites but raspy answered below! – John Liko May 26 '20 at 06:15
  • @Someprogrammerdude Hello! Thank you for your answer. It does run but only the .elf file extension. Raspy gave an answer below! – John Liko May 26 '20 at 06:16

1 Answers1

0

make will not create targets that you did not ask for. Your all target only asks to create files with .elf extension, nothing more. If you wish to build all others, you should tell make to do so.

The definition of targets to build should be updated, as it does not create file names properly. Written as it is, it only concatenates extension to the end of the variable. See for yourself:

$ make -rp 2>&1 | grep PROGRAMS_TO_CREATE
PROGRAMS_TO_CREATE := copy sec_soft.elf copy sec_soft.dump copy sec_soft.bin copy sec_soft.hex copy sec_soft.mem  copy sec_soft.coe

This should be updated to a proper string manipulation, e.g.:

PROGRAMS_TO_CREATE := $(foreach program,$(PROGRAMS_NO_EX),$(addprefix $(program),.elf .dump .bin .hex .mem .coe))

This will generate a proper list of targets:

$ make -rp 2>&1 | grep PROGRAMS_TO_CREATE
PROGRAMS_TO_CREATE := copy.elf copy.dump copy.bin copy.hex copy.mem copy.coe sec_soft.elf sec_soft.dump sec_soft.bin sec_soft.hex sec_soft.mem sec_soft.coe

which after setting as dependency to target all:

all: $(PROGRAMS_TO_CREATE)

will result in proper build.

raspy
  • 3,995
  • 1
  • 14
  • 18
  • Thank you very much it worked. But I did not understand what you say in this line " it only concatenates extension to the end of the variable. ". Im very new to Makefiles and still trying to understand how the execution works. -Why did I use foreach statement? -Why I can not do it like the reference link from other post of Stackoverflow? Thank you again ! – John Liko May 26 '20 at 06:14
  • Also can you tell me how can I execute a configuration statement only once and then let Makefile check if it is updated or not? This is what I have tried : FORCE,touch and if: CONFIGURATION := configure --prefix=$(LIBRARY_DIR) --with-arch=rv32if --with-abi=ilp32d configure: config.status touch configure config.status: cd $(LIBRARY_DIR) && $(CONFIGURATION);if [ -a $(LIBRARY_DIR)/config.status ]; then cd $(LIBRARY_DIR) && $(CONFIGURATION); fi; – John Liko May 26 '20 at 06:21
  • I showed you in the answer: when your `$(PROGRAMS_NO_EX)` contains `copy sec_soft`, then expression `$(PROGRAMS_NO_EX).elf` simply expands to `copy sec_soft.elf`, not to `copy.elf sec_soft.elf` which you might have expected. – raspy May 26 '20 at 08:45
  • As for the referenced link: it created targets based on .c file name indeed and that's what you had in your example as well. The thing is that in your case this is not the only and final target. You don't have one final target, but rather .elf, .dump, .bin, .hex, .mem and .coe. So your `ALL_RES` should rather say `$(PROGRAMS:%.c=%.elf) $(PROGRAMS:%.c=%.dump) $(PROGRAMS:%.c=%.bin) $(PROGRAMS:%.c=%.hex) $(PROGRAMS:%.c=%.mem) $(PROGRAMS:%.c=%.coe)`, which is another variant of what I suggested (with a `$(foreach)`). Remember, `make` only builds targets that you requested and dependencies of them. – raspy May 26 '20 at 08:55
  • Great I understood. Thank you very much again ! – John Liko May 26 '20 at 09:04
  • Can you also help me with this issue: https://stackoverflow.com/questions/61984239/makefile-can-i-execute-a-configuration-only-once – John Liko May 26 '20 at 10:17