【问题标题】:Custom common target to build a solution自定义通用目标以构建解决方案
【发布时间】:2010-08-03 14:25:15
【问题描述】:

我创建了一个自定义通用目标“RealClean”,它删除了输出和“中间输出”目录中的每个文件。我把它放在 Microsoft.Common.targets 文件中。 当我在我的 csproj 上运行 MsBuild 时,一切都很好。 但是当我在我的 sln 上运行 MsBuild(它只引用了一个 csproj 列表)我有以下错误

error MSB4057: The target "RealClean" does not exist in the project.

这是我输入运行 MsBuild 的命令行

C:\Windows\Microsoft .NET\Framework\v3.5\MsBuild.exe /p:Configuration="Release";OutputPath="..\..\MSBuild.Referentiel.net35";nowarn="1591,1573" /t:RealClean mySolution.sln

有什么提示吗?

【问题讨论】:

    标签: msbuild projects-and-solutions target


    【解决方案1】:

    我遇到了同样的问题,但不想修改源代码树之外的内容以使其正常工作。将文件添加到 C:\Program Files... 意味着您必须在每台开发机器上手动执行此操作才能获得相同的行为。

    我做了三件事:

    1) 创建了一个自定义目标文件,我通过将以下内容添加到每个 proj 文件中,将其导入到我的解决方案中的每个 C# 和/或 VB/F# 项目中:

    <!-- Rest of project file -->
    
    <PropertyGroup Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">
        <!-- Relative path to containing solution folder -->
        <SolutionDir>..\</SolutionDir>
    </PropertyGroup>
    <Import Project="$(SolutionDir)CommonSettings.targets" />
    

    2) 添加了一个在真正的 Clean 之后调用的 clean 目标(使用 MSBuild 4.0 中的 AfterTargets 属性):

    <Target Name="CleanCs" AfterTargets="Clean">
        <Message Text="Deep cleaning C# project..." />
        <CreateItem Include="$(OutDir)**\*.*; $(ProjectDir)\obj\**\*.*; $(IntermediateOutputPath)**\*.*"
                                Exclude="**\bin\**\*.vshost.exe; $(IntermediateOutputPath)**\*.log">
            <Output TaskParameter="Include" ItemName="AfterClean_FilesToDelete"/>
        </CreateItem>
        <Delete Files="@(AfterClean_FilesToDelete)" />
        <CreateItem Include="$(ProjectDir)\obj\" >
            <Output TaskParameter="Include" ItemName="AfterClean_DirectoriesToDelete" />
        </CreateItem>
        <CreateItem Include ="$(ProjectDir)\bin\" Condition="'$(TargetExt)' != '.exe'" >
            <Output TaskParameter="Include" ItemName="AfterClean_DirectoriesToDelete"/>
        </CreateItem>
        <RemoveDir ContinueOnError="true" Directories="@(AfterClean_DirectoriesToDelete)" />
    </Target>
    

    3) 在我的持续集成 MSBuild 项目中,我检查并确保所有 proj 文件都有 #1:

    <ItemGroup>
        <!-- Exclude viewer acceptance tests as they must compile as x86 -->
        <CheckProjects_CsProjects Include="**\*.csproj" />
    </ItemGroup>
    <Target Name="CheckProjects">
        <!-- 
            Look for C# projects that don't import CommonSettingsCs.targets 
        -->
        <XmlRead XPath="//n:Project[count(n:Import[@Project[contains(string(), 'CommonSettingsCs.targets')]]) = 0]/n:PropertyGroup/n:AssemblyName/text() "
            XmlFileName="%(CheckProjects_CsProjects.Identity)"
            Namespace="http://schemas.microsoft.com/developer/msbuild/2003"
            Prefix="n" >
            <Output TaskParameter="Value" ItemName="CheckProjects_CsMissingImports"/>
        </XmlRead>
        <Error Text="Project missing CommonSettingsCs.targets: %(CheckProjects_CsMissingImports.Identity)"
                     Condition="'%(CheckProjects_CsMissingImports.Identity)' != ''" />
    </Target>
    

    这可以防止开发人员忘记添加 #1。您可以创建自己的项目模板,以确保所有新项目默认都有此模板。

    这种方法的优点是设置新的源代码树登记只涉及获取当前源代码树。缺点是您必须在创建项目文件时对其进行一次编辑。

    【讨论】:

    • 谢谢!花了半个上午寻找一个体面的解决方案;您的第 3 点是缺少的链接。
    • 谢谢。如果有的话,AfterTargets 属性让我走上了正确的道路
    • 自发布此答案已有 7 年。虽然很好,但我想知道现在是否有一种不那么冗长的方法来做到这一点?
    • 可能会有,但这些天我真的不是我们VS。 AFAIK 项目系统没有显着变化。
    【解决方案2】:

    要处理解决方案文件,MSBuild 会创建一个临时 MSBuild 项目文件,其中仅包含一些目标,例如 BuildClean。所以你不能在解决方案文件上调用你的自定义目标。

    【讨论】:

    • 好的,我知道了。我进入了这个临时项目文件,它包括构建、清理、重建和发布。没有从 common.targets.files 导入。太糟糕了,我将不得不找到另一个解决方案。
    【解决方案3】:

    Madgnome 可能是对的。但我想补充一点,您不应该编辑 Microsoft.common.targets 文件。如果你这样做了,你就有可能在这台机器上拥有与其他人不同的构建过程。在您的情况下,您可以只使用 RealClean 目标创建一个新的 MSBuild 文件并将其放置在 C:\Program Files (x86)\MSBuild\v4.0\Custom.After.Microsoft.Common.targets 或 32 位 C:\Program Files\MSBuild\v4.0\Custom.After.Microsoft.Common.targets 本质上,这与将该文件放在 Microsoft.Common.targets 中相同,只是您不必修改该文件。

    【讨论】:

    • 谢谢!这样会更干净。
    • 还有什么方法可以在解决方案级别而不是机器级别进行此修改?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-07
    • 2014-08-11
    • 2013-08-15
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 2012-01-17
    相关资源
    最近更新 更多