Reputation: 24523
I have an external tool that fetches some sources (Rebar). I want to fill in a variable according to the contents of a directory after Rebar runs.
EFLAGS += -I$(PWD)/include
EFLAGS += -pa $(PWD)/ebin
## $(PWD)/deps/* will only have contents after Rebar runs
EFLAGS += $(patsubst %,-pa %,$(wildcard $(PWD)/deps/*/ebin))
build-deps:
./rebar get-deps
./rebar compile
build-main: build-deps
erlc $(EFLAGS) $(INFILE)
The above will work as intended if I run it as two separate invocations:
make build-deps
make build-main
However, if I just make build-main
, then EFLAGS
gets set while the deps/
directory is empty, then the directory is populated, and then I use EFLAGS
.
Is there a good way for me to only set EFLAGS
after I've run some rules?
EDIT: Here's a Makefile that may demonstrate the problem more easily:
A=$(wildcard test*)
foo:
touch test1
bar: foo
@echo $A
clean:
-rm test*
Here, the "foo" target is standing in for my call to rebar
, so just imagine that you don't know which files I'm going to pass to touch
. If you try
make clean
make bar
make bar
you will find that the two invocations of make bar
produce different results, because in the second one test1
exists before make
begins. I'm looking for a way to get the output of the second make bar
invocation immediately after running make clean
.
Upvotes: 2
Views: 1545
Reputation: 81052
I believe something like the following, using an included makefile, will work. Untested but I believe something along these lines will do what you want. Assuming you want to run rebar every time you try to build.
EFLAGS += -I$(PWD)/include
EFLAGS += -pa $(PWD)/ebin
EFLAGS += $(PADIRS)
-include paflags.mk
build-main:
erlc $(EFLAGS) $(INFILE)
paflags.mk: force
./rebar get-deps
./rebar compile
echo 'PADIRS := $$(patsubst %,-pa %,$$(wildcard $$(PWD)/deps/*/ebin))' > '$@'
force: ;
Above edited to remove the .PHONY
declaration on paflags.mk
as that seemed to cause make to not perform the restart necessary for this trick to work.
Alternatively, since you aren't using any of make's prerequisite testing for this you could just move it all into the build-main rule body and do the globbing/etc. in the shell.
Alternatively alternatively, you could use eval
to forcibly evaluate the patsubst in the build-main rule I believe (I'd have to test that to be sure the timing works out correctly with how, GNU make at least, hoists make directives in rule bodies).
This version of the idea above for the simple test case works for me:
-include inc.mk
$(warning A:$A)
bar:
@echo $A
inc.mk:
touch test1
echo 'A=$$(wildcard test*)' > '$@'
force: ;
Edited both sample makefiles to include a force rule on the included makefile to force make to build the included file every time. Without that (and without fancy automatic dependency generation/detection) make will only build the included file the first time and then never touch it again. I believe the force, at a cost of always trying to build it, will avoid that problem.
That being said, for this case, MadScientist's answer is probably the better choice.
Upvotes: 3
Reputation: 101081
The simplest solution is to use the shell to compute the value, rather than using make rules. Like this:
EFLAGS += -I$(PWD)/include
EFLAGS += -pa $(PWD)/ebin
## $(PWD)/deps/* will only have contents after Rebar runs
EFLAGS += $(patsubst %,-pa %,$(wildcard $(PWD)/deps/*/ebin))
build-deps:
./rebar get-deps
./rebar compile
build-main: build-deps
for f in $(PWD)/deps/*/ebin; do paflags="$$paflags -pa $$f"; done; \
erlc $(EFLAGS) $$paflags $(INFILE)
Upvotes: 4