Reputation: 1577
I stumbled upon this very annoying problem while working with CERN's ROOT on Ubuntu 12.04 but I think it's a more general problem.
I have some C++ code with external references that I compile and link using the following makefile. On my Mac with OS X 10.8 and a sever with SL5 this works fine.
CXX=clang++
CXXFLAGS=-Wall -O2 -g $(shell root-config --cflags --libs)
testroot: testroot.cc
It evaluates to
clang++ -Wall -O2 -g -pthread -m64 -I/opt/ROOT/5.34.05/include/root -L/opt/ROOT/5.34.05/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic testroot.cc -o testroot
Which gives me undefined references and a linker error on the Ubuntu server. I have already tried setting the libs in LDFLAGS
but it produces the same result. When I compile it manually and put the source file and the -o option before the libraries, it compiles without a problem.
From other threads, I figured that the order of the commands can matter but I wonder why it does on some machines and it doesn't on others. Even if the order mattered, I thought make
was smart enough to figure it out for itself.
The questions now are: How can I get around this? Do I have to use a different version of make or ld? Do I have to modify my makefile?
Thanks in advance!
Upvotes: 3
Views: 1325
Reputation: 153909
You shouldn't combine the options of root-config
. It should
be:
CXXFLAGS = -Wall -O2 -g $(shell root-config --cflags)
LIBS = $(shell root-config -libs -glibs)
You then use these options where appropriate. (For example, you
wouldn't use $(LIBS)
when just compiling, and not linking.)
As for why it works on a different system? Different systems
have different linkers, which work differently. Or perhaps
there are no additional libs needed for some
system—although it very definitely goes against tradition,
it's not necessarily unreasonable on a modern system to put
everything in libc.so
.
Finally: how could make
figure any of this out. Make
literally knows nothing of the commands you execute; they're
just strings which it passes to the shell.
Upvotes: 2
Reputation: 344
The problem you experience relates to the algorithm ld uses to resolve the external references. You could try different ld, but reordering the list of libraries can just as well help. Put the base libraries first (the once that have no dependencies), then libraries that depend on already listed libraries and so on.
Upvotes: 0
Reputation: 25693
You should not add -l
arguments to LDFLAGS
(not even mentioning CXXFLAGS
). The proper variable for link libraries is LDLIBS
in the case of implicit make rules like in your makefile.
On some machines the order doesn't matter because with GNU ld it matters only for static libraries or with the --as-needed
option enabled (which is enabled by default on some systmes).
Upvotes: 5