c# - 在 PInvoke 中管理大量 3rdparty 依赖项以获得更好的编译速度

标签 c# c++ visual-studio dependency-management

情况:

我正在从事一个研究项目,由于某些限制,该项目具有 C# 用户界面(主要用于可视化),但大部分处理是使用 PInvoke 和非托管 C++ 代码完成的。非托管代码对各种 3rdparty 库有大量依赖:Boost、PCL、OpenCV、CGAL、VTK、Eigen、FLANN、OpenMesh 等(如果你能说出它的名字,我们可能会依赖它!)。 C# 项目与 C++ 项目交互(从现在起我将其简称为“包装器”)。显然,包装器是使用所有 3rdparty 依赖项的地方,也是定义 PInvoke 入口点的地方。包装器被编译成 DLL 并通过生成后事件复制到 C# 项目的输出目录中。

我是该项目的唯一开发者。我的主要开发平台是 Windows 10 和 Visual Studio 2015,Git 是我的版本控制。我主要在 3 台不同的机器上开发,但有时我需要在其他只安装了 Visual Studio 2015 的机器上开发。

到目前为止我做了什么:

显然,管理所有这些 3rdparty 依赖项对一个人来说是一件麻烦事,而且我不愿意在新的开发机器上安装这些库。我所做的是将所有这些 3rdparty 库从源代码编译成静态 lib 文件(显然只有 header 文件除外)。所有源都为 Debug 配置构建一次,为 Release 配置构建一次。我花了一些时间将它们集成到我的包装器项目中(即定义额外的包含目录,使用大量 #pragma comment (lib, "blah.lib") 根据构建配置引用不同的构建, ETC。)。我还遵循了 Microsoft's linker best practices 中的一些建议, 以减少链接时间。具体来说,我使用的是增量链接器,我禁用了 /LTCG/OPT

现在我的 VS 解决方案中有这个巨大的“Dependencies”文件夹,大约 8GB,并且版本控制与项目分开(使用 Git 子模块)。包装器项目静态链接到所有这些,结果如上所述,在构建包装器项目后只生成一个 DLL。这种方法的好处是,在任何新的开发机器上,我克隆主存储库,克隆 Dependencies 子模块,然后我就可以开始了!但是……

最糟糕的部分:

你猜对了!糟糕的链接时间。即使在功能强大的计算机上,在我更改包装器项目中的一行之后,我也必须等待几分钟,直到链接器完成。当我采用上述方法时,我没有看到的是我忘记了我对快速原型(prototype)制作的重视程度:在将包装项目中的某些随机功能公开给 PInvoke 之前,对其进行快速和肮脏的测试。理想情况下,我希望能够更改包装器项目中的一些小内容,快速构建、运行和测试更改,然后继续将功能公开给 PInvoke。

我的问题:

很明显,我在这方面没有经验!我应该如何以不同的方式做事,特别是考虑到我上面提到的依赖关系?构建 DLL 而不是静态库更好吗?但是每次 C# 程序启动时,我都必须将依赖项添加到 PATH ( as mentioned here )。作为附带问题,您如何评价我目前的方法?

最佳答案

根据@silverscania 的评论,我决定只采用 DLL 路线。重建所有依赖关系有点痛苦,但我现在对结果非常满意。

现在,从头开始构建整个解决方案需要 36 秒!以前是4分钟左右,所以我没什么可提示的。此外,修改包装器项目中的单个文件并再次构建需要 3 秒,这真是太神奇了!事实上,所有编译的依赖项现在大约为 1 GB(相对于静态库的 ~8GB)是一个加号!我再高兴不过了。

注意事项:

  1. 在我进行大部分开发的主机上,我有一个 SanDisk SSD。我注意到,出于某种超出我理解的原因,与普通 HDD 相比,在该设备上构建项目的速度方式慢。我正在调查这个问题,但没有找到原因(TRIM 已启用且驱动器处于 AHCI 模式)。
  2. 我更多地摆弄了旗帜。我注意到编译器标志 /GL(全程序优化)在链接期间导致相当大的速度下降。我也禁用了该选项。

关于c# - 在 PInvoke 中管理大量 3rdparty 依赖项以获得更好的编译速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40305807/

相关文章:

c# - 使用 C# 将多行插入到 MS Sql Server

c# - 无法使用 asp.net mvc 3 获得事件模糊

c# - ASP.NET : Client-side validation, 服务器端操作

c++ - 在这种情况下,为什么 g++ 和 clang 会破坏 namespace 抽象?

c# - 在 C# (Visual Studio) 中折叠所有 #regions only(!)

visual-studio - 如何调试流畅的 API?

c++ - memcpy 和 _CrtlsValidHeapPointer(pUserData)

c# - 将两个查询合并为一个查询

c++ - SFINAE 检测类型是否被定义

c++ - 使用WIC(Windows镜像组件)时遇到的问题