I'm trying to create a generic build template for my Makefiles, kind of like they discuss in the eval documentation.
I can't seem to get the wildcard function to work within an eval. The basic code I'm having issues with looks like this.
SRC_DIR = ./src/
PROG_NAME = test
define PROGRAM_template
$(1)_SRC_DIR = $(join $(SRC_DIR), $(1)/)
$(1)_SRC_FILES = $(wildcard $$($(1)_SRC_DIR)*.c)
endef
$(eval $(call PROGRAM_template, $(PROG_NAME)))
all:
@echo $(test_SRC_DIR)
@echo $(test_SRC_FILES)
@echo $(wildcard $(wildcard $(test_SRC_DIR)*.c)
When I run make with this, the output is
./src/test
[correct list of all .c files in ./src/test/]
Basically, the wildcard call within PROGRAM_template is not being eval'd as I expect it. The call results in an empty list.
The join call is being eval'd correctly though.
So, what am I doing wrong? My guess is that
$$($(1)_SRC_DIR)
is not correct, but I can't figure out the right way to do it.
EDIT Once this was solved, it didn't take long for me to hit another issue with eval. I posted it as a new question at Workaround for GNU Make 3.80 eval bug
You need to double escape virtually all of the functions and variables when you use eval
. In most cases, the only things that don't need to be double-escaped are function arguments (because the call
function will fully expand them). In this case, you technically don't need to double-escape join
or SRC_DIR
either, but it will simplify your life if you just always double-escape all variables and functions when using eval
.
The reason you need the double escapes is that expansion happens twice when using eval
. The eval
function itself performs expansion, and then expansion is done again when the block is finally parsed as makefile syntax (i.e. when it is actually evaluated).
The way you've got it written, wildcard
is invoked on the string literal $( test_SRC_DIR)*.c
. If you want, you can see this for yourself by replacing wildcard
with info
in your version and see what happens.
You need to hold off on actually invoking wildcard
until the second expansion, so that it's argument is the result of the expansion of $(test_SRC_DIR)
.
Try this:
SRC_DIR = ./src/
PROG_NAME = test
define PROGRAM_template
$(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/)
$(1)_SRC_FILES = $$(wildcard $$($(1)_SRC_DIR)*.c)
endef
$(eval $(call PROGRAM_template,$(PROG_NAME)))
all:
@echo $(test_SRC_DIR)
@echo $(test_SRC_FILES)
@echo $(wildcard $(test_SRC_DIR)*.c)
EDIT: After posting this, I thought I'd better test it out to make sure it actually works. In doing so, I discovered another problem. You should avoid putting spaces between the comma and argument when calling functions. It causes a literal space character to be prepended to the argument that is passed to the function and leads to unintended results. I've removed the spaces after the commas in the function calls in my version (while this isn't a problem for the call to join
, I removed the space there as well just because it's a good habit to get into).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With