Is it possible to suppress variable inheritance for a specific premise?

I have a C ++ project that creates a shared library, and I want to add tests to it, in a separate executable file that dynamically links to the library. Therefore, the relevant part of the Makefile looks like this:

libstuff.so: stuff.o
    $(LINK_SHARED)

test: LDLFAGS += -L$(CURDIR) -Wl,-rpath=$(CURDIR) -lstuff
test: libstuff.so
test: test.o
    $(LINK)

check:: test
    ./test

      

LINK_SHARED

and are LINK

defined to call the compiler appropriately. The magic rpath

is to make sure the dynamic linker is linked to the exact version of the library I just compiled and want to test, and not the one installed.

The problem is that by default all target variables are inherited by preconditions, so it libstuff.so

gets -lstuff

in its own LDFLAGS

, and the linker complains that it can't find it (duh!).

Is there a way to say that I don't want any particular assumption to inherit my variables and only be used for dependency purposes?

There are some hacky workarounds that I don't like. For example, I can override LDFLAGS=

in the spec libstuff.so

, but then it won't display global LDFLAGS if I choose to define them.

There is a "private" modifier for variables here , which would solve my particular problem with LDFLAGS

, but I would be left with other things like CFLAGS

inherited (and I want it to be inherited by other prerequisites like files .o

). I want something like a private modifier instead.

I can make the test executable statically referenced with the object files that I am testing, but I really like the fact that I am testing that I have linked the shared object correctly.

I can get make to start with a clean slate on a variable using a recursive call to make:

.PHONY: test_prerequisites
test_prerequisites:
    $(MAKE) testlib.so

      

Marking a target as fake makes it run every time (as it should, since the original make cannot know about its real dependencies or try to make them itself). An unfortunate side effect is that the executable test

itself is rebuilt every time (although it is portable and at least testlib.so

not recoverable if necessary).

+1


source to share


2 answers


It looks like it can't be done in a sane way, but I figured out that a devilish contraption makes recursive call referencing completely correct, thanks to @EtanReisner. Here is a complete mock Makefile demonstrating the technique:

all:test

define LINK =
    @echo linking $@ with LDFLAGS=$(LDFLAGS)
    @touch $@
endef

stuff.o test.o:
    @echo compiling $@
    @touch $@

libstuff.so: stuff.o
    $(LINK)

.PHONY: FORCE

# A hack to avoid spilling LDFLAGS to prerequisites
.test_prerequisites.tmp: FORCE
    $(MAKE) .test_prerequisites2.tmp

.test_prerequisites2.tmp: libstuff.so
    touch .test_prerequisites.tmp .test_prerequisites2.tmp

test: LDFLAGS += -L$(CURDIR) -Wl,-rpath=$(CURDIR) -lstuff
test: .test_prerequisites.tmp
test: test.o
    $(LINK)

      

It uses two temporary witness files. When libstuff.so

(or any other possible condition) changes, both evidence files are updated and test

rebuilt.



However, when libstuff.so

not updating, the first recipe is still executing (due to the presence of a false premise), then the recursive call causes the second witness not to be updated and does not execute its recipe, so the first witness is not updated or test

rebuilt.

Note: For this particular problem, I decided to use make's original, simpler recursive solution because a) I already have a fake target used to build all the shared libraries in the project, and b) I almost always want the test binary to be restored when running tests anyway, because I just changed something, the thing I want to test.

+1


source


Add the LDFLAGS_TEST variable and add it to the LINK command for testing.



If you don't want to do this, see this related question: Define a make variable during rule execution

0


source







All Articles