【问题标题】:MSBuild C++ link-time dependenciesMSBuild C++ 链接时依赖项
【发布时间】:2015-03-06 07:40:46
【问题描述】:

我想在以下场景中增加使用 MSBuild 构建的并行度:

共有三个 C++ 项目(目标)。第一个是名为A 的静态库,第二个是名为B 的动态库,它依赖于A,第三个是一个可执行的C,它依赖于B。所有的项目都包含简单的源代码,没有头文件生成或其他恶作剧。

此配置中没有任何内容可以阻止所有翻译单元并行编译,因为唯一真正的依赖关系是在链接时。但是,在 MSBuild 中设置引用和依赖项的标准方法会强制所有 A 在它开始在 B 中构建任何东西之前构建,等等。这不必要地序列化了一些构建过程。

项目和通用解决方案需要对“普通”开发人员保持平易近人,这意味着维护项目和构建设置应该完全在 Visual Studio UI 中实现(新库和可执行文件可能依赖于预先存在的属性表,但应该不需要手动编辑新项目的 .vcxproj 文件,也不需要手动编写 MSBuild XML 文件。

我目前的想法是将所有代码从BC 移动到单独的静态库中,称为B'C'。然后B 将依赖于AB',允许它们并行编译。同样,C 最终依赖于AB'C',它们都可以并行编译。正如预期的那样,唯一剩下的串行过程将是链接器步骤。尽管这不会是世界末日,但这比我想要的要麻烦和不习惯。

我真的很希望能够为项目的链接步骤创建依赖项,而这些依赖项也不能作为项目编译步骤的依赖项。在我熟悉的大多数其他构建系统中,即使不是隐含的,这也是微不足道的。考虑到 Visual Studio 的易用性要求,是否可以在 MSBuild for C++ 项目中使用;如果有,怎么做?

【问题讨论】:

    标签: visual-studio msbuild linker


    【解决方案1】:

    我找到了一个不太理想的轮询解决方法,但它很有效而且很简单。在实施后的短短几分钟内,就能够将完全重建从约 17 秒降至约 14 秒,并有望进一步降低。一旦我用得更多,就会更新。

    首先删除项目之间的依赖关系,以便它们都同时构建。这将导致我们将手动修复的构建竞争条件。在项目 B 的 vcxproj 底部(对于 C 到 B 也是如此)放置:

    <Target Name="WaitForA" BeforeTargets="Link">
      <Exec Command="$(SolutionDir)Build\A.bat $(OutputPath)A.lib"/>
    </Target>
    

    目标只运行一次,这很好,但要确保名称是唯一的。 WaitFor.bat 是只运行 powershell 的 bat:

    param([string] $file)
    
    $sleeps = 0
    while($true)
    {
        try
        {
            $lock = [System.IO.File]::Open($file,'Open','ReadWrite','None');
            $lock.dispose();
            break;
        }
        catch
        {
            $sleeps = $sleeps + 1
            Start-Sleep -m 100
        }
    }
    
    Write-Host ("Slept {0} times waiting for '{1}'" -f $sleeps,$file)
    

    【讨论】:

    • 这种方法适用于完全重建的情况,但在进行部分构建、非并行构建以及出现错误时会出现许多问题。努力寻找解决这些问题的方法。至少说明了构建性能提高的可能性。
    • 对这个答案不太满意,所以最终使用 LoadLibrary 和 GetProcAddress 延迟加载所有依赖项。这允许事物并行构建
    【解决方案2】:

    他们最简单的方法是将您的三个项目放入一个 Visual Studio 解决方案文件(即 *.sln)中。我知道它很难看,而且解决方案文件不是真正的 msbuild 文件。为了使其工作,您还必须使用 Visual Studio 工具指定项目依赖项。 (即右键单击解决方案,选择“项目依赖项...”)

    一旦你这样做了,在 Visual Studio 内部,它应该为所有项目并行执行编译步骤,然后以正确的顺序链接它们。

    在命令行上,要达到相同的效果,您必须将 -m 传递给 msbuild.exe 以及解决方案文件的名称。

    这也假设您在所有项目文件中也指定了 -MP。

    【讨论】:

    • 我不完全确定我在关注;我确实有一个 .sln 文件中的所有项目,并且它们没有完全并行构建。你是说我只需要使用项目依赖项而不是链接引用吗?
    猜你喜欢
    • 2011-03-29
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 1970-01-01
    相关资源
    最近更新 更多