【问题标题】:Build a static library for c++ which is internally dependent on third-party libraries为c++构建一个内部依赖第三方库的静态库
【发布时间】:2019-02-22 06:30:18
【问题描述】:

我想在/home/my/library/libmyfoo.a 的位置创建一个库libmyfoo.a

我想以最简单的形式使用这个静态库,如下所示:

假设这是 myProgram.cpp

#include "AAA.h"

int main(void) {
    int x = 2;

    myFooFunction(x);

    return(0);
}

我想以g++ -std=c++11 -I/path/to/AAA.h myProgram.c -o myProgram -L/home/my/library/ -lmyfoo 运行它

现在: AAA.h(和AAA.cc)依赖于第三方框架/库,即gstreamerprotobufgrpc

/path/to/AAA.h 的层次结构是

Makefile
AAA.h
AAA.cc
AAA.o
BBB(Folder)
    BBB.cc
    BBB.h
    BBB.o

Makefile 有规则:

GOOGLEAPIS_GENS_PATH ?= $(HOME)/GOOGLE/googleapis/gens
GOOGLEAPIS_API_CCS = $(shell find $(GOOGLEAPIS_GENS_PATH)/google/api \
    -name '*.pb.cc')
GOOGLEAPIS_RPC_CCS = $(shell find $(GOOGLEAPIS_GENS_PATH)/google/rpc \
    -name '*.pb.cc')
GOOGLEAPIS_SPEECH_CCS = $(shell find \
    $(GOOGLEAPIS_GENS_PATH)/google/cloud/speech -name '*.pb.cc')
GOOGLEAPIS_LONGRUNNING_CCS = $(shell find \
    $(GOOGLEAPIS_GENS_PATH)/google/longrunning -name '*.pb.cc')
GOOGLEAPIS_CCS = $(GOOGLEAPIS_API_CCS) $(GOOGLEAPIS_RPC_CCS) \
    $(GOOGLEAPIS_LONGRUNNING_CCS) $(GOOGLEAPIS_SPEECH_CCS)


OBJS = ./BBB/BBB.o AAA.o

.PHONY: all
all: libmyfoo.a
libmyfoo.a: $(OBJS) $(GOOGLEAPIS_CCS:.cc=.o)
    ar rcs $@ $(OBJS) $(GOOGLEAPIS_CCS:.cc=.o)
    ranlib $@
    echo "build final executable......"

这会构建libmyfoo.a,其中包含大量*.o 文件。

问题:当我尝试运行如上所示的myProgram.cpp 时,它会抛出对很多东西的未定义引用。这意味着它没有正确链接。

正如我所说,现在AAA.ccBBB.cc 依赖于grpc、protobuf 和gstreamer。所以我将myProgram.cpp中的那些链接为

g++ -std=c++11 -I/path/to/AAA.h myProgram.c -o myProgram -L/home/my/library/ -lmyfoo -L/usr/lib -L/usr/lib64 -L/usr/local/lib64 -L/usr/local/lib -lgrpc++ -lgrpc -lgrpc++_reflection -lprotobuf -lpthread -lglib-2.0 -lgobject-2.0 -lgstreamer-1.0 -ldl -lboost_system -lboost_thread

而且这工作得非常好

有人能解释一下这是为什么吗? 也可以像前面提到的那样运行myProgram.cpp,即g++ -std=c++11 -I/path/to/AAA.h myProgram.c -o myProgram -L/home/my/library/ -lmyfoo

问候,

【问题讨论】:

    标签: c++ makefile g++ gnu static-linking


    【解决方案1】:

    当您使用的静态库依赖于共享库时,您需要将最终二进制文件显式链接到这些共享库。原因是静态库只是对象文件的集合,打包到“ar”存档中(这就是.a 文件。)没有存储有关共享库依赖项的信息。

    【讨论】:

    • 我明白了。正如您所说,共享库 (xyz.so) 将被显式链接。但是有没有办法让那些第三方(共享)库 - >静态?这甚至可能吗?
    • @RC0993 不可以。共享库不能转换为静态库。您需要构建所需库的静态版本。对于 gstreamer,这几乎是不可能的。我试过一次,但是你需要在你的代码中显式地实例化所有需要的插件,并且有数百个插件,具有非常复杂的依赖结构。我花了大约 5 天的时间不停地做这件事,最后放弃了。
    • 哦,这很有帮助。显然我正试图完成“几乎不可能”的事情:P。总之,您是否会说我发布的内容没有比这更好的了?
    • @RC0993 根据您的用例,如果您的目标是分发不需要外部媒体库的二进制文件,libvlc 可能是更好的选择。 GStreamer 很难与二进制包捆绑。对于我的一个项目,我从 gstreamer 切换到 libvlc。它也不能构建为静态库(它具有与 gstreamer 相同的插件问题),但捆绑其共享库更容易。
    • 我有一些限制,所以现在我会在这里坚持使用 gstreamer。但如果我有工作空间,我肯定会在接下来的项目中寻找libvlc。 :) 感谢您的所有帮助@NikosC
    猜你喜欢
    • 2021-08-27
    • 1970-01-01
    • 2018-10-19
    • 2011-04-01
    • 1970-01-01
    • 2012-09-19
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多