Directory.Build.targets для файлов проекта без целей в Visual Studio

Если в моем файле проекта нет целей, и у меня есть файл Directory.Build.targets (с соответствующими целями) в соответствующем каталоге, Visual Studio не может построить проект. Версия VS - 2019RC, но я не думаю, что это проблема конкретной версии.

Это ожидаемое поведение и почему?

ОБНОВЛЕНИЕ - полная структура проекта. В общем, это модифицированный проект из шаблона "Проект коннектора данных" из "Power Query SDK" - https://marketplace.visualstudio.com/items?itemName=Dakahn.PowerQuerySDK.

Имя проекта — PQExtensionTest. Он имеет типичную структуру папок - каталог решения PQExtensionTest, внутри файла PQExtensionTest.sln и каталог проекта PQExtensionTest с файлами PQExtensionTest.mroj и Directory.build.targets.

Файл PQExtensionTest.sln:

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2046
MinimumVisualStudioVersion = 10.0.40219.1
Project("{4DF76451-A46A-4C0B-BE03-459FAAFA07E6}") = "PQExtensionTest", "PQExtensionTest\PQExtensionTest.mproj", "{6DEC2A2E-C380-4701-AA12-5052284223E4}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|x86 = Debug|x86
        Release|x86 = Release|x86
    EndGlobalSection
    GlobalSection(ProjectConfigurationPlatforms) = postSolution
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Debug|x86.ActiveCfg = Debug|x86
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Debug|x86.Build.0 = Debug|x86
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Release|x86.ActiveCfg = Release|x86
        {6DEC2A2E-C380-4701-AA12-5052284223E4}.Release|x86.Build.0 = Release|x86
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
    EndGlobalSection
    GlobalSection(ExtensibilityGlobals) = postSolution
        SolutionGuid = {50EB6857-946A-4D05-B65C-B99E4D39BEDD}
    EndGlobalSection
EndGlobal

Файл PQExtensionTest.mroj:

<Project xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <ProjectGuid>{6dec2a2e-c380-4701-aa12-5052284223e4}</ProjectGuid>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include = "PQExtensionTest.pq">
      <SubType>Code</SubType>
    </Compile>
    <Content Include = "PQExtensionTest.query.pq">
      <SubType>Code</SubType>
    </Content>
  </ItemGroup>
</Project>

Файл Directory.Build.targets:

<Project DefaultTargets = "BuildExtension" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition = " '$(Configuration)' == '' ">Debug</Configuration>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{a9cd1ca9-92e5-493d-8065-377910605c30}</ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>MyRootNamespace</RootNamespace>
    <AssemblyName>MyAssemblyName</AssemblyName>
    <EnableUnmanagedDebugging>False</EnableUnmanagedDebugging>
    <AllowNativeQuery>False</AllowNativeQuery>
    <AsAction>False</AsAction>
    <FastCombine>False</FastCombine>
    <ClearLog>False</ClearLog>
    <ShowEngineTraces>False</ShowEngineTraces>
    <ShowUserTraces>False</ShowUserTraces>
    <LegacyRedirects>False</LegacyRedirects>
    <SuppressRowErrors>False</SuppressRowErrors>
    <SuppressCellErrors>False</SuppressCellErrors>
    <MaxRows>1000</MaxRows>
    <ExtensionProject>Yes</ExtensionProject>
    <Name>PQExtensionTest</Name>
  </PropertyGroup>
  <PropertyGroup Condition = " '$(Configuration)' == 'Debug' ">
    <DebugSymbols>false</DebugSymbols>
    <!--Should be true, fix this when the debugger is implemented -->
    <OutputPath>bin\Debug\</OutputPath>
  </PropertyGroup>
  <PropertyGroup Condition = " '$(Configuration)' == 'Release' ">
    <DebugSymbols>false</DebugSymbols>
    <OutputPath>bin\Release\</OutputPath>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include = "mscorlib" />
    <Reference Include = "System" />
    <Reference Include = "System.Data" />
    <Reference Include = "System.Xml" />
  </ItemGroup>
 <Import Project = "$(MSBuildBinPath)\Microsoft.CSharp.targets" />
  <UsingTask TaskName = "BuildExtension" TaskFactory = "CodeTaskFactory" AssemblyFile = "$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
    <ParameterGroup>
      <InputDirectory ParameterType = "System.String" Required = "true" />
      <OutputFile ParameterType = "System.String" Required = "true" />
    </ParameterGroup>
    <Task>
      <Reference Include = "System.IO.Compression" />
      <Reference Include = "System.IO.Compression.FileSystem" />
      <Using Namespace = "System.Globalization" />
      <Using Namespace = "System.IO.Compression " />
      <Code Type = "Fragment" Language = "cs"><![CDATA[    
    using(FileStream fileStream = File.Create(OutputFile))
    using(ZipArchive archiveOut = new ZipArchive(fileStream, ZipArchiveMode.Create, false))
    {
        foreach(string fullPath in Directory.EnumerateFiles(InputDirectory))
        {
            string filename = Path.GetFileName(fullPath);

            archiveOut.CreateEntryFromFile(fullPath, filename, CompressionLevel.Optimal);
        }
    }
]]></Code>
    </Task>
  </UsingTask>
  <Target Name = "BuildExtension" DependsOnTargets = "ExtensionClean">
    <ItemGroup>
      <PQFiles Include = "@(Compile)" Condition = "'%(Extension)' == '.pq'" />
    </ItemGroup>
    <ItemGroup>
      <NonPQFiles Include = "@(Compile)" Condition = "'%(Extension)' != '.pq'" />
    </ItemGroup>
    <MakeDir Directories = "$(IntermediateOutputPath)" />
    <MakeDir Directories = "$(OutputPath)" />
    <Copy SourceFiles = "@(NonPQFiles)" DestinationFolder = "$(IntermediateOutputPath)" />
    <Copy SourceFiles = "@(PQFiles)" DestinationFiles = "@(PQFiles->'$(IntermediateOutputPath)%(RecursiveDir)%(FileName).m')" />
    <BuildExtension InputDirectory = "$(IntermediateOutputPath)" OutputFile = "$(OutputPath)\$(ProjectName).mez" />
  </Target>
  <Target Name = "ExtensionClean">
    <!-- Remove obj folder -->
    <RemoveDir Directories = "$(BaseIntermediateOutputPath)" />
    <!-- Remove bin folder -->
    <RemoveDir Directories = "$(OutputPath)" />
<Message Text = "MyM: $(aProperty)" />
   </Target>

Если возможно, не могли бы вы поделиться простым образцом файла вашего проекта и файла Directory.Build.targets. В ходе этого процесса на результат сборки может повлиять множество факторов. Поэтому трудно сказать, является ли это ожидаемым поведением без этих двух файлов.

LoLance 18.03.2019 10:00

Привет, я проверил ваше обновление и боюсь, что этот тип проекта не поддерживает вашу ситуацию. Этот тип проекта является расширением от третьей стороны, а не от команды разработчиков VS. И после того, как я протестировал это расширение, у него есть специальный процесс проверки, который сильно отличается от проектов VS. (C# C++...) Например: Создайте новый проект, удалите две цели в своем файле проекта. Перезагрузитесь, и вы обнаружите, что опция сборки исчезла!!!

LoLance 20.03.2019 09:09

И для ошибки: E_INVALIDARG. Add PropertyGroup Condition = " '$(Configuration)' == 'Debug' "> <DebugSymbols>false</DebugSymbols> <!--Должно быть true, исправьте это, когда отладчик будет реализован --> <OutputPath>bin\Debug \</OutputPath> </PropertyGroup> в файл proj может помочь загрузить. Не знаю почему, процесс проверки довольно странный.

LoLance 20.03.2019 09:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
6 352
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Is that expected behavior, and why?

Это зависит.

1. Во-первых, согласно этот документ, Directory.Build.targets работает только после того, как Microsoft.Common.props вызывает его.

Поэтому, если вы не импортировали Microsoft.Common.props (или .targets) в файл проекта, сборка завершится ошибкой.

В этой ситуации ожидаемое поведение состоит в том, что мы не можем построить проект без целей в файле проекта.

2. Как вы упомянули «У меня есть файл Directory.Build.targets (с соответствующими целями)», убедитесь, что в вашем файле проекта есть <Import Project = "$(MSBuildToolsPath)\Microsoft.CSharp.targets" />. Без него сборка не может работать в вашей ситуации (без настраиваемых целей в файле проекта).

Убедитесь, что вы импортировали Microsoft.CSharp.targets в файл проекта. А для ваших целей в Directory.Build.targets добавьте атрибут <Target BeforeTargets = "..."> или <Target AfterTargets = "...">, чтобы он работал.

Пример для моего Directory.Build.targets:

<Project ToolsVersion = "15.0" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
...
  </PropertyGroup>
  <Target Name = "Test" AfterTargets = "build">
    <Message Text = "..."/>
  </Target>
</Project>

Только когда вы соблюдаете эти пункты, вы можете успешно строить в своей ситуации. Поэтому, пожалуйста, проверьте это.

Обновлять:

Для пользовательского .proj файла. У нас должна быть цель, определенная непосредственно в файле .proj, или цель, импортированная с другими файлами целей.

Поскольку в вашем файле проекта нет целей, и цели в ваших импортированных целях не будут запущены, MSBuild выдаст ошибку MSB4040 (в проекте нет цели). Потому что, если цель не запущена, процесс MSBuild не имеет смысла. Это функция по дизайну.

Обновление2

В test.sln у меня есть Directory.build.props в каталоге решений:

<Project  xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name = "Today">
    <Message Text = "JustForTest"/>
  </Target>
</Project>

И довольно простой файл .csproj в каталоге проекта:

<?xml version = "1.0" encoding = "utf-8"?>
<Project ToolsVersion = "15.0" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project = "$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition = "Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
</Project>

Если я соберу test.csproj, сборка может завершиться успешно и запустить цель «Сегодня», чтобы вывести «JustForTest». И если я закомментирую импорт Microsoft.Common.Props, сборка завершится ошибкой с MSB4040. Потому что в .NET Directory.build.propsне может быть импортирован неявно без Microsoft.Common.Props.

Обновление3

Я проверил содержимое microsoft.common.props и microsoft.Csharp.targets. В файле M.C.P есть определение и вызовы Directory.build.props. Находясь в файле M.C.T, он определяет стандартный процесс сборки C#. Поэтому я согласен с тем, что в вашем файле проекта должно быть что-то, что вызывает Directory.build.props, но это не может быть microsoft.Csharp.targets или microsoft.VB.targets.

1. У меня есть цели в Directory.Build.targets. Но только в этом файле. Значит, это нечестиво? 2. «Directory.Build.targets работает только после того, как Microsoft.Common.props вызовет его» — вы имеете в виду, что Directory.Build.targets будут импортированы после Microsoft.Common.props импортированы или если Microsoft.Common.props импортированы, или что-то другое?

Andrey Minakov 19.03.2019 11:38

For1, как я упоминал выше, в ситуации, когда у нас есть цели только в Directory.Build.targets и только в этом файле, сможем ли мы построить проект или нет, зависит от того, есть ли у нас «Microsoft.Common.props» для назовите его или что-то с похожей функцией, например «Microsoft.Common.props».

LoLance 19.03.2019 11:51

For2, да, только что еще раз проверил. В проекте C# он использует Microsoft.Common.props для неявного импорта Directory.Build.targets, если я прокомментирую, что import Microsoft.Common.props, то сборка упадет, поскольку цели не импортируются в файл proj. Я скоро добавлю некоторые детали в свое обновление, вы можете проверить это.

LoLance 19.03.2019 11:54

Кроме того: если Directory.build.props не может быть неявно импортирован в файл вашего проекта, где нет целей, вы не сможете построить проект, если не импортируете его явно с помощью <Import Project = "..\Directory.Build.props " />

LoLance 19.03.2019 12:03

"Я скоро добавлю некоторые детали в свое обновление, вы можете проверить его" - не могли бы вы сказать, где я могу проверить обновление? Спасибо. По поводу ошибки - я даже не могу "загрузить" проект, когда я открываю такой проект (проект без какой-либо цели, но в Directory.Build.targets), я вижу проект в состоянии "выгрузки", и если я пытаюсь загрузить это, я получаю сообщение об ошибке. Поэтому я не вижу, какие файлы Microsoft.Common* используются для сборки такого проекта.

Andrey Minakov 20.03.2019 07:29

Привет, какой тип проекта в визуальной студии? Может быть, я могу создать тип проекта, который вы используете, а затем я могу исследовать его структуру. Кроме того, даже если у нас нет целей в файле проекта и в обоих файлах Directory.Build.targets, сборка завершится ошибкой, а перезагрузка может быть успешной. Не могли бы вы поделиться сообщением об ошибке при попытке загрузки, я предполагаю, что могут быть некоторые синтаксические ошибки. (И посмотрите update2, я пытаюсь описать, что я имею в виду, когда Directory.build.targets вызывается другим проектом импорта)

LoLance 20.03.2019 07:39

Ошибка E_INVALIDARG. Кстати, я просмотрел свой файл mporj и понял, что там есть импорт Microsoft.CSharp.targets для встроенной задачи. И я подозреваю, что все штучки Directory.Build* у меня работают только потому, что есть этот импорт. Это правильно? Таким образом, без импорта Microsoft.CSharp.targets или Microsoft.VisualBasic.targets вся эта магия Directory.Build.* исчезает.

Andrey Minakov 20.03.2019 07:42

Хорошо, я размещу всю структуру проекта в обновлении для своего поста. Большое спасибо за ваше терпение.

Andrey Minakov 20.03.2019 07:43

Хорошо, я проверю это после вашего обновления. Любой вопрос, пожалуйста, не стесняйтесь связаться со мной :)

LoLance 20.03.2019 07:50

Давайте продолжить обсуждение в чате.

Andrey Minakov 20.03.2019 09:17

Другие вопросы по теме