C++ 如何静态编译boost\u iostreams?

C++ 如何静态编译boost\u iostreams?,c++,boost,compilation,makefile,static-linking,C++,Boost,Compilation,Makefile,Static Linking,我不熟悉创建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 zonePar

我不熟悉创建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

在网上搜索之后,使用的正确参数似乎是:“-Wl,-Bstatic-lboost_iostreams-Wl,-Bdynamic”。有人能告诉我我做错了什么吗?

静态链接和动态链接之间缺少一个重要的区别。将应用程序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:大多数软件包(遗憾的是不是boost)将安装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是解决此问题的另一种工具。链接时,您使用名为libtool的包装器,而不是直接使用g++:

    $ libtool --mode=link gcc -static -o my_app -lboost_iostreams
    
    libtool将尝试添加必要的lib并将它们自动传递给gcc。它通过搜索与库同名的文件(在您的例子中是libboost_iostreams),但后缀为.la(而不是.a)来完成此操作。如果在文本编辑器中打开.la文件,您将看到它列出了libboost_iostreams的依赖项。我个人不喜欢libtool,它的设置有点棘手,而且越来越不被使用。我可能只需要查看.la文件并手动添加依赖项


  • 当我在libboost_iostreams上运行ldd时,它同意我需要libz和libbz2。但是当我添加'-lbz2-lz'时,我得到了这样一个结果:'/usr/bin/ld:cannot find-lbz2',我甚至尝试用'-L/usr/lib'指定要搜索的目录。请检查是否在/usr/lib中安装了libbz2.a。如果没有,您必须安装libbz2的静态版本。您可以从此处下载libbz2:解包后,使用文本编辑器打开解包文件夹中的“Makefile”,并将“PREFIX=/usr/local”行编辑为“PREFIX=/usr”。之后,导航到该文件夹并键入“make&&sudo make install”。您现在应该在系统上安装了libbz2的静态版本。在安装libbz2后,我在尝试执行操作时遇到以下错误:我自己刚刚尝试过它,并且“g++-static-o test main.cc-lboost_iostreams-lbz2-lz”对我来说很有用。请注意顺序也很重要。它必须按照依赖关系的顺序:因为libbz2依赖于libz,所以必须在-lbz2d之后指定-lz,而不要使用-Wl、-static和-Bdynamic。只需使用“-static”。还要记住依赖关系顺序,我在上面的评论中提到:“.o”文件就像静态库(事实上“.a”文件只是压缩的.o文件),因为zoneParser.o依赖于boost_iostreams,所以它必须排在列表的第一位,然后是boost_iostreams,然后是bz2…所以:“gcc-static-g-Wall-Wextra-o ZoneParserester zoneParser.o-lboost_iostreams-lbz2-lz”。应该是这样的!:-D