在PInvoke中管理大量的第三方依赖关系,以提高编译速度
本文关键字:高编译 速度 编译 关系 管理 PInvoke 依赖 第三方 | 更新日期: 2023-09-27 18:15:20
情况:
我正在做一个研究项目,由于一些限制,该项目有一个C#用户界面(主要用于可视化(,但大部分处理都使用PInvoke和非托管C++代码。非托管代码对各种第三方库有很多依赖:Boost、PCL、OpenCV、CGAL、VTK、Eigen、FLANN、OpenMesh等(如果你能说出它的名字,我们可能会依赖它!(。C#项目与C++项目交互(从现在起,我只是将其称为"包装器"(。显然,包装器是消耗所有第三方依赖关系的地方,也是定义PInvoke入口点的地方。包装器被编译成DLL,并通过构建后事件复制到C#项目的输出目录中。
我是这个项目的唯一开发商。我的主要开发平台是带有Visual Studio 2015的Windows 10,Git是我的版本控制。我主要在3台不同的机器上开发,但有时我需要在其他只安装了Visual Studio 2015的机器上进行开发。
到目前为止我所做的:
令人费解的是,管理所有这些第三方依赖关系对一个人来说是一件麻烦事,我不想不得不在新的开发机器上安装这些库。我所做的是,我已经将所有这些第三方库从源代码编译成了静态lib文件(显然除了只有头的文件(。对于Debug
配置,所有源都构建一次,对于Release
配置,构建一次。我花了一些时间将它们集成到我的包装器项目中(即定义额外的include目录,使用大量#pragma comment (lib, "blah.lib")
,根据构建配置引用不同的构建,等等(。我还遵循了微软链接器最佳实践中的一些建议,以减少链接时间。具体来说,我使用的是增量链接器,我禁用了/LTCG
和/OPT
。
现在,我的VS解决方案中有一个巨大的"Dependencies"文件夹,大约8GB,并且与项目分开进行版本控制(使用Git子模块(。包装器项目静态链接到所有这些,因此,如上所述,在构建包装器项目后只生成一个DLL。这种方法的好处是,在任何新的开发机器上,我都可以克隆主存储库,克隆依赖项子模块,然后就可以开始了!但是
最糟糕的部分:
你已经猜到了!可怕的链接时间。即使在功能强大的计算机上,在我更改包装器项目中的一行之后,我也必须坐上几分钟,直到链接器完成。当我采取上述方法时,我没有看到的是,我忘记了我有多重视快速原型设计:在将该功能暴露给PInvoke之前,对包装器项目中的一些随机功能进行快速而肮脏的测试。理想情况下,我希望能够更改包装器项目中的一些小东西,快速构建、运行和测试这些更改,并继续向PInvoke公开该功能。
我的问题:
很明显,我在这方面缺乏经验!我应该如何做不同的事情,特别是考虑到我上面提到的依赖性?构建DLL而不是静态库更好吗?但是,每次C#程序启动时,我都必须将依赖项添加到PATH中(如上所述(。作为一个附带问题,你如何评价我目前的做法?
根据@silverscania的评论,我决定只走DLL路线。重建所有的依赖关系有点痛苦,但我现在对结果非常满意。
现在,从头开始构建整个解决方案需要36秒!以前是4分钟左右,所以我没有什么可抱怨的。此外,在包装器项目中修改一个文件并再次构建需要3秒,这太神奇了!事实上,所有编译的依赖项现在都大约是1GB(而静态库的依赖项大约是8GB(,这是一个优势!我再高兴不过了。
一连串的音符:
- 在我进行大部分开发的主机上,我有一个闪迪SSD。我注意到,由于一些我无法理解的原因,在该设备上构建项目的速度比普通HDD慢。我正在调查这个问题,但还没有找到原因(TRIM已启用,驱动器处于AHCI模式(
- 我又玩了一会儿旗帜。我注意到编译器标志
/GL
(全程序优化(在链接过程中导致了相当大的速度减慢。我也禁用了该选项