g++/clang++中参数的顺序与makefile

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

本文关键字:顺序 makefile 参数 clang++ g++      更新时间:2023-10-16

我在Ubuntu 12.04上使用CERN的ROOT时偶然发现了这个非常恼人的问题,但我认为这是一个更普遍的问题。

我有一些带有外部引用的c++代码,我使用下面的makefile编译和链接。在我的Mac OS X 10.8和SL5服务器上,这工作得很好。

CXX=clang++
CXXFLAGS=-Wall -O2 -g $(shell root-config --cflags --libs)
testroot: testroot.cc

计算结果为

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

这给了我未定义的引用和Ubuntu服务器上的链接错误。我已经尝试在LDFLAGS中设置lib,但它产生相同的结果。当我手动编译它并将源文件和-o选项放在库之前时,它可以正常编译。

从其他线程,我认为命令的顺序可能很重要,但我想知道为什么它在一些机器上,而在其他机器上没有。即使顺序很重要,我认为make足够聪明,可以自己弄清楚。

现在的问题是:我怎样才能绕过这个?我必须使用不同版本的make或old吗?我必须修改我的makefile吗?

提前感谢!

不应该给LDFLAGS添加-l参数(甚至不应该提到CXXFLAGS)。对于像makefile中那样的隐式make规则,链接库的适当变量是LDLIBS

在某些机器上,顺序无关紧要,因为在GNU中,它只对静态库或启用了--as-needed选项(在某些系统上默认启用)有影响。

您不应该将root-config的选项组合。它应该是:

CXXFLAGS = -Wall -O2 -g $(shell root-config --cflags)
LIBS     = $(shell root-config -libs -glibs)

然后在适当的地方使用这些选项。(例如,你在编译时不使用$(LIBS),而不是链接。)

至于为什么它在不同的系统上工作?不同的系统有不同的链接器,工作方式也不同。或者有些程序不需要额外的库虽然这绝对是违反传统的,这在现代系统中并不一定是不合理的一切在libc.so

最后:make是怎么弄明白这些的?使完全不知道您执行的命令;他们就是传递给shell的字符串

您遇到的问题与用于解决外部引用的算法有关。您可以尝试不同的方法,但是重新排序库列表也会有所帮助。把基本库放在第一位(没有依赖关系的那个),然后是依赖于已经列出的库的库,依此类推。