I'm trying to define a make rule that modifies a make variable, as a way to conditionally compile the code. Something like:
[...]
LD_PREL:=
all: main
main: $(OBJ)
$(COMP) $(DEBUG) $(FLAGS) $^ -shared -o libname.so $(LIBS)
main_ld: ld_prel_def $(OBJ)
$(COMP) $(DEBUG) $(FLAGS) $^ -shared -o libname_ld.so $(LIBS)
ld_prel_def:
$(eval LD_PREL:=-DWITH_LD_PRELOAD)
echo $(LD_PREL)
$(OBJDIR)/%.o: src/%.c $(DEPS)
$(COMP) $(DEBUG) $(FLAGS) $(DDEFS) $(TDEFS) $(LD_PREL) $(WARN) -c -fPIC -o $@ $<
From the echo
line, it seems that it is working as expected:
echo -DWITH_LD_PRELOAD
-DWITH_LD_PRELOAD
except that the linker than throws error:
/usr/local/bin/ld: cannot find ld_prel_def: No such file or directory
collect2: error: ld returned 1 exit status
make: *** [Makefile:27: main_ld] Error 1
What am I doing wrong?
Oh, I see the problem. This rule:
main_ld: ld_prel_def $(OBJ)
$(COMP) $(DEBUG) $(FLAGS) $^ -shared -o libname_ld.so $(LIBS)
uses $^
which resolves to all the prerequisites. One of the prerequisites is your target ld_prel_def
which obviously is not a valid object file, so your linker fails.
You could use:
main_ld: ld_prel_def $(OBJ)
$(COMP) $(DEBUG) $(FLAGS) $(filter %.o,$^) -shared -o libname_ld.so $(LIBS)
In general, as with almost any use of $(eval ...)
inside recipes, this is a pretty brittle way to write a makefile IMO. What if some of the objects are compiled one way, say without the option, and then you run make main_ld
and compile the rest of the objects that aren't up to date the other way? Now you have a mix of some objects built one way and some built the other way.