【问题标题】:How do I statically compile boost_iostreams?如何静态编译 boost_iostreams?
【发布时间】:2013-08-22 07:08:17
【问题描述】:

我是创建 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”。谁能告诉我我做错了什么?

【问题讨论】:

    标签: c++ boost compilation makefile static-linking


    【解决方案1】:

    您忽略了静态链接和动态链接之间的重要区别。将您的应用程序 A 动态链接到库 B 将引入库 B 在运行时所有依赖项,而无需显式指定它们。当静态链接您的应用程序时,您还需要在链接时以与依赖项链相同的顺序包含库 B 的 所有依赖项(以及依赖项的依赖项等)(因此,如果应用程序A 依赖于库 B,而库 B 依赖于库 C,您必须按顺序指定库;对于 .o 文件也是如此)。

    要弄清楚特定库的整个依赖链(及其顺序)可能有点麻烦。有时,链接过程中的错误消息可以为您提供一些提示。如果这没有帮助,还有其他几种方法:

    1. 做出明智的猜测:猜测 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
      
    2. 使用 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 
      
    3. 使用 .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 文件并手动添加依赖项。

    【讨论】:

    • 当我在 libboost_iostreams 上运行 ldd 时,它同意我需要 libz 和 libbz2。但是,当我添加“-lbz2 -lz”时,我得到这个:“/usr/bin/ld: 找不到 -lbz2”我什至尝试使用“-L /usr/lib”指定要搜索的目录,但没有成功。
    • 检查是否在 /usr/lib 中安装了 libbz2.a。如果没有,您必须安装 libbz2 的静态版本。你可以从这里下载libbz2:link解压后,用文本编辑器打开解压后的文件夹中的“Makefile”,将“PREFIX=/usr/local”这一行编辑为“PREFIX=/usr”。之后,导航到文件夹并输入“make && sudo make install”。您现在应该在系统上安装了静态版本的 libbz2。
    • 安装 libbz2 后,我在尝试制作时收到以下错误:pastebin.com/d1AQ0rtu
    • 我自己试过了,“g++ -static -o test main.cc -lboost_iostreams -lbz2 -lz”对我有用。请注意,顺序也很重要。必须按依赖顺序:因为libbz2依赖于libz,所以必须在-lbz2之后指定-lz
    • 不要使用 -Wl,-static 和 -Bdynamic。只需使用“-static”。还要记住依赖顺序,我在上面的评论中提到:“.o”文件就像静态库(实际上“.a”文件只是压缩的.o文件),并且因为 zoneParser.o 依赖于 boost_iostreams 它必须来列表中的第一个,然后是 boost_iostreams,然后是 bz2... 所以:“gcc -static -g -Wall -Wextra -o zoneParserTester zoneParser.o -lboost_iostreams -lbz2 -lz”。应该是这样! :-D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 2021-11-23
    • 1970-01-01
    相关资源
    最近更新 更多