Compartir a través de


Ejecutar un destino exactamente una vez

Si va a compilar un proyecto de .NET para múltiples frameworks mediante el multitargeting del SDK de .NET, por lo general, cada compilación es una compilación completa de todos los destinos pertinentes. Sin embargo, en algunos casos, desea que un objetivo determinado solo se ejecute una vez, por ejemplo, un objetivo que incremente una versión.

Configura los destinos

La solución que se muestra aquí ejecuta el MyBeforeBuildTarget una vez y solo una vez, independientemente de si se está compilando un solo framework o varios frameworks, sin cambiar el destino en sí.

  1. Agregue Condition expresiones que usen la Multitarget propiedad para determinar si se van a compilar varios frameworks o solo uno.

    <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. Agregue tres objetivos al proyecto: el tuyo, que deseas ejecutar una sola vez (MyBeforeBuildTarget), y los otros dos, tal como se muestra aquí.

    <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>
    

Este método se basa en la forma en que el destino múltiple funciona en proyectos del SDK de .NET. Las compilaciones externas establecen TargetFrameworks, pero las internas establecen TargetFramework para cada objetivo deseado. Por lo tanto, para compilar una vez para el build interno, quite la propiedad TargetFramework. Esto invoca la compilación externa con el destino deseado en lugar de ejecutarla en cada una de las compilaciones internas.

Construir el proyecto

  1. Desde la línea de comandos, compile sin multiestinación:

    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. Ahora intente crear con multitargeting:

    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
    

Como puede ver en el resultado, la advertencia solo se emitió una vez, independientemente de si se usó o no multitargeting.

La solución que se muestra aquí funciona porque el destino al que desea ejecutar una vez, MyBeforeBuildTarget, está vinculado a otro destino mediante BeforeTargets, pero independientemente de si el destino múltiple es true o false, el destino al que está asociado siempre es uno que se ejecuta una vez. La compilación externa es un único objetivo, DispatchToInnerBuilds, que ejecuta la compilación interna para todos los diferentes marcos especificados en TargetFrameworks; DispatchToInnerBuilds se ejecuta solo una vez en una compilación con múltiples objetivos, pero para una compilación con un único objetivo, no se ejecuta en absoluto. En el caso de una sola compilación específica, se establece BeforeTargets como BeforeBuild como de costumbre para ejecutar el destino, pero Condition se asegura de que esté asociado solo a BeforeBuild en el caso de un solo destino.

Multidestino del SDK de .NET