2017-10-10 5 views
0

J'ai un outil générateur de code que je possède partiellement, et maintenant que les fichiers csproj peuvent lister plusieurs Frameworks Cibles et les construire tous, j'essaye de comprendre comment faire une Cible MSBuild pour faire la génération de code seulement une fois par exécution de la génération, quel que soit le nombre de cadres cibles répertoriés, et que la compilation de chaque structure cible attende jusqu'à la fin de la génération du code.Comment créer une cible MSBuild qui ne s'exécute qu'une fois au lieu d'une fois, avant les cibles qui s'exécutent une fois par structure dans le tag TargetFrameworks?

Je l'ai actuellement conditionnel à une valeur spécifique de TargetFramework. Par exemple, Condition="'netstandard2.0' == '$(TargetFramework)'". Cela permet d'éviter que l'outil de génération de code ne soit lancé pour chaque Framework cible en même temps, puis d'obtenir des erreurs d'accès refusé lorsque les processus essaient de créer/mettre à jour les mêmes fichiers.

Cependant, les autres cadres cibles vont directement à essayer de compiler sans attendre la fin de la génération du code et échouer sans que ce code ne soit existant. Je souhaite que ma génération de code ne se produise qu'une fois chaque fois qu'un projet est construit et que la compilation de chaque Framework cible ne commence qu'une fois celle-ci terminée.

Il doit s'exécuter chaque fois qu'une version est exécutée, au cas où les entrées ont changé et génère un code différent. Remarque: Pour l'instant, j'ignore un cas où #if FrameworkSpecificDefine est utilisé pour avoir un code d'entrée différent du générateur de code, de sorte que différents cadres cibles entraînent des sorties différentes du générateur de code. Pour l'instant, je considère que la sortie du générateur de code est la même et valide pour tous les cadres cibles.

Mise à jour: Après avoir cherché une cible qui se passe avant MSBuild se divise en construit spécifique TargetFramework, que je pourrais alors accrocher à construire avant, je vois cela dans la sortie détaillée de construction dans VS:

1>Target _SetBuildInnerTarget: 
1>Target _ComputeTargetFrameworkItems: 
1>Target DispatchToInnerBuilds: 
1> Using "MSBuild" task from assembly "Microsoft.Build.Tasks.Core, Version=15.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a". 
1> Task "MSBuild" 
1> Additional Properties for project "ProjectA.csproj": 
1>  TargetFramework=netstandard2.0 
1> Additional Properties for project "ProjectA.csproj": 
1>  TargetFramework=net47 

I puis définissez ma cible comme BeforeTargets="DispatchToInnerBuilds" et elle s'exécute avant que les builds individuels qui définissent TargetFramework spécifiquement et semble répondre exactement à mes besoins.

(L'ajout à la propriété BuildDependsOn ne semble plus fonctionner: Add a msbuild task that runs after building a .NET Core project in Visual Studio 2017 RC; je suspecte que Microsoft.Common.targets est évalué plus tard dans le nouveau format csproj, et tout ajout aux propriétés que vous faites dans le fichier de projet sont écrasées par des arguments Microsoft.Common.Targets.)

+0

Serait-ce une fois ou une fois chaque fois que vous construisez? –

+0

Pouvez-vous injecter votre cible dans, disons, CoreBuildDependsOn, ou similaire? –

Répondre

0

Alors que certaines cibles ne s'exécutent que dans les builds internes, par ex. Lorsque vous utilisez BeforeTargets="BeforeBuild", la version externe définit également la variable IsCrossTargetingBuild pour indiquer que la version en cours d'exécution est la version externe distribuée à la version interne et constitue le moyen préféré de conditionner les cibles.

Vous pouvez donc conditionner votre cible comme Condition="'$(IsCrossTargetingBuild)' == 'true'" pour vous assurer que la cible n'est exécutée que pour la version externe.