Kevin Dungs
Kevin Dungs

Reputation: 1577

Order of parameters in g++/clang++ with makefile

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

Answers (3)

James Kanze
James Kanze

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

user2038893
user2038893

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

wRAR
wRAR

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

Related Questions