I've been using target-specific variables for a while to pass object-specific flags. For example, if I need to link an executable with a certain library, I might do:
bin/foo: LDFLAGS += -lbar
And the bin/%
rule will pick up -lbar
. This works great for system libraries, but there's a problem when the libraries I'm linking against are also part of the project. In this case I'll have a dependency like
bin/foo: lib/libbar.so
and the target-specific rule I applied to bin/foo
is also passed when building lib/libbar.so
! This doesn't work since libbar.so
can't link to itself. As the manual says,
There is one more special feature of target-specific variables: when you define a target-specific variable that variable value is also in effect for all prerequisites of this target, and all their prerequisites, etc. (unless those prerequisites override that variable with their own target-specific variable value).
What can I do to add that flag only for bin/foo
but not its prerequisites? The quote above suggests something like
lib/libbar.so: LDFLAGS :=
but that's not ideal since my real project has other LDFLAGS set globally that I want to keep.
Here's a reproducer:
Makefile
bin/%: @mkdir -p $(@D) gcc $(LDFLAGS) $(filter %.o,$^) -o $@ lib/%: @mkdir -p $(@D) gcc $(LDFLAGS) -shared $(filter %.o,$^) -o $@ obj/%.o: src/%.c @mkdir -p $(@D) gcc $(CFLAGS) -c $< -o $@ bin/foo: obj/foo.o lib/libbar.so bin/foo: LDFLAGS := -Wl,-rpath='$$ORIGIN/../lib' -Llib -lbar lib/libbar.so: obj/bar.o clean: rm -rf bin lib obj .PHONY: clean
src/foo.c
int bar(void); int main() { return bar(); }
src/bar.c
int bar() { return 42; }
This is broken:
$ make bin/foo
gcc -c src/foo.c -o obj/foo.o
gcc -c src/bar.c -o obj/bar.o
gcc -Wl,-rpath='$ORIGIN/../lib' -Llib -lbar -shared obj/bar.o -o lib/libbar.so
/bin/ld: lib/libbar.so: file not recognized: file truncated
collect2: error: ld returned 1 exit status
make: *** [Makefile:7: lib/libbar.so] Error 1
But if I build the lib first it works:
$ make lib/libbar.so
gcc -c src/bar.c -o obj/bar.o
gcc -shared obj/bar.o -o lib/libbar.so
$ make bin/foo
gcc -c src/foo.c -o obj/foo.o
gcc -Wl,-rpath='$ORIGIN/../lib' -Llib -lbar obj/foo.o -o bin/foo
$ ./bin/foo; echo $?
42