msbuild: establezca un preprocesador específico #define en la línea de comando

7 minutos de lectura

avatar de usuario de acemtp
acemtp

En un archivo C++, tengo un código como este:

#if ACTIVATE
#   pragma message( "Activated" )
#else
#   pragma message( "Not Activated")
#endif

Quiero establecer esta definición ACTIVA en 1 con la línea de comandos de msbuild.

Intentó esto pero no funciona:

msbuild /p:DefineConstants="ACTIVATE=1"

¿Alguna idea?

avatar de usuario de bigh_29
grande_29

Llegué un poco tarde a la fiesta (solo 4 años más o menos), pero tuve que solucionar este problema en un proyecto y me encontré con esta pregunta mientras buscaba una solución. Nuestra solución fue usar una variable de entorno con /D define en él, combinado con el cuadro Opciones adicionales en Visual Studio.

  1. En Visual Studio, agregue una macro de variable de entorno, $(ExternalCompilerOptions)a las Opciones adicionales en las opciones del proyecto->C/C++->Línea de comandos (recuerde las configuraciones de depuración y liberación)
  2. Establezca la variable de entorno antes de llamar a msbuild. Utilizar el /D opción del compilador para definir sus macros
    c:\> set ExternalCompilerOptions=/DFOO /DBAR 
    c:\> msbuild

El elemento n. ° 1 termina luciendo así en el archivo vcxproj:

    <ClCompile>
      <AdditionalOptions>$(ExternalCompilerOptions) ... </AdditionalOptions>
    </ClCompile>

Esto funciona para mí con VS 2010. Manejamos msbuild desde varios scripts de compilación, por lo que la variable de entorno ugliness está un poco oculta. Tenga en cuenta que no he probado si esto funciona cuando necesita establecer la definición en un valor específico ( /DACTIVATE=1 ). Creo que funcionaría, pero me preocupa tener múltiples ‘=’ allí.

H ^ 2

  • Gracias por la respuesta tardía 🙂

    – Acemtp

    8 de enero de 2013 a las 6:42

  • Para configurar las definiciones al crear archivos de recursos, configure también las Opciones adicionales en Propiedades de configuración -> Recursos -> Línea de comando

    – Radó

    13 de abril de 2016 a las 16:27

  • ¡Me salvas el día!

    – l2m2

    17 de marzo a las 1:38

Avatar de usuario de Mac
Mac

Los proyectos (y soluciones) de C++ no están (¿aún?) integrados en el entorno de MSBuild. Como parte del proceso de construcción, el tarea VCBuild se llama, que es solo un envoltorio vcbuild.exe.

Tú podrías :

  • cree una configuración específica para su solución donde ACTIVATE=1 sería definido, y compilarlo con devenv.exe (con el /ProyectoConfig cambiar).
  • cree su propio archivo de destino para envolver su propia llamada al tarea VCBuild (ver el parámetro Override)…
  • use vcbuild.exe en lugar de msbuild.exe. (vcbuild.exe no parece tener el equivalente de un parámetro Override).

Tenga en cuenta que su solución tampoco funcionaría para proyectos de C# a menos que modificara un poco los archivos de su proyecto. Como referencia, así es como haría esto:

  • Agregue el siguiente código antes de la llamada a <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> :
<PropertyGroup Condition=" '$(MyConstants)' != '' ">
  <DefineConstants>$(DefineConstants);$(MyConstants)</DefineConstants>
</PropertyGroup>
  • Llame a MSBuild así:
msbuild /p:MyConstants="ACTIVATE=1"

  • Puedo usar vcbuild.exe en lugar de msbuild.exe pero la pregunta es la misma. ¿Cómo configurar un preprocesador específico en la línea de comandos de vcbuild?

    – Acemtp

    3 de octubre de 2008 a las 12:31

  • Tiene razón: asumí erróneamente que vcbuild.exe tenía el mismo conjunto de parámetros que la tarea VCBuild. Respuesta actualizada.

    – Mac

    3 de octubre de 2008 a las 12:49

  • Buen tiro, <DefineConstants>$(DefineConstants);$(MyConstants)</DefineConstants>eso es lo que quiero.

    – JasonMing

    29 de septiembre de 2014 a las 3:31

Avatar de usuario de 4LegsDrivenCat
4PiernasImpulsadoGato

Si necesita definir alguna constante (no solo true/false), puedes hacerlo de la siguiente manera:

En línea de comando:

MSBuild /p:MyDefine=MyValue

En el archivo vcxproj (en la sección <ClCompile>; y/o <ResourceCompile>dependiendo de dónde lo necesites):

<PreprocessorDefinitions>MY_DEFINE=$(MyDefine);$(PreprocessorDefinitions)</PreprocessorDefinitions>

Tenga en cuenta que si no especifica /p:MyDefine=MyValue en una llamada a MSBuild entonces se asignará una cadena vacía a MY_DEFINE macro. Si está bien para ti, eso es todo. Si no, sigue leyendo.

Cómo hacer que una macro no esté definida si no se especifica el parámetro correspondiente de MSBuild

Tener MY_DEFINE macro indefinida en lugar de una cadena vacía, puede usar el siguiente truco:

<ClCompile>
  ....
  <PreprocessorDefinitions>_DEBUG;_CONSOLE;OTHER_UNCONDITIONAL_MACROS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
  <PreprocessorDefinitions Condition="'$(MyDefine)'!=''">MY_DEFINE=$(MyDefine);%(PreprocessorDefinitions)</PreprocessorDefinitions>
  ....
</ClCompile>

Primero PreprocessorDefinitions define macros incondicionales. Segundo PreprocessorDefinitions además define MY_DEFINE macro cuando MyDefine no es una cadena vacía. Puede probar esto colocando el siguiente fragmento de código en su archivo cpp:

#define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(x)

#ifndef MY_DEFINE
#pragma message("MY_DEFINE is not defined.")
#else
#pragma message("MY_DEFINE is defined to: [" STRINGIZE(MY_DEFINE) "]")
#endif

y corriendo:

> MSBuild SandBox.sln /p:Configuration=Debug /p:MyDefine=test /t:Rebuild
...
MY_DEFINE is defined to: [test]
...

> MSBuild SandBox.sln /p:Configuration=Debug /p:MyDefine= /t:Rebuild
...
MY_DEFINE is not defined.
...

> MSBuild SandBox.sln /p:Configuration=Debug /t:Rebuild
...
MY_DEFINE is not defined.
...

  • ¿Es posible agregar MY_DEFINE=$(MyDefine) en proyectos propiedades?

    – s4eed

    18 de mayo de 2018 a las 10:48

  • @s4eed Sí, abra el cuadro de diálogo de propiedades del proyecto, seleccione Configuración específica (por ejemplo, Depuración) y Plataforma (por ejemplo, Win32), vaya a C/C++ -> Sección de preprocesador y agregue “MY_DEFINE=$(MyDefine);” delante de otras definiciones en el campo Definiciones de preprocesador. Por ejemplo, si tenía “a=b;$(PreprocessorDefinitions)” en ese campo, conviértalo en “MY_DEFINE=$(MyDefine);a=b;$(PreprocessorDefinitions)”. Haga lo mismo en la sección Recursos -> General si es necesario.

    – 4LegsDrivenCat

    19 de julio de 2018 a las 13:56


  • Repita esto para otras configuraciones y plataformas.

    – 4LegsDrivenCat

    19 de julio de 2018 a las 14:02

  • Esto parece más limpio que la respuesta principal, que establece variables de entorno y funciona en MSBuild 16.1.76. Es posible que desee agregar #ifndef guardias a las constantes para silenciar las advertencias.

    – MakotoE

    2 de julio de 2019 a las 1:15

  • El desafío con esta solución es que MY_DEFINE siempre está definido, al menos hasta la cadena vacía. Esto es difícil de probar. La sugerencia de @MakotoE con #ifndef no funciona.

    – Troels Blum

    13 de noviembre de 2019 a las 14:59

Creo que quieres:

/p:DefineConstants=ACTIVATE

Use la variable de entorno CL para definir macros de preprocesador

Antes de llamar a MSBUILD, simplemente configure la variable de entorno ‘CL’ con las opciones ‘/D’ así:

set CL=/DACTIVATE para definir ACTIVAR

Puede usar el símbolo ‘#’ para reemplazar el signo ‘=’

set CL=/DACTIVATE#1 definirá ACTIVATE=1

Luego haga la llamada a MSBUILD

Se puede encontrar más documentación sobre las variables de entorno CL en:
https://msdn.microsoft.com/en-us/library/kezkeayy(v=vs.140).aspx

Tal vez sea una mala idea responder una pregunta tan antigua, pero recientemente busqué en Google un problema similar y encontré este tema. Escribí un script cmd para algún sistema de compilación y logré encontrar una solución. Lo dejo aquí para las futuras generaciones (:

Según el problema de @acemtp, mi solución se vería así:

@echo off

:: it is considered that Visual Studio tools are in the PATH
if "%1"=="USE_ACTIVATE_MACRO" (
    :: if parameter USE_ACTIVATE_MACRO is passed to script
    :: the macro ACTIVATE will be defined for the project
    set CL=/DACTIVATE#1
)
call msbuild /t:Rebuild /p:Configuration=Release

UPD: Traté de usar set CL=/DACTIVATE=1 y también funcionó, pero el documentación oficial recomienda usar símbolo de número

Avatar de usuario de Bruce Ikin
bruce ikin

También necesitaba hacer esto: necesitaba poder compilar dos versiones diferentes de mi aplicación y quería poder programar la compilación con VCBUILD. VCBUILD tiene el interruptor de línea de comando /override, pero no estoy seguro de que se pueda usar para modificar los símbolos #define que luego se pueden probar usando la compilación condicional #if.

La solución que se me ocurrió fue escribir una utilidad simple para crear un archivo de encabezado que #definiera el símbolo en función del estado de una variable de entorno y ejecutar la utilidad desde un paso previo a la compilación. Antes de cada ejecución del paso VCBUILD, el script establece la variable de entorno y “toca” un archivo en la aplicación para garantizar que se ejecute el paso de precompilación.

Sí, es un truco feo, ¡pero fue lo mejor que se me ocurrió!

¿Ha sido útil esta solución?