Empaquetado de distribución de .NET

Como .NET 5 (y .NET Core) y las versiones posteriores están disponibles en cada vez más plataformas, resulta útil aprender a empaquetar y versionar aplicaciones y bibliotecas que lo usan, así como asignarles un nombre. De esta manera, los mantenedores de paquetes pueden ayudar a garantizar una experiencia coherente, independientemente de dónde los usuarios elijan ejecutar .NET. Este artículo resultará útil para los usuarios que:

  • Intentan compilar .NET desde el origen.
  • Quieren realizar cambios en la CLI de .NET que pueden afectar a la distribución o a los paquetes generados resultantes.

Diseño de disco

Cuando se instala, .NET consta de varios componentes que están dispuestos tal y como se indica a continuación en el sistema de archivos:

{dotnet_root}                    (0)              (*)
├── dotnet                       (1)
├── LICENSE.txt                  (8)
├── ThirdPartyNotices.txt        (8)
├── host                                          (*)
│   └── fxr                                       (*)
│       └── <fxr version>        (2)
├── sdk                                           (*)
│   └── <sdk version>            (3)
├── sdk-manifests                (4)              (*)
│   └── <sdk feature band version>
├── library-packs                (4)              (*)
├── metadata                     (4)              (*)
│   └── workloads
│       └── <sdk feature band version>
├── template-packs               (4)              (*)
├── packs                                         (*)
│   ├── Microsoft.AspNetCore.App.Ref              (*)
│   │   └── <aspnetcore ref version>     (11)
│   ├── Microsoft.NETCore.App.Ref                 (*)
│   │   └── <netcore ref version>        (12)
│   ├── Microsoft.NETCore.App.Host.<rid>          (*)
│   │   └── <apphost version>            (13)
│   ├── Microsoft.WindowsDesktop.App.Ref          (*)
│   │   └── <desktop ref version>        (14)
│   ├── NETStandard.Library.Ref                   (*)
│   │   └── <netstandard version>        (15)
│   ├── Microsoft.NETCore.App.Runtime.<rid>       (*)
│   │   └── <runtime version>            (18)
│   └── Microsoft.AspNetCore.App.Runtime.<rid>    (*)
│       └── <aspnetcore version>         (18)
├── shared                                        (*)
│   ├── Microsoft.NETCore.App                     (*)
│   │   └── <runtime version>     (5)
│   ├── Microsoft.AspNetCore.App                  (*)
│   │   └── <aspnetcore version>  (6)
│   ├── Microsoft.AspNetCore.All                  (*)
│   │   └── <aspnetcore version>  (6)
│   └── Microsoft.WindowsDesktop.App              (*)
│       └── <desktop app version> (7)
└── templates                                     (*)
│   └── <templates version>      (17)
/
├── etc/dotnet
│       └── install_location     (16)
├── usr/share/man/man1
│       └── dotnet.1.gz          (9)
└── usr/bin
        └── dotnet               (10)
  • (0) {dotnet_root} es una raíz compartida para todas las versiones principales y secundarias de .NET. Si se instalan varios entornos de ejecución, comparten la carpeta {dotnet_root}, por ejemplo, {dotnet_root}/shared/Microsoft.NETCore.App/6.0.11 y {dotnet_root}/shared/Microsoft.NETCore.App/7.0.0. El nombre de la carpeta {dotnet_root} debe ser independiente de la versión; es decir, simplemente dotnet.

  • (1) dotnet: el host (también conocido como "muxer") tiene dos roles diferentes: activar un entorno de ejecución para iniciar una aplicación y activar un SDK para enviarle comandos. El host es un ejecutable nativo (dotnet.exe).

Aunque hay un único host, la mayoría del resto de componentes está en directorios con versión (2,3,5,6). Esto significa que puede haber varias versiones en el sistema ya que se instalan en paralelo.

  • (2) host/fxr/<versión de fxr> contiene la lógica de resolución del marco que usa el host. El host usa la versión más reciente de hostfxr que está instalada. Hostfxr es responsable de seleccionar el entorno de ejecución adecuado cuando se ejecuta una aplicación .NET. Por ejemplo, una aplicación compilada para .NET 7.0.0 usa el runtime de 7.0.5 cuando esté disponible. De forma similar, hostfxr selecciona el SDK adecuado durante el desarrollo.

  • (3) sdk/<versión sdk> el SDK (también conocido como "las herramientas") es un conjunto de herramientas administradas que se usan para escribir y compilar aplicaciones y bibliotecas de .NET Core. El SDK incluye la CLI de .NET, los compiladores de lenguajes administrados, MSBuild, y las tareas y los destinos de compilación asociados, NuGet, nuevas plantillas de proyecto, etc.

  • (4) sdk-manifests/<sdk feature band version> (Los nombres y versiones de los recursos que requiere una instalación de carga de trabajo opcional se mantienen en los manifiestos de carga de trabajo almacenados en esta carpeta). El nombre de la carpeta es la versión de banda de características del SDK. Por lo tanto, para una versión del SDK como 7.0.102, esta carpeta todavía se denominaría 7.0.100. Cuando se instala una carga de trabajo, se crean las siguientes carpetas según sea necesario para los recursos de la carga de trabajo: paquetes de biblioteca, metadatos y paquetes de plantillas. Una distribución puede crear un archivo /metadata/workloads/<sdkfeatureband>/userlocal vacío si las cargas de trabajo deben instalarse en una ruta de acceso de usuario en lugar de en la carpeta dotnet. Para más información, consulte la incidencia de GitHub dotnet/installer#12104.

La carpeta shared contiene marcos. Un marco compartido proporciona un conjunto de bibliotecas en una ubicación central para que las puedan usar diferentes aplicaciones.

  • (5) shared/Microsoft.NETCore.App/<versión del entorno de ejecución> este marco contiene el entorno de ejecución de .NET y compatibilidad con las bibliotecas administradas.

  • (6) shared/Microsoft.AspNetCore.{App,All}/<versión de aspnetcore> contiene las bibliotecas de ASP.NET Core. Las bibliotecas de Microsoft.AspNetCore.App se desarrollan y se admiten como parte del proyecto de .NET. Las bibliotecas de Microsoft.AspNetCore.All son un superconjunto que también contiene bibliotecas de terceros.

  • (7) shared/Microsoft.Desktop.App/<versión de aplicación de escritorio> contiene las bibliotecas de escritorio de Windows. Esto no se incluye en plataformas que no son de Windows.

  • (8) LICENSE.txt,ThirdPartyNotices.txt son las licencias .NET y de bibliotecas de terceros que se usan en .NET, respectivamente.

  • (9,10) dotnet.1.gz, dotnet: dotnet.1.gz es la página manual de dotnet. dotnet es un vínculo simbólico al host(1) de dotnet. Estos archivos se instalan en ubicaciones bien conocidas para la integración del sistema.

  • (11,12) Microsoft.NETCore.App.Ref,Microsoft.AspNetCore.App.Ref describen la API de una versión x.y de .NET y de ASP.NET Core, respectivamente. Estos paquetes se utilizan al compilar para esas versiones de destino.

  • (13) Microsoft.NETCore.App.Host.<rid> contiene un binario nativo para la plataforma rid. Este archivo binario es una plantilla cuando se compila una aplicación .NET en un archivo binario nativo para esa plataforma.

  • (14) Microsoft.WindowsDesktop.App.Ref: describe la API de la versión x.y de las aplicaciones de escritorio de Windows. Estos archivos se usan al compilar para ese destino. Esto no se proporciona en plataformas que no son de Windows.

  • (15) NETStandard.Library.Ref: describe la API x.y de netstandard. Estos archivos se usan al compilar para ese destino.

  • (16) /etc/dotnet/install_location: es un archivo que contiene la ruta de acceso completa a {dotnet_root}. La ruta de acceso puede terminar con una nueva línea. No es necesario agregar este archivo cuando la raíz es /usr/share/dotnet.

  • (17) templates: contiene las plantillas que usa el SDK. Por ejemplo, dotnet new busca plantillas de proyecto aquí.

  • (18) Microsoft.NETCore.App.Runtime.<rid>/<runtime version>,Microsoft.AspNetCore.App.Runtime.<rid>/<aspnetcore version> Estos archivos permiten compilar aplicaciones independientes. Estos directorios contienen vínculos simbólicos a archivos en (2), (5) y (6).

Varios paquetes usan las carpetas marcadas con (*). Algunos formatos de paquete (por ejemplo, rpm) requieren un tratamiento especial de esas carpetas. El mantenedor de paquetes debe encargarse de esto.

El control de versiones de .NET se basa en los números de versión [major].[minor] del componente del entorno de ejecución. La versión del SDK usa el mismo valor [major].[minor] y tiene un valor [patch] independiente que combina la semántica de la característica y la revisión del SDK. Por ejemplo: la versión 7.0.302 del SDK es la segunda versión de revisión de la tercera versión de características del SDK que admite el runtime 7.0. Para obtener más información sobre el funcionamiento del control de versiones, vea la introducción al control de versiones de .NET.

Algunos de los paquetes incluyen parte del número de versión en su nombre. Esto permite instalar una versión concreta. No se incluye el resto de la versión en el nombre de la versión. Esto permite al administrador de paquetes del sistema operativo actualizar los paquetes (por ejemplo, instalar automáticamente correcciones de seguridad). Los administradores de paquetes compatibles son específicos de Linux.

A continuación se enumeran los paquetes recomendados:

  • dotnet-sdk-[major].[minor]: instala el SDK más reciente del runtime concreto

    • Versión:<versión de sdk>
    • Ejemplo: dotnet-sdk-7.0
    • Contiene: (3),(4),(18)
    • Dependencias:dotnet-runtime-[major].[minor], aspnetcore-runtime-[major].[minor], dotnet-targeting-pack-[major].[minor], aspnetcore-targeting-pack-[major].[minor], netstandard-targeting-pack-[netstandard_major].[netstandard_minor], dotnet-apphost-pack-[major].[minor] y dotnet-templates-[major].[minor]
  • aspnetcore-runtime-[major].[minor]: instala un runtime concreto de ASP.NET Core.

    • Versión:<versión aspnetcore de runtime>
    • Ejemplo: aspnetcore-runtime-7.0
    • Contiene: (6)
    • Dependencias:dotnet-runtime-[major].[minor]
  • dotnet-runtime-deps-[major].[minor](Opcional): instala las dependencias para ejecutar aplicaciones independientes

    • Versión:<versión de runtime>
    • Ejemplo: dotnet-runtime-deps-7.0
    • Dependencias:dependencias específicas de la distribución
  • dotnet-runtime-[major].[minor]: instala un runtime concreto.

    • Versión:<versión de runtime>
    • Ejemplo: dotnet-runtime-7.0
    • Contiene: (5)
    • Dependencias:dotnet-hostfxr-[major].[minor], dotnet-runtime-deps-[major].[minor]
  • dotnet-hostfxr-[major].[minor]: dependencia.

    • Versión:<versión de runtime>
    • Ejemplo: dotnet-hostfxr-7.0
    • Contiene: (2)
    • Dependencias:dotnet-host
  • dotnet-host: dependencia.

    • Versión:<versión de runtime>
    • Ejemplo: dotnet-host
    • Contiene: (1), (8), (9), (10), (16)
  • dotnet-apphost-pack-[major].[minor]: dependencia.

    • Versión:<versión de runtime>
    • Contiene: (13)
  • dotnet-targeting-pack-[major].[minor]: permite establecer como destino un runtime que no sea el más reciente.

    • Versión:<versión de runtime>
    • Contiene: (12)
  • aspnetcore-targeting-pack-[major].[minor]: permite establecer como destino un runtime que no sea el más reciente.

    • Versión:<versión aspnetcore de runtime>
    • Contiene: (11)
  • netstandard-targeting-pack-[netstandard_major].[netstandard_minor]: permite establecer como destino una versión de netstandard.

    • Versión:<versión de sdk>
    • Contiene: (15)
  • dotnet-templates-[major].[minor]

    • Versión:<versión de sdk>
    • Contiene: (17)

Los dos metapaquetes siguientes son opcionales. Aportan valor para los usuarios finales en el sentido de que abstraen el paquete de nivel superior (dotnet-sdk), que simplifica la instalación del conjunto completo de paquetes de .NET. Estos metapaquetes hacen referencia a una versión específica del SDK de .NET.

  • dotnet[major]: instala la versión del SDK especificada

    • Versión:<versión de sdk>
    • Ejemplo: dotnet7
    • Dependencias:dotnet-sdk-[major].[minor]
  • dotnet: instala una versión específica del SDK determinada por distribuciones para que sea la versión principal, normalmente la más reciente disponible

    • Versión:<versión de sdk>
    • Ejemplo: dotnet
    • Dependencias:dotnet-sdk-[major].[minor]

dotnet-runtime-deps-[major].[minor] requiere el conocimiento de las dependencias concretas de distribución. Dado que el sistema de compilación de distribución puede derivar esto de forma automática, el paquete es opcional, en cuyo caso estas dependencias se agregan directamente al paquete dotnet-runtime-[major].[minor].

Cuando el contenido del paquete se encuentra en una carpeta con versión, el nombre del paquete [major].[minor] coincide con el nombre de la carpeta con versión. En todos los paquetes, excepto en netstandard-targeting-pack-[netstandard_major].[netstandard_minor], esto también coincide con la versión de .NET.

Las dependencias entre paquetes deben usar un requisito de versión igual o mayor que. Por ejemplo, dotnet-sdk-7.0:7.0.401 requiere aspnetcore-runtime-7.0 >= 7.0.6. Esto hace posible que el usuario actualice su instalación mediante un paquete raíz (por ejemplo, dnf update dotnet-sdk-7.0).

La mayoría de las distribuciones requieren que todos los artefactos se compilen desde el origen. Esto tiene algún impacto en los paquetes:

  • Las bibliotecas de terceros de shared/Microsoft.AspNetCore.All no se pueden compilar fácilmente desde el origen. Por tanto, se omite esa carpeta en el paquete aspnetcore-runtime.

  • La carpeta NuGetFallbackFolder se rellena con artefactos binarios desde nuget.org. Debe permanecer vacía.

Es posible que varios paquetes dotnet-sdk proporcionen los mismos archivos para la carpeta NuGetFallbackFolder. Para evitar problemas con el administrador de paquetes, estos archivos deben ser idénticos (suma de comprobación, fecha de modificación, etc.).

Depurar paquetes

El contenido de depuración debe empaquetarse en paquetes con nombre de depuración que siguen la división de paquetes .NET descrita anteriormente en este artículo. Por ejemplo, el contenido de depuración del paquetedotnet-sdk-[major].[minor] debe incluirse en un paquete denominado dotnet-sdk-dbg-[major].[minor]. Debe instalar el contenido de depuración en la misma ubicación que los archivos binarios.

Estos son algunos ejemplos binarios:

En el directorio{dotnet_root}/sdk/<sdk version>, se esperan los dos archivos siguientes:

  • dotnet.dll : instalado con dotnet-sdk-[major].[minor] paquete
  • dotnet.pdb : instalado con dotnet-sdk-dbg-[major].[minor] paquete

En el directorio {dotnet_root}/shared/Microsoft.NETCore.App/<runtime version>, se esperan los dos archivos siguientes:

  • System.Text.Json.dll : instalado con dotnet-runtime-[major].[minor] paquete
  • System.Text.Json.pdb : instalado con dotnet-runtime-dbg-[major].[minor] paquete

En el directorio {dotnet_root/shared/Microsoft.AspNetCore.App/<aspnetcore version>, se esperan los dos archivos siguientes:

  • Microsoft.AspNetCore.Routing.dll : instalado con paquetes de aspnetcore-runtime-[major].[minor]
  • Microsoft.AspNetCore.Routing.pdb : instalado con paquetes de aspnetcore-runtime-dbg-[major].[minor]

A partir de .NET 8.0, todo el contenido de depuración de .NET (archivos PDB), generado por la compilación de origen, está disponible en un tarball denominado dotnet-symbols-sdk-<version>-<rid>.tar.gz. Este archivo contiene archivos PDF en subdirectorios que coinciden con la estructura de directorios del tarball del SDK de .NET: dotnet-sdk-<version>-<rid>.tar.gz.

Aunque todo el contenido de depuración está disponible en el tarball de depuración, no todo el contenido de depuración es igualmente importante. Los usuarios finales están interesados principalmente en el contenido de los directorios shared/Microsoft.AspNetCore.App/<aspnetcore version> y shared/Microsoft.NETCore.App/<runtime version>.

El contenido del SDK en sdk/<sdk version> es útil para depurar conjuntos de herramientas del SDK de .NET.

Los siguientes paquetes son los paquetes de depuración recomendados:

  • aspnetcore-runtime-dbg-[major].[minor]: instala el contenido de depuración para un entorno de ejecución de ASP.NET Core específico

    • Versión:<versión aspnetcore de runtime>
    • Ejemplo: aspnetcore-runtime-dbg-8.0
    • Contiene: contenido de depuración para (6)
    • Dependencias:aspnetcore-runtime-[major].[minor]
  • dotnet-runtime-dbg-[major].[minor] : instala el contenido de depuración para un entorno de ejecución específico

    • Versión:<versión de runtime>
    • Ejemplo: dotnet-runtime-dbg-8.0
    • Contiene: contenido de depuración para (5)
    • Dependencias:dotnet-runtime-[major].[minor]

El siguiente paquete de depuración es opcional:

  • dotnet-sdk-dbg-[major].[minor]: instala el contenido de depuración para una versión específica del SDK
    • Versión:<versión de sdk>
    • Ejemplo: dotnet-sdk-dbg-8.0
    • Contiene: contenido de depuración para (3),(4),(18)
    • Dependencias:dotnet-sdk-[major].[minor]

El tarball de depuración también contiene algún contenido de depuración en packs, que representa copias del contenido en shared. En el diseño de .NET, el directorio packs se usa para compilar aplicaciones .NET. No hay escenarios de depuración, por lo que no debe empaquetar el contenido de depuración en packs en el tarball de depuración.

Compilar paquetes

El repositorio dotnet/source-build proporciona instrucciones sobre cómo crear un paquete tarball de origen del SDK de .NET y todos sus componentes. La salida del repositorio de compilación de código fuente coincide con el diseño que se describe en la primera sección de este artículo.