Partager via


Exécuter une cible exactement une fois

Si vous créez un projet .NET pour plusieurs frameworks à l’aide du multitargeting du Kit de développement logiciel (SDK) .NET, chaque build est généralement une build complète de toutes les cibles pertinentes. Toutefois, dans certains cas, vous souhaitez qu’une cible spécifique ne s’exécute qu’une seule fois, par exemple une cible qui incrémente une version.

Configurer les cibles

La solution présentée ici exécute le MyBeforeBuildTarget une seule fois, que ce soit pour un seul cadre ou plusieurs cadres, sans modifier la cible elle-même.

  1. Ajoutez des expressions Condition qui utilisent la propriété Multitarget pour déterminer s’il faut créer plusieurs cadres, ou juste un seul.

    <PropertyGroup>
     <TargetFrameworks Condition=" '$(Multitarget)' == 'true' ">net7.0;net8.0</TargetFrameworks>
     <TargetFramework  Condition=" '$(Multitarget)' != 'true' ">net8.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
     <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
    </PropertyGroup>
    
  2. Ajoutez trois cibles au projet, le vôtre que vous souhaitez exécuter une seule fois (MyBeforeBuildTarget), les deux autres comme indiqué ici :

    <Project Sdk="Microsoft.NET.Sdk">
    
    <PropertyGroup>
        <TargetFrameworks Condition=" '$(Multitarget)' == 'true' ">net7.0;net8.0</TargetFrameworks>
        <TargetFramework  Condition=" '$(Multitarget)' != 'true' ">net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>
    </PropertyGroup>
    
    <Target Name="MyBeforeBuildTarget">
        <Warning Text="MyBeforeBuildTarget" />
    </Target>
    
    <Target Name="BuildMyBeforeBuildTargetBeforeOuterBuild"
            DependsOnTargets="MyBeforeBuildTarget"
            BeforeTargets="DispatchToInnerBuilds"
            />
    
    <Target Name="BuildMyBeforeBuildTargetBeforeInnerBuild"
            BeforeTargets="BeforeBuild">
       <MSBuild Projects="$(MSBuildProjectFullPath)"
             Targets="MyBeforeBuildTarget"
             RemoveProperties="TargetFramework" />
    </Target>
    
    </Project>
    

Cette méthode s’appuie sur la manière dont le multiciblage fonctionne dans les projets .NET SDK. Les builds externes définissent TargetFrameworks, tandis que les builds internes définissent TargetFramework pour chaque cible requise. Par conséquent, pour compiler une fois pour la compilation interne, supprimez la propriété TargetFramework. Cela appelle la compilation externe avec la cible désirée au lieu de l’exécuter dans chaque compilation interne.

Créer le projet

  1. À partir de la ligne de commande, construisez sans ciblage multiple :

    dotnet msbuild -nologo -tl:false -bl -clp:nosummary -p:Multitarget=false

    ExtendMaybeMultitargeted.csproj(12,5): warning : MyBeforeBuildTarget
    ExtendMaybeMultitargeted -> ExtendMaybeMultitargeted\bin\Debug\net8.0\ExtendMaybeMultitargeted.dll
    
  2. Essayez maintenant de créer avec le multi-ciblage :

    dotnet msbuild -nologo -tl:false -bl -clp:nosummary -p:Multitarget=true

    ExtendMaybeMultitargeted\ExtendMaybeMultitargeted.csproj(12,5): warning : MyBeforeBuildTarget
      ExtendMaybeMultitargeted -> ExtendMaybeMultitargeted\bin\Debug\net8.0\ExtendMaybeMultitargeted.dll
      ExtendMaybeMultitargeted -> ExtendMaybeMultitargeted\bin\Debug\net7.0\ExtendMaybeMultitargeted.dll
    

Comme vous pouvez le voir dans la sortie, l’avertissement n’a été émis qu’une seule fois, que le multi-ciblage ait été utilisé ou non.

La solution illustrée ici fonctionne parce que la cible que vous souhaitez exécuter une seule fois, MyBeforeBuildTarget, est liée à une autre cible à l’aide de BeforeTargets. Qu’importe si le ciblage multiple est vrai ou faux, la cible à laquelle elle est attachée s’exécute toujours une fois. La build externe est une cible unique, DispatchToInnerBuildsqui exécute la build interne pour toutes les différentes infrastructures spécifiées en TargetFrameworks; DispatchToInnerBuilds elle-même ne s’exécute qu’une seule fois pour une build multitargetée, mais pour une build ciblée unique, elle ne s’exécute pas du tout. Pour une build ciblée unique, vous définissez BeforeTargets sur BeforeBuild comme d'habitude pour exécuter votre cible, mais le Condition veille à ce qu'il ne soit attaché qu'à BeforeBuild dans le cas d'une cible unique.

Multiciblage du SDK .NET