Tutorial: Uso de MSBuild

MSBuild es la plataforma de compilación para Microsoft y Visual Studio. Este tutorial presenta los bloques de compilación de MSBuild y muestra la forma de escribir, manipular y depurar los proyectos de MSBuild. Aprenderá sobre los siguientes temas:

  • Crear y manipular un archivo del proyecto

  • Cómo usar las propiedades de compilación

  • Cómo usar los elementos de compilación

Puede ejecutar MSBuild desde Visual Studio o en la ventana de comandos. En este tutorial, creará un archivo del proyecto de MSBuild con Visual Studio. Editará el archivo del proyecto en Visual Studio y utilizará una ventana de comandos para compilar el proyecto y examinar los resultados.

Instalación de MSBuild

Si tiene Visual Studio, ya tiene MSBuild instalado. Con Visual Studio 2019 y versiones posteriores, se instala en la carpeta de instalación de Visual Studio. En el caso de una instalación predeterminada típica en Windows 10, MSBuild.exe se encuentra en la carpeta de instalación en MSBuild\Current\Bin.

En el instalador, asegúrese de que las herramientas de MSBuild para las cargas de trabajo que usa estén seleccionadas y seleccione Instalar.

Installing MSBuild

Para instalar MSBuild en un sistema que no tiene Visual Studio, vaya a Build Tools for Visual Studio 2019 (Herramientas de compilación para Visual Studio 2019) o instale el SDK de .NET.

Si tiene Visual Studio, ya tiene MSBuild instalado. Con Visual Studio 2022, se instala en la carpeta de instalación de Visual Studio. En el caso de una instalación predeterminada típica en Windows 10, MSBuild.exe se encuentra en la carpeta de instalación en MSBuild\Current\Bin.

En el instalador de Visual Studio, vaya a Componentes individuales y busque la casilla para MSBuild. Se selecciona automáticamente al elegir cualquiera de las demás cargas de trabajo que se instalarán.

Para instalar MSBuild en un sistema que no tiene Visual Studio, vaya a las herramientas de compilación para Visual Studio2022 en la página de descargas. Otra manera de obtener MSBuild es instalar el SDK de .NET.

Creación de un proyecto de MSBuild

El sistema de proyectos de Visual Studio se basa en MSBuild. Es fácil crear un archivo de proyecto mediante Visual Studio. En esta sección, creará un archivo de proyecto de C#. En su lugar, puede crear un archivo del proyecto de Visual Basic. En el contexto de este tutorial, la diferencia entre los dos archivos del proyecto es menor.

Para crear un archivo de proyecto

  1. Abra Visual Studio y cree un proyecto:

    En el cuadro de búsqueda, escriba winforms y, después, elija la opción para crear una nueva aplicación de Windows Forms (.NET Framework). En el cuadro de diálogo que se abre, elija Crear.

    En el cuadro Nombre del proyecto, escriba BuildApp. Escriba una ubicación para la solución, por ejemplo, D:\.

  2. Haga clic en Aceptar o Crear para crear el archivo del proyecto.

Examen del archivo de proyecto

En la sección anterior, usó Visual Studio para crear un archivo de proyecto de C#. El archivo del proyecto se representa en el Explorador de soluciones por el nodo de proyecto denominado BuildApp. Puede utilizar el editor de código de Visual Studio para examinar el archivo del proyecto.

Para examinar el archivo de proyecto

  1. En el Explorador de soluciones, haga clic en el nodo de proyecto BuildApp.

  2. En el navegador de Propiedades, observe que la propiedad Project File es BuildApp.csproj. Todos los nombres de los archivos de proyecto llevan el sufijo proj. Si hubiera creado un proyecto de Visual Basic, el nombre del archivo del proyecto sería BuildApp.vbproj.

  3. Haga clic con el botón secundario de nuevo en el nodo del proyecto y, a continuación, haga clic en Editar BuildApp.csproj.

    El archivo del proyecto aparece en el editor de código.

Nota

Para algunos tipos de proyecto, como C++, debe descargar el proyecto (haga clic con el botón derecho en el archivo del proyecto y elija Descargar el proyecto) para poder abrir y editar el archivo del proyecto.

Destinos y tareas

Los archivos del proyecto son archivos con formato XML y con el nodo raíz Project.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0"  xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

La mayoría de los proyectos de .NET tienen un atributo Sdk. Estos proyectos se denominan proyectos de estilo SDK.

<Project Sdk="Microsoft.NET.Sdk">

Hay muchas variaciones de los SDK de .NET para fines especiales; se describen en SDK de proyectos de .NET.

El trabajo de compilar una aplicación se realiza con los elementos Target y Task.

  • Una tarea es la unidad de trabajo más pequeña, en otras palabras, el "átomo" de una compilación. Las tareas son componentes ejecutables independientes, que pueden tener entradas y salidas. No hay actualmente ninguna tarea a la que se haga referencia o que esté definida en el archivo del proyecto. Podrá agregar tareas al archivo del proyecto en las secciones siguientes. Para obtener más información, consulte Tareas.

  • Un destino es una secuencia con nombre de tareas. Podría tratarse de una secuencia de tareas con nombre, pero, de forma crítica, representa algo que se va a compilar o hacer, por lo que debe definirse de forma orientada a objetivos. Para obtener más información, consulte Destinos.

El destino predeterminado no se define en el archivo del proyecto, En su lugar, se especifica en proyectos importados. El elemento Import indica los proyectos importados. Por ejemplo, en un proyecto de C#, el destino predeterminado se importa del archivo Microsoft.CSharp.targets.

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Los archivos importados se insertan realmente en el archivo del proyecto, dondequiera que se les haga referencia.

En proyectos de estilo SDK no se ve este elemento de importación porque el atributo de SDK hace que este archivo se importe de forma implícita.

MSBuild realiza el seguimiento de los destinos de una compilación y garantiza que cada destino se compile solamente una vez.

Agregar un destino y una tarea

Agregue un destino al archivo del proyecto. Agregue una tarea al destino que imprime un mensaje.

Para agregar un destino y una tarea

  1. Agregue estas líneas al archivo del proyecto, justo después de la instrucción Import o del elemento Project de apertura:

    <Target Name="HelloWorld">
    </Target>
    

    Este código crea un destino denominado HelloWorld. Observe que tiene compatibilidad con IntelliSense mientras edita el archivo del proyecto.

  2. Agregue líneas al destino HelloWorld para que la sección resultante sea similar a esta:

    <Target Name="HelloWorld">
      <Message Text="Hello"></Message>  <Message Text="World"></Message>
    </Target>
    
  3. Guarde el archivo de proyecto.

La tarea Message es una de las muchas tareas que se distribuyen con MSBuild. Para obtener una lista completa de tareas disponibles e información de uso, consulte Referencia de tareas.

La tarea Message toma el valor de cadena del atributo Text como entrada y lo muestra en el dispositivo de salida (o lo escribe en uno o varios registros, si procede). El destino HelloWorld ejecuta la tarea Message dos veces: primero para mostrar "Hello" y luego para mostrar "World".

Compilación del destino

Si intenta compilar este proyecto desde Visual Studio, no se compilará el destino que ha definido. Esto se debe a que Visual Studio elige el destino predeterminado, que sigue siendo el del archivo .targets importado.

Ejecute MSBuild desde el Símbolo del sistema para desarrolladores de Visual Studio para compilar el destino HelloWorld definido anteriormente. Utilice el modificador de línea de comandos -target o -t para seleccionar el destino.

Nota:

Haremos referencia al Símbolo del sistema para desarrolladores como la ventana Comandos en las secciones siguientes.

Para compilar el destino:

  1. Abra la ventana Comandos.

    En el cuadro de búsqueda de la barra de tareas, comience a escribir el nombre de la herramienta, como dev o developer command prompt. Esto muestra una lista de las aplicaciones instaladas que coinciden con el patrón de búsqueda.

    Si tiene que buscarlo manualmente, es el archivo LaunchDevCmd.bat de la carpeta {carpeta de instalación de Visual Studio}\Common7\Tools.

  2. En la ventana de comandos, navegue hasta la carpeta que contiene el archivo de proyecto, en este caso, D:\BuildApp\BuildApp.

  3. Ejecute msbuild con el modificador de comando -t:HelloWorld. Este comando selecciona y compila el destino HelloWorld:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine la salida en la ventana Comandos. Debe ver las dos líneas "Hello" y "World":

    Hello
    World
    

Nota

Si en su lugar ve The target "HelloWorld" does not exist in the project, es probable que se haya olvidado de guardar el archivo del proyecto en el editor de código. Guarde el archivo y vuelva a intentarlo.

Alternando entre el editor de código y la ventana Comandos, puede cambiar el archivo del proyecto y ver rápidamente los resultados.

Propiedades de compilación

Las propiedades de compilación son pares de nombre y valor que guían la compilación. Ya se han definido varias propiedades de compilación al principio del archivo del proyecto:

<PropertyGroup>
...
  <ProductVersion>10.0.11107</ProductVersion>
  <SchemaVersion>2.0</SchemaVersion>
  <ProjectGuid>{30E3C9D5-FD86-4691-A331-80EA5BA7E571}</ProjectGuid>
  <OutputType>WinExe</OutputType>
...
</PropertyGroup>

Todas las propiedades son elementos secundarios de elementos PropertyGroup. El nombre de la propiedad es el nombre del elemento secundario y el valor de la propiedad es el elemento de texto del elemento secundario. Por ejemplo,

<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>

define la propiedad denominada TargetFrameworkVersion y le da el valor de cadena "v4.5".

Las propiedades de compilación se pueden redefinir en cualquier momento. Si

<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>

aparece más adelante en el archivo del proyecto, o en un archivo importado posteriormente en el archivo del proyecto, TargetFrameworkVersion toma el nuevo valor "v3.5".

Examen del valor de una propiedad

Para obtener el valor de una propiedad, utilice la sintaxis siguiente, donde PropertyName es el nombre de la propiedad:

$(PropertyName)

Utilice esta sintaxis para examinar algunas de las propiedades en el archivo del proyecto.

Para examinar el valor de una propiedad

  1. En el editor de código, reemplace el destino HelloWorld por este código:

    <Target Name="HelloWorld">
      <Message Text="Configuration is $(Configuration)" />
      <Message Text="MSBuildToolsPath is $(MSBuildToolsPath)" />
    </Target>
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debería ver estas dos líneas (la salida puede diferir):

    Configuration is Debug
    MSBuildToolsPath is C:\Program Files\Microsoft Visual Studio\2022\MSBuild\Current\Bin\amd64
    
    Configuration is Debug
    MSBuildToolsPath is C:\Program Files (x86)\Microsoft Visual Studio\2019\MSBuild\16.0\Bin
    

Propiedades condicionales

Muchas propiedades, como Configuration, se definen condicionalmente; es decir, el atributo Condition aparece en el elemento de propiedad. Las propiedades condicionales se definen o vuelven a definir solo si la condición se evalúa como "true". Las propiedades no definidas reciben el valor predeterminado de una cadena vacía. Por ejemplo,

<Configuration   Condition=" '$(Configuration)' == '' ">Debug</Configuration>

significa "Si la propiedad Configuration no se ha definido todavía, defínala y dele el valor 'Debug'".

Casi todos elementos de MSBuild pueden tener un atributo Condition. Para obtener más información sobre cómo utilizar el atributo Condition, consulte Condiciones.

Propiedades reservadas

MSBuild reserva algunos nombres de propiedades para almacenar información sobre el archivo del proyecto y los archivos binarios de MSBuild. MSBuildToolsPath es un ejemplo de una propiedad reservada. Como a cualquier otra propiedad, a las propiedades reservadas se hace referencia con la notación $. Para obtener más información, vea Cómo: Hacer referencia al nombre o la ubicación del archivo del proyecto y Propiedades reservadas y conocidas de MSBuild.

Variables de entorno

En los archivos del proyecto, se puede hacer referencia a las variables de entorno como si fueran propiedades de compilación. Por ejemplo, para utilizar la variable de entorno PATH en el archivo de proyecto, utilice $(Path). Si el proyecto incluye la definición de una propiedad que tiene el mismo nombre que una variable de entorno, la propiedad del proyecto reemplaza el valor de la variable de entorno. Para obtener más información, vea Cómo: Usar variables de entorno al compilar.

Establecimiento de propiedades desde la línea de comandos

Las propiedades se pueden definir en la línea de comandos utilizando el modificador de línea de comandos -property o -p. Los valores de propiedad recibidos desde la línea de comandos invalidan los valores de propiedad establecidos en el archivo del proyecto y las variables de entorno.

Para establecer el valor de una propiedad desde la línea de comandos:

  1. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld -p:Configuration=Release
    
  2. Examine los resultados. Debe ver esta línea:

    Configuration is Release.
    

MSBuild crea la propiedad Configuration y le asigna el valor "Release".

Caracteres especiales

Ciertos caracteres tienen un significado especial en archivos del proyecto de MSBuild. Ejemplos de estos caracteres son los signos de punto y coma (;) y los asteriscos (*). Para utilizar estos caracteres especiales con su significado literal en un archivo del proyecto, es preciso especificarlos con la sintaxis %<xx>, en que <xx> representa el valor hexadecimal ASCII del carácter.

Cambie la tarea Message para mostrar el valor de la propiedad Configuration con caracteres especiales para que se pueda leer mejor.

Para utilizar caracteres especiales en la tarea Message:

  1. En el editor de código, reemplace ambas tareas Message por esta línea:

    <Message Text="%24(Configuration) is %22$(Configuration)%22" />
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debe ver esta línea:

    $(Configuration) is "Debug"
    

Para más información, consulte Caracteres especiales de MSBuild.

Elementos de compilación

Un elemento es un fragmento de información, normalmente un nombre de archivo, que se utiliza como entrada al sistema de compilación. Por ejemplo, una colección de elementos que representan archivos de código fuente pueden pasarse a una tarea denominada Compile para compilarlos en un ensamblado.

Todos los elementos son elementos secundarios de elementos ItemGroup. El nombre de elemento es el nombre del elemento secundario y el valor de elemento es el valor del atributo Include del elemento secundario. Los valores de elementos con el mismo nombre se agrupan en tipos de elemento de ese nombre. Por ejemplo,

<ItemGroup>
    <Compile Include="Program.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

define un grupo de elementos que contiene dos elementos. El tipo de elemento Compile tiene dos valores: Program.cs y Properties\AssemblyInfo.cs.

El código siguiente crea el mismo tipo de elemento declarando ambos archivos en un atributo Include, separados por punto y coma.

<ItemGroup>
    <Compile Include="Program.cs;Properties\AssemblyInfo.cs" />
</ItemGroup>

Para obtener más información, consulte Elementos.

Nota

Las rutas de acceso de archivo son relativas a la carpeta que contiene el archivo del proyecto de MSBuild, incluso aunque el archivo del proyecto sea uno importado. Hay algunas excepciones a esto, como cuando se usan elementos Import y UsingTask.

Examen de los valores de tipo de elemento

Para obtener los valores de un tipo de elemento, utilice la sintaxis siguiente, donde ItemType es el nombre del tipo de elemento:

@(ItemType)

Utilice esta sintaxis para examinar el tipo de elemento Compile en el archivo del proyecto.

Para examinar los valores de tipo de los elementos:

  1. En el editor de código, reemplace la tarea de destino HelloWorld por este código:

    <Target Name="HelloWorld">
      <Message Text="Compile item type contains @(Compile)" />
    </Target>
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debe ver esta línea larga:

    Compile item type contains Form1.cs;Form1.Designer.cs;Program.cs;Properties\AssemblyInfo.cs;Properties\Resources.Designer.cs;Properties\Settings.Designer.cs
    

Los valores de un tipo de elemento se separan de forma predeterminada con puntos y coma.

Para cambiar el separador de un tipo de elemento, utilice la sintaxis siguiente, donde ItemType es el tipo de elemento y Separator es una cadena de uno o más caracteres de separación:

@(ItemType, Separator)

Cambie la tarea Message para utilizar retornos de carro y saltos de línea (% 0A%0D) con el fin de mostrar los elementos Compile uno por línea.

Para mostrar los valores de tipo de elemento uno por línea

  1. En el editor de código, reemplace la tarea Message por esta línea:

    <Message Text="Compile item type contains @(Compile, '%0A%0D')" />
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debe ver las siguientes líneas:

    Compile item type contains Form1.cs
    Form1.Designer.cs
    Program.cs
    Properties\AssemblyInfo.cs
    Properties\Resources.Designer.cs
    Properties\Settings.Designer.cs
    

Include, Exclude y caracteres comodín

Puede utilizar los caracteres comodín "*", "**" y "?" con el atributo Include para agregar elementos a un tipo de elemento. Por ejemplo,

<Photos Include="images\*.jpeg" />

agrega todos los archivos con la extensión .jpeg de la carpeta images al tipo de elemento Photos, mientras que

<Photos Include="images\**\*.jpeg" />

agrega todos los archivos con la extensión .jpeg de la carpeta images, y todas sus subcarpetas, al tipo de elemento Photos. Para obtener más ejemplos, vea Cómo: Seleccionar los archivos que se van a compilar.

Observe que según se declaran elementos se agregan al tipo de elemento. Por ejemplo,

<Photos Include="images\*.jpeg" />
<Photos Include="images\*.gif" />

crea un tipo de elemento denominado Photo que contiene todos los archivos de la carpeta images con una extensión .jpeg o .gif. Estas líneas son equivalentes a la línea siguiente:

<Photos Include="images\*.jpeg;images\*.gif" />

Puede excluir un elemento de un tipo de elemento con el atributo Exclude. Por ejemplo,

<Compile Include="*.cs" Exclude="*Designer*">

agrega todos los archivos con la extensión .cs al tipo de elemento Compile, salvo los archivos cuyos nombres contienen la cadena Designer. Para obtener más ejemplos, vea Cómo: Excluir archivos de la compilación.

El atributo Exclude solamente afecta a los elementos agregados por el atributo Include en el elemento que contiene ambos. Por ejemplo,

<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">

no excluiría el archivo Form1.cs, que se agregó en el elemento anterior.

Para incluir y excluir elementos

  1. En el editor de código, reemplace la tarea Message por esta línea:

    <Message Text="XFiles item type contains @(XFiles)" />
    
  2. Agregue este grupo de elementos justo después del elemento Import:

    <ItemGroup>
       <XFiles Include="*.cs;properties/*.resx" Exclude="*Designer*" />
    </ItemGroup>
    
  3. Guarde el archivo de proyecto.

  4. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  5. Examine los resultados. Debe ver esta línea:

    XFiles item type contains Form1.cs;Program.cs;Properties/Resources.resx
    

Metadatos de elementos

Los elementos pueden contener metadatos además de la información recopilada de los Include atributos y Exclude. Las tareas que requieren más información sobre los elementos que solo el valor del elemento pueden usar estos metadatos.

Los metadatos de elementos se declaran en el archivo de proyecto creando un elemento con el nombre de los metadatos como elemento secundario del elemento. Un elemento puede tener cero o varios valores de metadatos. Por ejemplo, el elemento CSFile siguiente tiene los metadatos Culture con un valor de "Fr":

<ItemGroup>
    <CSFile Include="main.cs">
        <Culture>Fr</Culture>
    </CSFile>
</ItemGroup>

Para obtener el valor de metadatos de un tipo de elemento, utilice la sintaxis siguiente, donde ItemType es el nombre del tipo de elemento y MetaDataName es el nombre de los metadatos:

%(ItemType.MetaDataName)

Para examinar los metadatos de los elementos:

  1. En el editor de código, reemplace la tarea Message por esta línea:

    <Message Text="Compile.DependentUpon: %(Compile.DependentUpon)" />
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debe ver las siguientes líneas:

    Compile.DependentUpon:
    Compile.DependentUpon: Form1.cs
    Compile.DependentUpon: Resources.resx
    Compile.DependentUpon: Settings.settings
    

Observe cómo la frase "Compile.DependentUpon" aparece varias veces. El uso de metadatos con esta sintaxis dentro de un destino produce el "procesamiento por lotes". El procesamiento por lotes significa que las tareas dentro del destino se ejecutan una vez para cada valor de metadatos único. El procesamiento por lotes es el equivalente del script de MSBuild de la construcción de programación "bucle foreach" común. Para obtener más información, consulte Procesamiento por lotes.

Metadatos conocidos

Cada vez que se agrega un elemento a una lista de elementos, se le asignan metadatos conocidos. Por ejemplo, %(Filename) devuelve el nombre de archivo de cualquier elemento. Para obtener una lista completa de metadatos conocidos, consulte Metadatos de elementos conocidos.

Para examinar los metadatos conocidos:

  1. En el editor de código, reemplace la tarea Message por esta línea:

    <Message Text="Compile Filename: %(Compile.Filename)" />
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debe ver las siguientes líneas:

    Compile Filename: Form1
    Compile Filename: Form1.Designer
    Compile Filename: Program
    Compile Filename: AssemblyInfo
    Compile Filename: Resources.Designer
    Compile Filename: Settings.Designer
    

Comparando los dos ejemplos anteriores, puede ver que mientras que no todos los elementos del tipo de elemento Compile tiene metadatos DependentUpon, todos los elementos tienen metadatos Filename conocidos.

Transformaciones de metadatos

Las listas de elementos se pueden transformar en nuevas listas de elementos. Para transformar una lista de elementos, utilice la sintaxis siguiente, donde <ItemType> es el nombre del tipo de elemento y <MetadataName> es el nombre de los metadatos:

@(ItemType -> '%(MetadataName)')

Por ejemplo, una lista de elementos de archivos de origen se puede transformar en una colección de archivos de objeto mediante una expresión como @(SourceFiles -> '%(Filename).obj'). Para obtener más información, consulte Transformaciones.

Para transformar elementos mediante metadatos:

  1. En el editor de código, reemplace la tarea Message por esta línea:

    <Message Text="Backup files: @(Compile->'%(filename).bak')" />
    
  2. Guarde el archivo de proyecto.

  3. Desde la ventana Comandos, escriba y ejecute la siguiente línea:

    msbuild buildapp.csproj -t:HelloWorld
    
  4. Examine los resultados. Debe ver esta línea:

    Backup files: Form1.bak;Form1.Designer.bak;Program.bak;AssemblyInfo.bak;Resources.Designer.bak;Settings.Designer.bak
    

Observe que los metadatos expresados en esta sintaxis no producen el procesamiento por lotes.

Pasos siguientes

Para obtener información sobre cómo crear un archivo de proyecto sencillo paso a paso en Windows, consulte Crear un archivo de proyecto de MSBuild desde cero.

Si usa principalmente el SDK de .NET, siga leyendo en Referencia de MSBuild para proyectos del SDK de .NET.