相同C库

时间:2017-11-20 14:10:57

标签: c linux gcc makefile shared-libraries

背景

我正在使用一个用于与我们产品接口的大型C库。我们最初只有一个产品coconut,它使用了libfruit.so以及libfruit的所有相关API头文件。头文件本身不使用相对路径包含,而是使用项目根包含。例如,考虑这两个实际标题:

${LIBFRUIT_BASE}/headers/Include/fruit/framework/beta/base.h
${LIBFRUIT_BASE}/headers/Include/fruit/framework/beta/coconut.h

coconut.h文件中,它包含base.h via:

#include "Include/fruit/framework/beta/base.h"

通过设置CFLAGS+= -I ${LIBFRUIT_BASE}/headers之类的内容来实现此目的。针对libfruit构建的外部程序类似地设置路径标志以解析标题。

问题

在构建libfruit时,以及在构建依赖于libfruit的程序时,这很有效,但现在我们遇到了一个大问题:

  1. 我们希望支持其他产品pineapple
  2. libfruit的开发人员决定分叉libfruit,以便每种产品都有不同的版本。
  3. 处理两个库非常简单,因为我们现在有一个libfruit_coconut.so(重命名为libfruit.so)和一个libfruit_pineapple.so。从名称冲突的两个库中删除全局导出的符号后,库正在运行。但是,仍然存在一个更大的问题:libfruit_coconutlibfruit_pineapple的公开导出标题发生冲突,即:

    libfruit_coconut

    ~/projects/myapp/dependencies/headers/Include/fruit/framework/beta/base.h
    ~/projects/myapp/dependencies/headers/Include/fruit/framework/beta/coconut.h
    

    libfruit_pineapple

    ~/projects/myapp/dependencies/headers/Include/fruit/framework/beta/base.h
    ~/projects/myapp/dependencies/headers/Include/fruit/framework/beta/pineapple.h
    

    这就是一切都崩溃了:我必须使用两个版本的几乎相同的库,并且base.h会被覆盖,具体取决于我首先复制的两个依赖项中的哪一个。我做的第一步是在构建环境中将每个库移动到它自己的不同子目录中:

    ~/projects/myapp/dependencies/libfruit_coconut/headers/Include/fruit/framework/beta/base.h
    ~/projects/myapp/dependencies/libfruit_coconut/headers/Include/fruit/framework/beta/coconut.h
    ~/projects/myapp/dependencies/libfruit_pineapple/headers/Include/fruit/framework/beta/base.h
    ~/projects/myapp/dependencies/libfruit_pineapple/headers/Include/fruit/framework/beta/pineapple.h
    

    这并没有完全解决我的问题:两个库提供的标头不使用相对包含路径,并且库标头抱怨无法从同一个库中找到其他标头,除非我设置了包含路径对于两个标题集,即:

    CFLAGS += -I~/projects/myapp/dependencies/libfruit_coconut   \
              -I~/projects/myapp/dependencies/libfruit_pineapple
    

    这似乎有效地使项目无法在不确定性地解析标题的情况下同时使用这两个库。

    问题

    假设我无法更改libfruit库,其标题等;是否有任何理智的方式以某种方式在一个项目中同时使用两个库?问题的中心似乎是库标题本身如何相互引用。或者我是不是强迫库开发人员为其API标头使用相对包含路径,或在所有标头中插入libfruit_${VARIANT_NAME}

1 个答案:

答案 0 :(得分:1)

鉴于您无法更改现有库或标头,您要求的唯一方法是为每个现有库/标头创建一个单独的新包装器库,并在每个共享库项目中, wrap typedef 所有现有符号(可能存在冲突)与唯一前缀标识符,例如pin_coc_(适用于菠萝,椰子)分别)。原始标头中存在的路径可以替换为包装器标头中原始位置的符号链接,以减轻标头问题。这种方法应该消除所有冲突。然后,您可以构建(并提供)包含原始子库集合的所有功能的单个共享库。

使用这种方法,虽然公认的蛮力并不理想,但却为在某种整体设计或项目管理之外开发的应用程序(或库)中的功能扩展提供了灵活的方法。