В чем разница между целью PreBuildEvent, BeforeBuild и целью BeforeCompile в MSBuild?

Недавно мне пришлось переместить некоторый код из PreBuildEvent в Visual Studio в цель BeforeBuild, чтобы заставить его работать в AppHarbor. При этом я также заметил цель BeforeCompile.

В чем разница между этими тремя, казалось бы, похожими событиями: PreBuildEvent, BeforeBuild Target, BeforeCompileTarget?

Что можно/нельзя сделать с каждым из них, и почему вы предпочли бы одно другому?


person Danny Tuppeny    schedule 08.05.2011    source источник


Ответы (1)


Ответ на этот вопрос можно найти в файле Microsoft.Common.targets, который можно найти (в зависимости от того, используете ли вы 64-разрядную или 32-разрядную платформу) по адресу: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.target для 64-разрядной версии и C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets для 32-разрядной среды выполнения. Этот файл определяет все этапы сборки вашего проекта. Цитирую источник:

<!--
============================================================
                                    Build

The main build entry point.
============================================================
-->
<PropertyGroup>
    <BuildDependsOn>
        BeforeBuild;
        CoreBuild;
        AfterBuild
    </BuildDependsOn>
</PropertyGroup>

Код достаточно хорош, чтобы объяснить использование целей BeforeBuild и AfterBuild в комментариях для обеих целей.

<!--
============================================================
                                    BeforeBuild

Redefine this target in your project in order to run tasks just before Build
============================================================
-->
<Target Name="BeforeBuild"/>

<!--
============================================================
                                    AfterBuild

Redefine this target in your project in order to run tasks just after Build
============================================================
-->
<Target Name="AfterBuild"/>

Далее следует определение цели CoreBuild:

<PropertyGroup>
    <CoreBuildDependsOn>
        BuildOnlySettings;
        PrepareForBuild;
        PreBuildEvent;
        ResolveReferences;
        PrepareResources;
        ResolveKeySource;
        Compile;
        UnmanagedUnregistration;
        GenerateSerializationAssemblies;
        CreateSatelliteAssemblies;
        GenerateManifests;
        GetTargetPath;
        PrepareForRun;
        UnmanagedRegistration;
        IncrementalClean;
        PostBuildEvent
    </CoreBuildDependsOn>
</PropertyGroup>

Таким образом, цель Build — это всего лишь оболочка вокруг цели CoreBuild, позволяющая выполнять настраиваемые шаги непосредственно перед или после цели CoreBuild. Как видно выше, PreBuildEvent и PostBuildEvent перечислены как зависимости цели CoreBuild. Зависимости цели Compile определяются следующим образом:

<PropertyGroup>
    <CompileDependsOn>
        ResolveReferences;
        ResolveKeySource;
        SetWin32ManifestProperties;
        _GenerateCompileInputs;
        BeforeCompile;
        _TimeStampBeforeCompile;
        CoreCompile;
        _TimeStampAfterCompile;
        AfterCompile
    </CompileDependsOn>
</PropertyGroup>

Снова BeforeCompile и AfterCompile закомментированы в коде:

<!--
============================================================
                                    BeforeCompile

Redefine this target in your project in order to run tasks just before Compile.
============================================================
-->
<Target Name="BeforeCompile"/>

<!--
============================================================
                                    AfterCompile

Redefine this target in your project in order to run tasks just after Compile.
============================================================
-->
<Target Name="AfterCompile"/>

Учитывая эту информацию, я не знаю, почему AppHarbor не поддерживает Pre-, PostBuildEvent, тогда как Build можно изменить с помощью Before-, AfterBuild.

Выбор того, какой Target переопределить для какого сценария, зависит от момента во время сборки, когда вы хотите выполнить данную задачу. Цели не имеют конкретных ограничений и/или преимуществ в отношении того, чего они могут достичь. Помимо того, что они могут адаптировать ItemGroup или свойства, которые были определены/заполнены на предыдущих шагах.

Использование nuget для добавления пакетов, вероятно, лучше всего выполнять до того, как сборка попытается разрешить зависимости проектов. Так что BeforeCompile не лучший кандидат для такого рода действий.

Я надеюсь, что это проливает свет на этот вопрос. Нашел еще одно хорошее объяснение в MSDN.

person Bas Bossink    schedule 08.05.2011
comment
Чтобы расширить это, msbuild читает список файлов, участвующих в процессе компиляции между BeforeBuild и BeforeCompile. Если вы используете задачу, которая генерирует файл, который вы используете в качестве входных данных сборки, это должно произойти в BeforeBuild; если вы сделаете это в BeforeCompile, файл будет сгенерирован, но затем msbuild будет жаловаться, что не может его найти. - person cdhowie; 27.10.2012
comment
Обязательно обратите внимание, что ничего из этого не относится к файлам проекта C++ (.vcxproj). Это относится только к проектам C#. - person C Johnson; 23.04.2013
comment
Для тех, кто хочет больше узнать о целях. Я вставляю эту ссылку сюда, потому что не нашел никакой полезной чистой цели, с которой можно было бы помешать: docs.microsoft.com/en-us/visualstudio/msbuild/ - person Fabrice T; 16.10.2020