与 Makefile 混淆似乎链接但我无法调用的库
Posted
技术标签:
【中文标题】与 Makefile 混淆似乎链接但我无法调用的库【英文标题】:Confusion with Makefile linking a library that seems to link but I can't call 【发布时间】:2017-05-07 01:07:59 【问题描述】:我正在尝试为使用 soplex 库(也依赖于 libz 和 libgmp)的项目构建一个 Makefile。 所以我有这个小Makefile:
SOPLEXPATH =../../lib/soplex-3.0.0/lib/
SOPLEXINCLUDE =../../lib/soplex-3.0.0/src/
SOPLEXDEP =../../lib/soplex-3.0.0/src/
CC = g++
CPPFLAGS = -g -std=c++0x -O3 -I $(SOPLEXINCLUDE)
#CPPFLAGS += -DNDEBUG
CPPFLAGS += -pg -ggdb
CPPFLAGS += -Wall -Werror=return-type
LIBS = -L $(SOPLEXPATH) -lz -lgmp -lsoplex
SRCS = $(wildcard ./src/core/*.cpp)
OBJS = $(addsuffix .o, $(basename $(SRCS)))
DEPS = $(addsuffix .d, $(basename $(SRCS)))
all : kea
kea : $(OBJS)
$(CC) $(CPPFLAGS) $(LIBS) -o bin/kea-core $(OBJS)
clean :
rm -f bin/kea-core $(OBJS) $(DEPS) *~
-include $(DEPS)
%.d: %.c
@$(CC) -MM -MT $(subst .d,.o,$@) -MT $@ $(CPPFLAGS) $< > $@
所有似乎都正确编译为目标文件(.o),但是链接器抱怨找不到函数soplex::SoPlex::SoPlex()
(SoPlex 的构造函数):
g++ -g -std=c++0x -O3 -I ../../lib/soplex-3.0.0/src/ -pg -ggdb -Wall -Werror=return-type -c -o src/core/ecircuit.o src/core/ecircuit.cpp
g++ -g -std=c++0x -O3 -I ../../lib/soplex-3.0.0/src/ -pg -ggdb -Wall -Werror=return-type -c -o src/core/solver_soplex.o src/core/solver_soplex.cpp
g++ -g -std=c++0x -O3 -I ../../lib/soplex-3.0.0/src/ -pg -ggdb -Wall -Werror=return-type -c -o src/core/main.o src/core/main.cpp
g++ -g -std=c++0x -O3 -I ../../lib/soplex-3.0.0/src/ -pg -ggdb -Wall -Werror=return-type -L ../../lib/soplex-3.0.0/lib/ -lz -lgmp -lsoplex -o bin/kea-core ./src/core/ecircuit.o ./src/core/solver_soplex.o ./src/core/main.o
./src/core/solver_soplex.o: In function `SolvSoplex::SolvSoplex(ECircuit&, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >&, SolvSoplex::Mode)':
/home/diego/Projects/kea-landscape-tool/src/core/solver_soplex.cpp:9: undefined reference to `soplex::SoPlex::SoPlex()'
/home/diego/Projects/kea-landscape-tool/src/core/solver_soplex.cpp:9: undefined reference to `soplex::SoPlex::~SoPlex()'
collect2: error: ld returned 1 exit status
Makefile:20: recipe for target 'kea' failed
make: *** [kea] Error 1
由于创建了所有 .o
文件,我尝试手动编译:
g++ -g -std=c++0x -O3 -I ../../lib/soplex-3.0.0/src/ -Wall -Werror=return-type -pg -ggdb -L/home/diego/Projects/kea-landscape-tool/../../lib/soplex-3.0.0/lib/ -lsoplex -lz -lgmp -o bin/kea-core src/core/main.o src/core/ecircuit.o src/core/solver_soplex.o
它失败并出现同样的错误。
然后我尝试像这样切换-L
和-l..
标志的位置,它编译为:g++ -g -std=c++0x -O3 -I ../../lib/soplex-3.0.0/src/ -Wall -Werror=return-type -pg -ggdb -o bin/kea-core src/core/main.o src/core/ecircuit.o src/core/solver_soplex.o -L/home/diego/Projects/kea-landscape-tool/../../lib/soplex-3.0.0/lib/ -lsoplex -lz -lgmp
见状,我尝试将Makefile中的规则改成如下:
kea : $(OBJS)
$(CC) $(CPPFLAGS) -o bin/kea-core $(OBJS) $(LIBS)
但它只是惨遭失败,在 soplex.cpp 内触发了大约 100 个错误(例如,它依赖于 -lgmp 和 -lz,但它找不到它们?粘贴在这里太长了)
我很困惑,知道如何解决这个问题吗? 谢谢。
【问题讨论】:
【参考方案1】:尝试将 $LIBS 放在命令的末尾。
改变这个:
LIBS = -L $(SOPLEXPATH) -lz -lgmp -lsoplex
进入这个:
LIBS = -L $(SOPLEXPATH) -lsoplex -lgmp -lz
如果 A 调用 B 中的函数,则始终需要将 B 放在 A 之后。至少使用静态库。
【讨论】:
谢谢!效果很好!你的解释很有道理。我还可以问:只有一个规则kea: $(OBJS)
和上面指定的 libs 有什么区别,和添加另一个规则 %.o : %.c
和 body $(CC) $(CPPFLAGS) $(LIBS) -o bin/kea-core $(OBJS)
有什么区别?我在其他地方看到过这种规则,但我不确定为什么要这样做。再次感谢! (现在我修复了 LIBS,两者似乎都可以工作,但不知道有什么区别)
%.o : %.c 规则告诉“make”如何将 C 源文件编译成目标文件。 Make 默认有这样的规则,所以你不需要给它,除非你需要在那里做一些特别的事情。请注意,默认规则在其编译规则中使用 C_FLAGS 或类似的东西,因此设置标志不是制定自定义规则的借口。我已经看到它用于确定目标文件的写入位置。以上是关于与 Makefile 混淆似乎链接但我无法调用的库的主要内容,如果未能解决你的问题,请参考以下文章