1

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

4

1 回答 1

3

您缺少静态链接和动态链接之间的重要区别。将应用程序 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 文件并手动添加依赖项。

于 2013-08-22T11:07:35.077 回答