Reputation: 642
I have a parent C++ Makefile that builds 2 libraries, from two source subdirectories.
Library B depends on Library A.
The cpp files is compiled via the standard implicit rule.
The linker step is completed by having a function that takes the sources, replaces the .cpp with a .o and then creates a dependency:
# $(call source-to-object, source-file-list)
source-to-object = $(subst .c,.o,$(filter %.c,$1)) \
$(subst .cpp,.o,$(filter %.cpp,$1))
# $(call make-library, library-name, source-file-list, customldopt)
define make-library
libraries += $1
sources += $2
$1: $(call source-to-object,$2)
$(CXX) $(CXXFLAGS) -shared $$^ -o $(RELEASE)/$$@ -L$(RELEASE) $(LDFLAGS) $(LDLIBS) $(addprefix -l,$3)
endef
This works fine until I want to introduce a dependency between the 2 libraries. I'm doing this by hardcoding:
libB.so: libA.so
The problem here is that the $$^
will now not cleanly contain a list of object files, but will also include the libA.so - which has no place being in the linker line in the same place as the object files?
So my question is how do I introduce the idea of a dependency between two libraries, without polluting the linker line with the value of the dependent library?
This statement is not correct, you do want the library to be referenced on the linker line in the same form as it is represented as a target - see my answer
I can of course just have -lA in the linker line for libB.so, just like you would for a 3rd party dependency - but this does not guarantee it will be built before it is referenced?
One thing I have noticed is that if I change $(RELEASE)/$$@
to just $$@
then it works:
g++ -fPIC -shared path/to/some_source.o libA.so -o libB.so
This is a problem as I need the output of both libraries in the $RELEASE directory, and I'm not convinced the libA.so
in the above linker line is ever correct?
It's becoming a bit of a mess - any advice?
Thanks
Upvotes: 2
Views: 747
Reputation: 642
The problem was my understanding of the linker command, and the moving of the output target as stated by @o11c in the comments under the original question.
Having libA.so on the linker line is fine.
I've added a subsequent cp command to copy the the $@ to $(RELEASE) so that targets are kept where make expects.
$1: $(call source-to-object,$2)
$(CXX) $(CXXFLAGS) -shared $$^ -o $$@ $(LDFLAGS) $(LDLIBS)
$(CP) $$@ $(RELEASE)
Upvotes: 0
Reputation: 111
You do already get the object files using the source-to-object
function. Can you not just use that instead of $$^
, or am I missing something here?
Upvotes: 1
Reputation: 171471
So my question is how do I introduce the idea of a dependency between two libraries, without polluting the linker line with the value of the dependent library?
You can specify an "order-only prerequisite" which means that the rule for creating libA.so must complete before creating libB.so:
libB.so : | libA.so
The difference from a normal prerequisite is that if libA.so is newer than libB.so then libB.so won't be re-built. When looking at the prerequisites for libB.so Make only cares if libA.so exists, not how old it is.
If that's not useful for you (because you want libB.so to be rebuilt when libA.so changes) then you can just filter it out of the prerequisites by using $(filter-out libA.so,$^)
Upvotes: 3