在Visual Studio中,为什么所有文件都自动成为我的C#项目的一部分?

fly*_*lyx 2 c# msbuild cmake visual-studio .net-standard

我使用CMake自动生成Visual Studio解决方案,其结构如下所示:

/src
  CMakeLists.txt
  SomeSource.cs
  /build       << contents of this folder generated by CMake
    GeneratedCode.cs
    MyProject.sln
    MyProjectNET.csharp
    <other files by CMake>
Run Code Online (Sandbox Code Playgroud)

问题是,当我在Visual Studio中打开解决方案时,C#项目在文件夹中包含所有内容/build,包括输出目录等。我检查了.csproj文件以查看CMake是否生成了项目,以便所有这些文件都明确包含在内,但实际情况并非如此。

现在只会带来不便。但是,如您所见,我GeneratedCode.cs/build目录中。此代码由CMake生成。由于CMake知道它是项目的一部分,因此在生成时会显式添加引用MyProjectNET.csharp。我现在观察到的行为是,GeneratedCode.cs在Visual Studio中打开时,编辑器几乎用红色突出显示所有内容,表示它是“歧义引用”,并且列出了同一类,GeneratedCode.cs其来源尽可能多。这使得基本上不可能发现代码中的实际错误。

有趣的是,编译代码是可行的。我只得到一个警告,提示编译器两次将相同文件作为输入。但是,我想摆脱这种行为,以便更高效地使用代码。

因此,导致我出现问题的原因是我的项目会/build自动在文件夹中包含所有文件,然后在GeneratedCode.cs显式文件中包含该文件,这会使Visual Studio感到困惑。为什么所有文件都在我的项目中?我认为这不是正常行为,因为我看不到C ++项目和CMake不会生成的另一个C#项目发生这种情况。我假设CMake在.csproj文件中生成了一些奇怪的设置,但是我在项目文件中找不到任何与我的问题有关的东西。什么设置会导致此行为?

编辑:VS版本是2017,版本15.9.9。希望合适,这是实际的项目文件:

<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk" DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Label="Globals">
    <ProjectGuid>{0AE1D52A-C2A2-35E1-914D-92101FC2A02F}</ProjectGuid>
    <WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
    <Keyword>Win32Proj</Keyword>
    <Platform>x64</Platform>
    <ProjectName>libheroes.NET</ProjectName>
    <VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
    <Authors>Felix Krause</Authors>
    <LangVersion>7.2</LangVersion>
    <PackageId>Libheroes.NET</PackageId>
    <RootNamespace>Heroes</RootNamespace>
    <Version>0.1.0</Version>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
  <TargetFramework>netstandard2.0</TargetFramework></PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <DebugSymbols>true</DebugSymbols>
    <DefineDebug>true</DefineDebug>
    <OutputPath>D:\Projects\libheroes\bindings\csharp\cmake-vs\Debug\</OutputPath>
    <PlatformToolset>v141</PlatformToolset>
    <AssemblyName>libheroes.NET</AssemblyName>
    <AdditionalOptions>/langversion:7.2</AdditionalOptions>
    <DebugType>full</DebugType>
    <DefineConstants>DEBUG</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <Optimize>false</Optimize>
    <WarningLevel>3</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <OutputPath>D:\Projects\libheroes\bindings\csharp\cmake-vs\Release\</OutputPath>
    <PlatformToolset>v141</PlatformToolset>
    <AssemblyName>libheroes.NET</AssemblyName>
    <AdditionalOptions>/langversion:7.2</AdditionalOptions>
    <DebugType>none</DebugType>
    <DefineConstants />
    <ErrorReport>queue</ErrorReport>
    <Optimize>true</Optimize>
    <WarningLevel>1</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'" Label="Configuration">
    <OutputPath>D:\Projects\libheroes\bindings\csharp\cmake-vs\MinSizeRel\</OutputPath>
    <PlatformToolset>v141</PlatformToolset>
    <AssemblyName>libheroes.NET</AssemblyName>
    <AdditionalOptions>/langversion:7.2</AdditionalOptions>
    <DebugType>none</DebugType>
    <DefineConstants />
    <Optimize>true</Optimize>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="Configuration">
    <DebugSymbols>true</DebugSymbols>
    <DefineDebug>true</DefineDebug>
    <OutputPath>D:\Projects\libheroes\bindings\csharp\cmake-vs\RelWithDebInfo\</OutputPath>
    <PlatformToolset>v141</PlatformToolset>
    <AssemblyName>libheroes.NET</AssemblyName>
    <AdditionalOptions>/langversion:7.2</AdditionalOptions>
    <DebugType>full</DebugType>
    <DefineConstants />
    <Optimize>false</Optimize>
  </PropertyGroup>
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets">
    <Import Project="$(UserRootDir)\Microsoft.CSharp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.CSharp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <ItemGroup>
    <None Include="D:\Projects\libheroes\bindings\csharp\CMakeLists.txt">
      <Link>CMakeLists.txt</Link>
    </None>
  </ItemGroup>
  <Target Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Name="CustomCommand_Debug_a636c07f1d51cd46229efc4bacc41a89" Inputs="D:/Projects/libheroes/bindings/csharp/CMakeLists.txt;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CompilerId\VS-10.csproj.in;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt;D:\Projects\libheroes\bindings\csharp\LibHeroes.NET.targets;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeCSharpCompiler.cmake;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeSystem.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt" Outputs="D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\generate.stamp">
    <Exec Command="echo Building Custom Rule D:/Projects/libheroes/bindings/csharp/CMakeLists.txt" />
    <Exec Command="setlocal&#xA;&quot;C:\Program Files\CMake\bin\cmake.exe&quot; -SD:/Projects/libheroes/bindings/csharp -BD:/Projects/libheroes/bindings/csharp/cmake-vs --check-stamp-file D:/Projects/libheroes/bindings/csharp/cmake-vs/CMakeFiles/generate.stamp&#xA;if %errorlevel% neq 0 goto :cmEnd&#xA;:cmEnd&#xA;endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone&#xA;:cmErrorLevel&#xA;exit /b %1&#xA;:cmDone&#xA;if %errorlevel% neq 0 goto :VCEnd" />
  </Target>
  <Target Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Name="CustomCommand_Release_a636c07f1d51cd46229efc4bacc41a89" Inputs="D:/Projects/libheroes/bindings/csharp/CMakeLists.txt;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CompilerId\VS-10.csproj.in;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt;D:\Projects\libheroes\bindings\csharp\LibHeroes.NET.targets;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeCSharpCompiler.cmake;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeSystem.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt" Outputs="D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\generate.stamp">
    <Exec Command="echo Building Custom Rule D:/Projects/libheroes/bindings/csharp/CMakeLists.txt" />
    <Exec Command="setlocal&#xA;&quot;C:\Program Files\CMake\bin\cmake.exe&quot; -SD:/Projects/libheroes/bindings/csharp -BD:/Projects/libheroes/bindings/csharp/cmake-vs --check-stamp-file D:/Projects/libheroes/bindings/csharp/cmake-vs/CMakeFiles/generate.stamp&#xA;if %errorlevel% neq 0 goto :cmEnd&#xA;:cmEnd&#xA;endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone&#xA;:cmErrorLevel&#xA;exit /b %1&#xA;:cmDone&#xA;if %errorlevel% neq 0 goto :VCEnd" />
  </Target>
  <Target Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'" Name="CustomCommand_MinSizeRel_a636c07f1d51cd46229efc4bacc41a89" Inputs="D:/Projects/libheroes/bindings/csharp/CMakeLists.txt;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CompilerId\VS-10.csproj.in;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt;D:\Projects\libheroes\bindings\csharp\LibHeroes.NET.targets;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeCSharpCompiler.cmake;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeSystem.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt" Outputs="D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\generate.stamp">
    <Exec Command="echo Building Custom Rule D:/Projects/libheroes/bindings/csharp/CMakeLists.txt" />
    <Exec Command="setlocal&#xA;&quot;C:\Program Files\CMake\bin\cmake.exe&quot; -SD:/Projects/libheroes/bindings/csharp -BD:/Projects/libheroes/bindings/csharp/cmake-vs --check-stamp-file D:/Projects/libheroes/bindings/csharp/cmake-vs/CMakeFiles/generate.stamp&#xA;if %errorlevel% neq 0 goto :cmEnd&#xA;:cmEnd&#xA;endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone&#xA;:cmErrorLevel&#xA;exit /b %1&#xA;:cmDone&#xA;if %errorlevel% neq 0 goto :VCEnd" />
  </Target>
  <Target Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Name="CustomCommand_RelWithDebInfo_a636c07f1d51cd46229efc4bacc41a89" Inputs="D:/Projects/libheroes/bindings/csharp/CMakeLists.txt;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpCompiler.cmake.in;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCSharpInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeCompilerIdDetection.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeDetermineCompilerId.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeGenericSystem.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeInitializeConfigs.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInformation.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeSystemSpecificInitialize.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCSharpCompiler.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CMakeTestCompilerCommon.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\CompilerId\VS-10.csproj.in;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\Windows.cmake;C:\Program Files\CMake\share\cmake-3.14\Modules\Platform\WindowsPaths.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt;D:\Projects\libheroes\bindings\csharp\LibHeroes.NET.targets;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeCSharpCompiler.cmake;D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\3.14.0\CMakeSystem.cmake;D:\Projects\libheroes\bindings\csharp\CMakeLists.txt" Outputs="D:\Projects\libheroes\bindings\csharp\cmake-vs\CMakeFiles\generate.stamp">
    <Exec Command="echo Building Custom Rule D:/Projects/libheroes/bindings/csharp/CMakeLists.txt" />
    <Exec Command="setlocal&#xA;&quot;C:\Program Files\CMake\bin\cmake.exe&quot; -SD:/Projects/libheroes/bindings/csharp -BD:/Projects/libheroes/bindings/csharp/cmake-vs --check-stamp-file D:/Projects/libheroes/bindings/csharp/cmake-vs/CMakeFiles/generate.stamp&#xA;if %errorlevel% neq 0 goto :cmEnd&#xA;:cmEnd&#xA;endlocal &amp; call :cmErrorLevel %errorlevel% &amp; goto :cmDone&#xA;:cmErrorLevel&#xA;exit /b %1&#xA;:cmDone&#xA;if %errorlevel% neq 0 goto :VCEnd" />
  </Target>
  <ItemGroup>
    <Compile Include="D:\Projects\libheroes\bindings\csharp\cmake-vs\LibHeroes.cs" />
    <Compile Include="D:\Projects\libheroes\bindings\csharp\Marshaling.cs">
      <Link>Marshaling.cs</Link>
    </Compile>
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="D:\Projects\libheroes\bindings\csharp\cmake-vs\ZERO_CHECK.vcxproj">
      <Project>{C0C9F6B6-CF04-32B9-BDB5-A1812B10331E}</Project>
      <Name>ZERO_CHECK</Name>
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
      <CopyToOutputDirectory>Never</CopyToOutputDirectory>
    </ProjectReference>


    <ProjectReference Include="D:\Projects\libheroes\bindings\csharp\cmake-vs\build\libheroes.vcxproj">
      <Project>{E8B13004-193F-393B-90DB-A41070EDBD99}</Project>
      <Name>libheroes</Name>
      <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
      <CopyToOutputDirectory>Never</CopyToOutputDirectory>
    </ProjectReference>
  </ItemGroup>

  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'Release'">
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'MinSizeRel'">
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)' == 'RelWithDebInfo'">
  </PropertyGroup>
  <PropertyGroup>
    <BuildDependsOn>
      CustomCommand_Debug_a636c07f1d51cd46229efc4bacc41a89;
      CustomCommand_MinSizeRel_a636c07f1d51cd46229efc4bacc41a89;
      CustomCommand_RelWithDebInfo_a636c07f1d51cd46229efc4bacc41a89;
      CustomCommand_Release_a636c07f1d51cd46229efc4bacc41a89;
      $(BuildDependsOn)
</BuildDependsOn>
  </PropertyGroup>
<ItemGroup><Content Include="build\Libheroes.NET.targets"><Pack>true</Pack><PackagePath>\build\</PackagePath></Content><Content Include="build\$(Configuration)\yaml.dll"><Pack>true</Pack><PackagePath>\build\</PackagePath></Content><Content Include="build\$(Configuration)\libheroes.dll"><Pack>true</Pack><PackagePath>\build\</PackagePath></Content></ItemGroup></Project>
Run Code Online (Sandbox Code Playgroud)

jes*_*ing 5

The new .NET Standard (<Project sdk="Microsoft.NET.Sdk">) style project files auto-include files with certain extensions automatically from the project folder. This change has been introduced with Visual Studio 2017/NetStandard/.NET Core and makes it much easier to maintain project files. Basically the new project system assumes that you want to include the following:

<Compile Include="**\*.cs" />
<EmbeddedResource Include="**\*.resx" />
<None Include"**\*" />
Run Code Online (Sandbox Code Playgroud)

As a by-product, it can accidentally include files you didn't want to. This upgrade blog-post walks through the differences. It helped me understand many of the specifics.

By default /bin and /obj are excluded. The best way for you to proceed is to generate your build folder under the obj folder by directing the output to $(BaseIntermediateOutputPath)\build.

There are ways to disable the 'new behavior' and to exclude certain files and folders.

To switch to the old behavior, add the following to the top of your project file:

<PropertyGroup>
    <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
    <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
    <EnableDefaultContentItems>false</EnableDefaultContentItems>

    <!-- Or all default includes -->
    <EnableDefaultItems>false</EnableDefaultItems>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

To exclude specific files from the solution I think this should do the trick:

<ItemGroup>
    <Compile Remove="build\**\*.cs">
    <EmbeddedResource Remove="build\**\*.resx" />
    <None Remove="build\**\*" />
</ItemGroup>
Run Code Online (Sandbox Code Playgroud)

Or add the build folder to the $(DefaultItemExcludes):

<PropertyGroup>
     <DefaultItemExcludes>$(DefaultItemExcludes);build\**\*</DefaultItemExcludes>
</PropertyGroup>
Run Code Online (Sandbox Code Playgroud)

Or you can exclude items from the Visual Studio Solution Explorer by right-clicking them and choosing Exclude from project.

See also:

  • `&lt;EnableDefaultItems&gt;` 标签正是我想要的。使用此标签生成项目修复了错误。感谢所有的链接,他们是一个很大的帮助。 (2认同)