在ninja/cmake中操作独立目标的构建顺序

kgqe7b3p  于 5个月前  发布在  其他
关注(0)|答案(2)|浏览(73)

我正在一个用cmake+ninja构建的c++项目上工作,在一台64线程的计算机上有大约1200个构建目标。
有一个翻译单元需要10分钟来编译,大多数其他的翻译单元都非常快,这样所有其他目标的构建都需要(构建在所有线程上)只有大约9分钟。慢速翻译单元与其他单元相当独立,因此它不必被调度得很晚,但事实证明,默认情况下,这样一个完整的构建需要15到20分钟,最后只有一个线程完成了几乎所有其他目标。对我来说构建会更快,如果先安排慢翻译单元,阻塞一个线程大约10分钟,而所有其他线程都在项目的其余部分工作,整个项目在10分钟内构建。
在cmake或ninja中有没有一种方法可以改变调度的优先级,以指出慢的或“请早”的目标,而不会混淆依赖关系?

5cnsuln7

5cnsuln71#

截至2021年2月27日,答案是。GitHub上有一些未解决的问题(#232#376)和一个已放弃的PR(#1333)请求在基础版Ninja中使用此功能。CMake也没有提供任何方法来确定目标的优先级(至少到3.20为止)。
在这里,处理依赖关系(甚至是仅顺序依赖关系)没有任何帮助(你可能知道),因为这只会迫使较小的目标要么完全在长目标之前开始,要么完全在长目标之后开始。
我能想到的唯一解决办法(这不是一个很好的方法),就是把你的长目标分割成一个单独的ExternalProject,然后创建一个同时构建大目标和独立部分的超级构建。这需要大量的重构,而且对于很多项目来说都是不可能的。如果你因为这个问题而损失了很多开发时间,那么这可能是值得的。不过

plupiseo

plupiseo2#

截至2023年11月,答案是 * 理论上是否定的,实际上大部分是肯定的 *。
目前ninja有效地将独立目标按their address in memory排序,根据我的经验,这个地址最终是基于它们在build.ninja文件中的顺序,因为目标在文件中遇到时被分配,内存分配器倾向于在每次分配时返回一系列递增的地址(忽略干预释放的复杂性)。
类似地,cmake通常按照在处理CMakeLists.txt文件期间遇到的顺序将目标输出到ninja文件中。
因此,通过调整cmake文件中包含的库和源文件的顺序,我成功地控制了独立目标(C++项目中的独立模块和模块中的源文件)的编译顺序。
当然,这是不能保证的,它可能会改变,等等,但OTOH它可能是无害的,因为这些事情的顺序往往是任意的。

相关问题