在大多数项目中,无需专门选择要生成的文件。 例如,使用 Visual Studio 创建的任何项目都会生成项目中的所有源文件。 但是,可能需要了解如何编辑项目文件来处理不同于默认的方案,例如,如果要从项目文件夹以外的其他位置生成文件,或者创建自己的生成过程而不是使用 .NET SDK 等 SDK。
按项目类型的默认行为
确定 MSBuild 在生成中包含的文件的默认行为因项目类型而异。
对于 .NET SDK 项目,标准 .NET SDK 定义一个默认 Compile 项列表,其中包含项目文件夹树中与相应特定于语言的文件扩展名匹配的文件。 例如,对于 C# 项目, Compile 该项使用 glob 模式填充,该模式 **/*.cs与项目文件夹中的所有源文件及其所有子文件夹以递归方式匹配。 看不到项目文件中的 Compile 元素,因为它在已隐式导入的 SDK .props 文件中定义。 请参阅 .NET 项目 SDK 概述 - 默认包括和排除。
如果您使用 Visual Studio,可以通过更改文件上的 生成操作 来修改要生成的源文件集。 将其设置为 None 以从生成中排除文件。 在 Visual Studio 中进行此更改会影响项目文件。 Visual Studio 添加行以从 Compile 项列表中删除源文件,并将其添加到 None 项列表中。
<ItemGroup>
<Compile Remove="Class.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Class.cs" />
</ItemGroup>
对于 .NET Framework 或其他非 SDK 项目,项目文件通过列出所有源文件显式构造Compile 项目。
对于C++项目,源文件被显式添加到项目文件中的ClCompile元素中。
在不使用 SDK 的情况下手动创作 MSBuild 项目文件时,可以在项目文件中单独列出每个源文件,也可以使用通配符将所有文件包含在一个目录或一组嵌套的目录中。 还可以使用本文中的技术来修改 Compile 项目列表(在 .NET 项目中)或 ClCompile C++项目中的项列表,以自定义生成的文件。
指定输入
项表示生成的输入(如源文件)。 有关项的详细信息,请参阅 “项”。
要将文件包含在构建中,它们必须被包含在项目列表中。 如前所述,在 .NET SDK 和 .NET Framework 项目中,源文件的项列表为 Compile。 在 .NET SDK 项目中看不到 Compile 项列表,因为它在隐式导入中定义。 请参阅 “使用项目 SDK”。
不依赖于标准导入的项目文件可以使用任意项列表名称,例如 VBFile 或 CSFile。 请参阅本文后面的 示例 1 和 示例 2 。 若要基于项列表设置生成,请按名称将项列表传递给生成任务, 如本文稍后所述。
可以将多个文件添加到项列表中,方法是单独添加文件或使用通配符一次性添加多个文件。
单独逐项声明
使用
Include的属性,类似于以下示例:<Compile Include="Form1.cs"/>或
<Compile Include="Form1.vb"/>注释
如果项集合中的项与项目文件不在同一目录中,则必须指定项的完整路径或相对路径。 例如:
Include="..\..\Form2.cs"。
同一项列表可以通过多个 Include 属性反复修改。 每个 Include 都会增加到之前的内容中。
声明多个项目
使用类似于以下示例的
Include属性进行操作:<Compile Include="Form1.cs;Form2.cs"/>或
<Compile Include="Form1.vb;Form2.vb"/>
使用通配符指定输入
还可以使用通配符以递归方式包括所有文件,或仅将子目录中的特定文件作为生成输入。 有关通配符的详细信息,请参阅 Items
以下示例基于一个项目,其中包含以下目录和子目录中的图形文件,项目文件位于 Project 目录中:
Project\Images\BestJpgs
Project\Images\ImgJpgs
Project\Images\ImgJpgs\Img1
在 Images 目录和子目录中包括所有 .jpg 文件
使用以下
Include属性:Include="Images\**\*.jpg"
包括所有以 img 开头的 .jpg 文件
使用以下
Include属性:Include="Images\**\img*.jpg"
在目录中包括名称以 jpgs 结尾的所有文件
使用以下一个属性
Include:Include="Images\**\*jpgs\*.*"或
Include="Images\**\*jpgs\*"
排除和删除项目
你可能想要指定与特定模式匹配的文件,但有一些例外情况。 可以通过将 Include 和 Exclude 结合在一起,在单个操作中完成此任务。
<ItemGroup>
<!-- Include every C# source file, except anything in the "sub" folder -->
<Compile Include="**/*.cs" Exclude="sub/**/*.cs">
</ItemGroup>
若要删除以前包含或 SDK 默认包含的项,可以使用该 Remove 属性。
<ItemGroup>
<!-- Remove anything in the "sub" folder -->
<Compile Remove="sub/**/*.cs">
</ItemGroup>
将项目传递到任务或目标
在大多数项目文件中,您无需将 Compile 项显式传递到目标或任务,因为标准导入会处理这一点。 但是,对于项目文件的目标,可以使用 @() 任务中的表示法将整个项列表指定为生成输入。 无论是单独列出所有文件还是使用通配符,都可以使用此表示法。
将所有 C# 或 Visual Basic 文件用作编译器任务的输入
请使用类似以下内容的
Include属性:<CSC Sources="@(CSFile)">...</CSC>或
<VBC Sources="@(VBFile)">...</VBC>
注释
必须使用通配符和项来指定生成的输入;不能使用 Sources MSBuild 任务(如 Csc 或 Vbc)中的属性来指定输入。 以下示例在项目文件中无效:
<CSC Sources="*.cs">...</CSC>
示例 1
下面的代码示例演示了一个项目,该项目单独包含所有输入文件。
<Project DefaultTargets="Compile">
<PropertyGroup>
<Builtdir>built</Builtdir>
</PropertyGroup>
<ItemGroup>
<CSFile Include="Form1.cs"/>
<CSFile Include="AssemblyInfo.cs"/>
<Reference Include="System.dll"/>
<Reference Include="System.Data.dll"/>
<Reference Include="System.Drawing.dll"/>
<Reference Include="System.Windows.Forms.dll"/>
<Reference Include="System.XML.dll"/>
</ItemGroup>
<Target Name="PreBuild">
<Exec Command="if not exist $(builtdir) md $(builtdir)"/>
</Target>
<Target Name="Compile" DependsOnTargets="PreBuild">
<Csc Sources="@(CSFile)"
References="@(Reference)"
OutputAssembly="$(builtdir)\$(MSBuildProjectName).exe"
TargetType="exe" />
</Target>
</Project>
示例 2
下面的代码示例使用通配符来包括所有 .cs 文件。
<Project DefaultTargets="Compile">
<PropertyGroup>
<builtdir>built</builtdir>
</PropertyGroup>
<ItemGroup>
<CSFile Include="*.cs"/>
<Reference Include="System.dll"/>
<Reference Include="System.Data.dll"/>
<Reference Include="System.Drawing.dll"/>
<Reference Include="System.Windows.Forms.dll"/>
<Reference Include="System.XML.dll"/>
</ItemGroup>
<Target Name="PreBuild">
<Exec Command="if not exist $(builtdir) md $(builtdir)"/>
</Target>
<Target Name="Compile" DependsOnTargets="PreBuild">
<Csc Sources="@(CSFile)"
References="@(Reference)"
OutputAssembly="$(builtdir)\$(MSBuildProjectName).exe"
TargetType="exe" />
</Target>
</Project>