草庐IT

c++ - 如何处理具有完全不同构建系统的第三方库?

coder 2023-05-30 原文

C++(和 C,尽管在那儿不太重要)标准规定程序中的所有翻译单元都需要具有相同的定义;这包括编译器开关之类的东西。例如,在 MSVC++ 上,必须链接到正确版本的 C 运行时库(/MT vs /MD vs /MTd vs /MDd) 在所有翻译单元中。

但是,我们想使用几个第三方依赖项,其中有几件事:

  • 他们都使用不同的构建系统(有一个 autoconf,有一个 cmake,还有一个似乎有它自己的手工制作的东西..)
  • 构建系统并非都在其配置中公开这些类型的开关,而且硬编码的开关在不同系统中的设置也不同。 (例如,一个库强制 /MD/MDd,而另一个库强制 /MT/MTd)

我们不确定处理这类事情的最佳方法是什么。我们讨论了以下选项:

  • 围绕任何第三方依赖项构建我们自己的构建系统。
    • 专业人士:我们知道一切都会匹配
    • 专业人士:我们知道我们可以以正确的方式提供跨平台支持
    • 缺点:我们不知道每个第三方构建系统的具体工作原理
    • CON:工作量很大
    • CON:如果第三方依赖发生变化则中断
  • 尝试使用第三方构建系统,并尝试修改它们来满足我们的需要。
    • 专业人士:似乎工作量更少
    • CON:我们可能会破坏第三方系统
    • CON:如果第三方依赖发生变化则中断
    • CON:迫使我们自己的构建变得非常复杂

我们不知道该怎么做;我们无法相信只有我们一个人遇到这些问题。我们应该选择上述选项之一,还是我没有想到的第三种选择?

最佳答案

严格来说,您并不需要所有库都链接到同一个运行时。假设它们是 DLL,那么只有当它们通过 DLL 边界传递 CRT 数据结构时才会出现问题。使用一个运行时在 DLL 中创建 FILE* 并从链接到另一个运行时的 DLL 中使用它会导致灾难。使用一个运行时从 DLL 调用 mallocnew,从另一个运行时调用 free/delete 会带来很多乐趣问题。

但只要所有与 CRT 相关的内容都保存在 DLL 内部,您就可以安全地链接到使用另一个 CRT 的 DLL。这也意味着您的调试版本可以使用与发布 CRT 链接的库。同样,只要您不尝试跨库混合 CRT 数据结构。

还要注意,大多数编译器标志不会影响 ABI,因此它们可以安全地在库(或文件)之间有所不同。改变 ABI 的通常是显而易见的,例如强制打包或堆栈对齐。

所以我们所做的基本上是这样的:

  • 我们尽可能自行构建库。在大多数情况下,这意味着我们可以通过相当简单的方式控制它应该链接到哪个运行时。这可能需要对构建系统进行少量调整,但通常只需指定是构建调试版本还是发布版本,大多数构建系统都有选择。 (如果库使用 Visual Studio 作为其构建系统,我们会尽可能将其升级到 2010)
  • 我们使用图书馆自己的构建系统。其他任何事情都只是痛苦的秘诀。您希望能够相信构建系统实际上与库源代码保持同步,而确保这一点的最简单方法是使用源代码附带的构建系统。
  • 如果构建库不可行,我们就按原样使用它,然后我们只需分发它所链接的任何运行时。我们会尽量避免这种情况,但在没有其他选择的情况下这样做是足够安全的。
  • 当我们构建一个库时,我们准确地在我们的内部 wiki 上记录它是如何完成的。如果我们必须升级到更新版本的库或重建它,这将是一个巨大的帮助。

我们目前依赖于三种不同的 VS 运行时(2005、2008 和 2010),处理起来很麻烦,但它工作。对于其中一两个,我们总是使用发布版本,即使在我们自己的代码的调试版本中也是如此。

维护起来有点麻烦,但它工作。而且我真的找不到更好的方法。

当然,你应该尽量减少你有多少第三方依赖,当你选择第三方库时,它的构建系统绝对应该是一个考虑因素。有些人比其他人更痛苦

但最终,您可能最终不得不使用一些没有良好构建系统的库,或者构建起来非常痛苦以至于不值得努力,或者在哪里您无法创建库的调试版本。然后拿走你能得到的。让它使用它喜欢使用的任何运行时。

关于c++ - 如何处理具有完全不同构建系统的第三方库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10854544/

有关c++ - 如何处理具有完全不同构建系统的第三方库?的更多相关文章

  1. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  2. ruby - 完全离线安装RVM - 2

    我打算为ruby​​脚本创建一个安装程序,但我希望能够确保机器安装了RVM。有没有一种方法可以完全离线安装RVM并且不引人注目(通过不引人注目,就像创建一个可以做所有事情的脚本而不是要求用户向他们的bash_profile或bashrc添加一些东西)我不是要脚本本身,只是一个关于如何走这条路的快速指针(如果可能的话)。我们还研究了这个很有帮助的问题:RVM-isthereawayforsimpleofflineinstall?但有点误导,因为答案只向我们展示了如何离线在RVM中安装ruby。我们需要能够离线安装RVM本身,并查看脚本https://raw.github.com/wayn

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  5. ruby-on-rails - Rails 3.1 中具有相同形式的多个模型? - 2

    我正在使用Rails3.1并在一个论坛上工作。我有一个名为Topic的模型,每个模型都有许多Post。当用户创建新主题时,他们也应该创建第一个Post。但是,我不确定如何以相同的形式执行此操作。这是我的代码:classTopic:destroyaccepts_nested_attributes_for:postsvalidates_presence_of:titleendclassPost...但这似乎不起作用。有什么想法吗?谢谢! 最佳答案 @Pablo的回答似乎有你需要的一切。但更具体地说...首先改变你View中的这一行对此#

  6. ruby - 在 Ruby 中构建长字符串的简洁方法 - 2

    在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo

  7. 电脑0x0000001A蓝屏错误怎么U盘重装系统教学 - 2

      电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。  准备工作:  1、U盘一个(尽量使用8G以上的U盘)。  2、一台正常联网可使用的电脑。  3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。  4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。  U盘启动盘制作步骤:  注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注

  8. 【鸿蒙应用开发系列】- 获取系统设备信息以及版本API兼容调用方式 - 2

    在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList​()Obt

  9. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  10. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

随机推荐