我应该添加库的来源而不是链接到它们吗?


14

我是C ++的新手,所以我不确定如何最好地处理小的依赖项(例如,脚本语言或JSON / YAML / XML解析器)。

我应该创建单独的项目并将其链接为静态库,还是仅将.h / .cpp文件放入我的主项目有不利之处?

后者似乎容易得多,因为我花了几个小时来处理不兼容的库(构建库时编译器设置不同),但是我不想以错误的方式开始学习C ++。

如果最好将它们保留为单独的库,那么我该如何最好地保持编译标志同步,以便.lib / .a文件成功链接到我的应用程序?

(我目前正在使用MSVC 2015,但目标是使用XCode / clang在Mac OS X和iOS上进行编译,因此我必须处理至少3种不同类型的库(Win x86,Mac x64,ARM) )


5
凝视ABIss,他们会看着您
Basilevs

1
请记住,某些库旨在以这种方式使用。所述的SQLite库的优选的使用模式是被混合的源和头文件拖放到C或C ++应用程序的源树来编译成可执行。
马克·本宁菲尔德

Answers:


6

TLDR;

应该添加源吗?X
应该添加源吗?要看

这是为什么...

过去,即使是较小的项目,编译时间也是一个问题。编译您的源代码,而不必担心缓存编译器结果,绝对吸引了某些人。这是与您无关的库的一点。

另一个重要的是版本控制。您是否真的需要分别对每个库进行版本控制?对每个测试进行测试?分配给许多团队成员吗?如果您愿意的话,图书馆很棒,而且移动起来很方便,但是同样,您似乎也不在乎。

最后一点是,这是一个额外的开销,在您的情况下,删除源文件更加容易,这非常重要地表明了删除源文件而不是使用库。如您所知,一旦更改了单个编译器设置,就必须追逐所有依赖项。

我从经验中知道所有这些:

对于Swift项目,我肯定使用框架(库)并链接到它们,因为使用Xcode进行配置很容易。我也确实需要在那里进行版本控制,测试和解耦,所以这就是原因。

对于Mono(C#)项目,对于Unity,我从时髦的方法开始,将项目分解为库,对每个库进行编译和测试,这很棒……但是一旦我将库放到Unity中,就会发生各种问题(从Mono Unity使用的黑手版本)到代码在更改平台时表现出的有时不同的行为。这里没有一个IDE来管理所有库是一个真正的难题,因此将所有源代码放入Unity可以极大地提高生产力。

最后,与您最相关的是我从事的C ++游戏项目。仅在客户端上为该游戏编写了游戏引擎,网络实时客户端,网络HTTP客户端,AI和持久性存储。我选择了什么?CLion +库。即使我正在使用库,也感觉不到。所有源代码都在CLion IDE项目中,并且通过组成CMakeLists,我能够一次触发所有构建并将其链接。

总结一下,我想说使用库是一种面向未来的解决方案,如果不需要的话,也是过早的优化。据我所能确定的情况,如果您要有多个构建目标,那么从MSVC切换到Xcode将会很痛苦。所以,只要将它放在和保持尽可能多的隔离尽可能为当时候,你可能需要使用图书馆。

PS:这些天来,我在docker上也遇到类似的难题。我应该写作吗?我应该只在本地跑步吗?..等。还有Elixir,因为它允许您在同一应用程序中构建应用程序。我应该这样做吗?还是将应用程序分为所谓的微服务?...等。没有什么灵丹妙药,总要像YMMV那样衡量自己。


2

与C ++库的链接需要大量的麻烦,并且需要大量的知识和精力才能正确地做到这一点。这可能会使C ++学习者感到恐惧。


通常,特定C ++库的作者/维护者会牢记这一点,并会推荐其中一种方法。

换句话说,如果作者/维护者打算将库包含在头文件( * .h和.hpp)中,或包含源文件( .h *或.c),则它在自述文件中会说得很清楚。或文档。


设计和维护为跨平台的库(并与多个C ++编译器供应商和环境兼容)通常将具有一个makefile系统或一个生成配置系统(例如CMake)。这些系统用于生成可消除平台差异的标头填充,并用于生成脚本,这些脚本将使用正确的命令行选项和正确的顺序在源文件上调用编译器和链接器。根据平台和配置的不同,这些构建系统可能包括或排除某些标头或源文件,或者它们可能定义或取消定义某些预处理器符号。


可能会违反作者/维护者的建议,但这始终需要大量的移植工作。移植工作所需的工作量可以等同于移植到不同的C ++环境。


因为Visual C ++使用自己的基于项目描述文件的构建系统(部分基于XML),所以它与Linux下使用的基于脚本的构建系统完全不同。CMake使用的方法是让CMake进行配置设置,然后发出整个Visual C ++项目结构,并将配置选项烘焙到* .vcxproj文件中。

如果在C ++与Visual C ++链接期间出现问题,则可以使用Visual Studio GUI(使用其项目属性页对话框)修改* .vcxproj文件中的生成设置。假定您已完全理解许多重要的C ++编译和链接设置的含义和后果。

现在是使用Visual C ++的最愚蠢的部分:如果您使用的是许多不同的第三方库,则更改所有库的构建设置都意味着进入每个* .vcxproj文件,然后在GUI上重复相同的更改次。麻烦了,但是,如果您知道如何正确进行,就可以做到。

大多数Visual C ++学习者通过观察由其错误代码标识的Visual C ++编译器和链接器错误,以较难的方式学习这些设置。例如,可以查找LNK2005,其表面意思是“符号符号定义不止一次”,但应了解重复的定义并非源于粗心的编程错误,而是可能由于某些错误而发生了。编译选项和链接选项的冲突或误用。


为了提供一种针对您情况的更具体和有用的答案,您将需要知道您打算使用的库的名称,以及链接错误或遇到的其他困难。您可以在相应图书馆的讨论区中找到这些问题的现有答案。这些问题往往带有“链接问题”,“窗口”和“ Visual C ++”的标签。

可以针对此问题进行初学者到专家的指南,但是它将针对特定项目。不同项目选择的不同首选项将需要完全重写该指南。


如果使用CMake发出.vcxproj,而不是修改.vcxproj,则可以修改CMake配置
Caleth,

1

我会说是的,只要比较容易。有很多好处:

  1. 这将导致更快更好的代码,特别是如果您打开“链接时间优化”。

  2. 您的IDE会更喜欢它,例如,它(希望)使您可以跳到库代码的实现(.cpp),而不仅仅是接口(.h),这在处理文档不良的代码时(例如,大多数代码)。

  3. 它通常允许您将依赖项添加为git子模块,这是一个有点笨拙但实际上是获得依赖项的好方法(无论如何对于C ++,它几乎没有健全的构建系统)。它使更新库和测试不同版本变得非常容易。

  4. 例如,在使用2017时,您不必担心使用MSVC ++ 2013编译依赖项。还是共享与静态MSVCRT。

  5. 您可以轻松地在调试模式下构建并进入库。

我认为您希望这样做的唯一原因是,如果库很大且具有复杂的构建系统,并且您不想在其中复制,例如Boost或LLVM。但是对于简单的库来说,确实没有缺点。

例如,我在一些项目中使用libusb,并且需要支持Windows。libusb使用的是自动工具,它只是构建系统的一个笑话,无论如何在Windows上都无法正常工作。它们确实提供了预编译的二进制文件,但是它们是使用MSVC ++ 2013构建的,不能与2017一起使用。到目前为止,最简单的解决方案是将所有相关的.c和.h文件添加到我的项目中。


2
1)真的吗?静态库只是对象文件的集合,就像您刚刚编译它们一样。
Baldrickk

您可以为.o已编译-flto但不是真正的静态库的文件做档案-对于Clang,它们是LLVM位代码文件。如果您使用其他人提供的静态库,则显然不起作用。
Timmmm

好的,让我们升级这个讨论 -我期待学习更多的知识:)
Baldrickk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.