views:

55

answers:

3

I have a large makefile which builds several libraries, installs them, and then keeps on building objects which link against those installed libraries. My trouble is that I want to use "-lfoo -lbar" as g++ flags to link against the two installed libraries, but the dependencies get messed up. If I change a header "42.h" which the library foo depends on, then of course make will rebuild and install it, but it does not appear to notice that my object "marvin" used "-lfoo" and marvin is left linked against the old version... :(

Thus far, I've been doing:

$(myObject): $(localSrc) /explicit/path/to/lib/libfoo.a
            $(CXX) $(CPPFLAGS) $(INCFLAGS) -o $@ $^ $(LINKFLAGS) $(LINKLIBS)

But I'm at a point where this is no longer a viable option. I need to simply add libraries "-lfoo -lbar" to the LINKFLAGS variable and have the linker figure things out?

In the mean time, I've aliased a few commands to explicitly blow away the object file(s) in question and then call make, but this is getting silly. I'm pressed for time, but if necessary I could post a small example perhaps Friday evening or Saturday morning.

Hence, I feel like I'm back in some bad version of windows dll hell. Is there something I can do to make the linker take notice of the version of the libraries that an object was built against and relink it if those libraries change??

Updated: So I hadn't had a chance to crash the suggestions until now. The drawback of what I'm doing is using static libraries. So I can't use ldd. So I rewrote my Makefile and found a way around this problem. If I get time, I'll post what I did.

A: 

You might try the gcc dependency generation arguments like -MD, it's not clear to me if you are using them.

Sam Miller
Yep. I am, sorry for not being specific.
M. Tibbits
please post your Makefile if possible, or a snippet that conveys the problem. It really sounds like some combination of the dependency arguments will solve this for you.
Sam Miller
+1  A: 

As far as I know, make in general isn't very good at automatically detecting dependencies like this. (It's not really make's job; make is a higher-level tool that's not aware of the specifics of the commands that it's spawning or what those commands do.)

Two options come to mind.

First, you could run ldd on $(myObject), save its list of libraries to a text file, then feed that back into your makefile as a list of dependencies. (This is similar to using -MD to save a list of header files to a text file then feeding that back into the makefile as additional rules for source file compilation, as Sam Miller suggested.)

Second, you could use a LINKLIBS variable as you've been using, and use GNU Make's functions to let the same variable work for both dependencies and command-line options. For example:

LINKLIBS := /explicit/path/to/lib/libfoo.so
$(myObject): $(localSrc) $(LINKLIBS)
        $(CXX) $(CPPFLAGS) $(INCFLAGS) -o $@ $^ $(LINKFLAGS) $(patsubst %,-l:%,$(LINKLIBS))
Josh Kelley
I never thought of using ldd on the object. Wouldn't this require the object to exist though, before it's compiled?As to your second suggestion (akin to the 'Beta' user) the trouble with this one is I no longer know the explicit path. I would like the linker to choose the correct library for me, but this has me thinking, perhaps I could use the patsubset in the dependency line with ?ld? or ?ldd? to determine the explicit path based on the LINKFLAGS (a bunch of -L's). However, from a quick google, I don't think ld or ldd can do this without building an object.
M. Tibbits
Anyone know of a tool akin to ld or ldd which can translate the -lfoo to the explicit path based on the -L's and the environmental variables?
M. Tibbits
ldd requires that the object already exist, but if the object doesn't exist, then you need to link it regardless (so you don't need to worry about dependencies for that case). You could set up your "link" rule to run ldd on the result then munge its output into a format that make expects for the next time that make is run. (Like I said, this would end up being similar logic to using -MD for gcc.)
Josh Kelley
+1  A: 

How about this:

LIBS = foo bar blah # and so on

LINKFLAGS = $(addprefix -l,$(LIBS))

LIBPATHS = $(patsubst %,/explicit/path/to/lib/lib%.so, $(LIBS))

$(myObject): $(localSrc) $(LIBPATHS)
        $(CXX) $(CPPFLAGS) $(INCFLAGS) -o $@ $^ $(LINKFLAGS) $(LINKLIBS)
Beta