我是创建Makefile的新手。我可以在使用动态链接时成功编译我的程序,但在尝试静态编译时,我得到“未定义的引用”错误。
CC=g++
CXXFLAGS= -g -Wall -Wextra
#LDFLAGS= -g -l boost_iostreams #this works for dynamic linking
LDFLAGS= -Wl,-Bstatic -lboost_iostreams -Wl,-Bdynamic
default: zoneParserTester
zoneParser:
$(CC) $(CXXFLAGS) $(LDFLAGS) $@.cpp
zoneParserTester: zoneParser.o
$(CC) $(CXXFLAGS) $(LDFLAGS) zoneParser.o -o $@ $@.cpp
gzExample:
$(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ $@.cpp
在网上搜索之后,似乎使用的正确参数是:“ - WI,-Bstatic -lboost_iostreams -Wl,-Bdynamic”。谁能告诉我我做错了什么?
答案 0 :(得分:2)
您缺少静态和动态链接之间的重要区别。将应用程序A动态链接到库B将在运行时引入库B 的所有依赖项,而无需明确指定它们。静态链接应用程序时,还需要在链接时包含库B的所有依赖项(以及依赖项的依赖项等),其顺序与依赖项链相同(因此,如果应用程序A依赖于库B,库B依赖于库C,您必须按顺序指定库;对于.o文件也是如此。
要弄清楚特定库的整个依赖链(及其顺序)可能有点麻烦。有时链接期间的错误消息可以为您提供一些提示。如果这没有帮助,还有其他几种方法:
做出明智的猜测:猜测libboost_iostreams所依赖的一种方法是查看库的动态版本所依赖的内容。您可以使用ldd工具执行此操作:
$ ldd /usr/lib/libboost_iostreams.so.1.46.1
在我的电脑上,它取决于libz和libbz2。所以我非常确定如果您添加
,您的应用程序将会链接-lbz2 -lz
到您链接应用程序的行。我不确定-Wl,-Bstatic是否必要。对我来说,只需指定-static即可:
$ gcc -static -o test test.cpp -lboost_iostreams -lbz2 -lz
使用pkg-config:大多数软件包(遗憾的是不提升)将安装pkg-config文件,这些文件会跟踪您必须如何链接程序以使用特定库。例如,假设你想静态链接到libcairo:
$ pkg-config --static --libs cairo
-pthread -lcairo -lgobject-2.0 -lffi -lpixman-1 -lfontconfig -lexpat -lfreetype -lpng12 -lz -lm -lxcb-shm -lxcb-render -lXrender -lglib-2.0 -lrt -lpcre -lX11 -lpthread -lxcb -lXau -lXdmcp
使用.la文件和libtool:这是一种有点弃用的方法,并且越来越不再使用,因此.la文件的可用性将取决于您的发行版。 libtool是另一个解决这个问题的工具。链接时,不使用直接使用g ++,而是使用名为libtool的包装器:
$ libtool --mode=link gcc -static -o my_app -lboost_iostreams
libtool将尝试添加必要的库并自动将它们传递给gcc。它通过搜索与库名称相同的文件(在您的情况下为libboost_iostreams),但使用后缀.la(而不是.a)来完成此操作。如果在文本编辑器中打开.la文件,您将看到它列出了libboost_iostreams的依赖项。我个人不喜欢libtool,设置起来有点棘手,而且越来越不再使用了。我可能只是查看.la文件并手动添加依赖项。