【发布时间】:2017-11-20 14:10:56
【问题描述】:
背景
我正在使用一个庞大的 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 的程序时很有效,但现在我们遇到了一个大问题:
- 我们希望支持另一个产品,
pineapple。 -
libfruit的开发人员决定分叉libfruit,以便为每个产品提供不同的版本。
处理两个库很容易,因为我们现在有一个libfruit_coconut.so(重命名为libfruit.so)和一个libfruit_pineapple.so。从具有名称冲突的两个库中删除全局导出符号后,这些库正在工作。但是,还有一个更大的问题:libfruit_coconut 和 libfruit_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
但这并没有完全解决我的问题:两个库提供的头文件不使用相对包含路径,并且库头文件抱怨无法从同一个库中找到其他头文件,除非我设置了包含路径对于 both 组标题,即:
CFLAGS += -I~/projects/myapp/dependencies/libfruit_coconut \
-I~/projects/myapp/dependencies/libfruit_pineapple
这似乎有效地使项目无法同时利用两个库,而没有不确定地解析标头。
问题
假设我无法更改任何一个 libfruit 库、它们的标头等;有什么理智的方法可以在一个项目中同时使用这两个库吗?我的问题的中心似乎是库标题本身如何相互引用。还是我坚持强迫库开发人员为其 API 标头使用相对包含路径,或者在所有标头中插入 libfruit_${VARIANT_NAME}?
【问题讨论】:
-
一种非常有用的方法是要求项目负责人提交用于项目请求的每个库,然后为特定库的所有符号使用唯一的短(例如 3 个字符)前缀以被出口。这几乎可以保证库之间不会发生冲突。例如
coc_func1()代表椰子。pin_func1()菠萝。 -
“假设我无法更改任何一个 libfruit 库、它们的标头等” 当您需要添加
libfruit_orange时,这似乎很麻烦。为什么不为每个单独的水果提供一个基础库和附加库?
标签: c linux gcc makefile shared-libraries