delphi conditional-compilation

¿Cómo definir la versión "and up" de ifdefs en Delphi?



conditional-compilation (4)

Estaba trabajando para que Log4D funcionara en Delphi XE4, y recibía algunos errores de compilación porque no podía encontrar Contnrs en la cláusula de usos, a menos que lo moviera fuera del ifdef en el que estaba definido.

{$IFDEF DELPHI5_UP} Contnrs, {$ENDIF}

Un poco de investigación descubrió que el ifdef está definido en un archivo incluido Defines.inc que tiene un bloque para cada versión "soportada" de delphi que detiene algunas versiones atrás:

p.ej:

{$IFDEF VER170} { Delphi 2005 } {$DEFINE DELPHI9} {$DEFINE DELPHI4_UP} {$DEFINE DELPHI5_UP} {$DEFINE DELPHI6_UP} {$DEFINE DELPHI7_UP} {$ENDIF} {$IFDEF VER180} { Delphi 2006 } {$DEFINE DELPHI10} {$DEFINE DELPHI4_UP} {$DEFINE DELPHI5_UP} {$DEFINE DELPHI6_UP} {$DEFINE DELPHI7_UP}

Entonces, si bien sería bastante fácil seguir adelante, copiar y pegar el ifdef para Delphi 2006 y crear un bloque Delphi XE4 ... esto parece una solución poco elegante. Definitivamente no es una prueba de futuro ... cada nueva versión a la que debe actualizar este archivo ahora, por lo que un código que no estaba presente en Delphi 4 no hace explotar el código heredado de más de 15 años de otra persona.

Así que me preguntaba si hay una mejor manera de hacer una compilación condicional de tal manera que realmente compruebe si tiene "Delphi 5 o superior" al compilar esa línea, en lugar de este formato que requiere la actualización de cada nueva versión de Delphi. .


IIRC, Delphi 6 introdujo expresiones condicionales, que en realidad son las que sugirió TLama. Para hacer que su código funcione con versiones de Delphi a continuación, debe verificar {$IFDEF CONDITIONALEXPRESSIONS } . Si esto no está definido, tiene que usar el antiguo esquema VERxxx para distinguir entre las versiones de Delphi.

Para Delphi 6 y RTLVersion posteriores, puede utilizar las constantes RTLVersion CompilerVersion y RTLVersion . Cuál de estos usas depende de tu código. Siempre que utilice una nueva prueba de características del compilador para CompilerVersion . Para cualquier cosa relacionada con la prueba RTL o VCL para RTLVersion .

Siempre es una buena idea codificar contra el compilador más nuevo y usar solo la parte condicional para la compatibilidad con versiones anteriores. Así que en lugar de escribir {$IF CompilerVersion >= 26.0} escriba su código de manera que se use {$IF CompilerVersion < 26.0} . Por lo tanto, en el futuro es mucho más fácil abandonar el soporte para versiones anteriores de compiladores.


La respuesta es más simple de lo que pensaba. De la documentation :

Por ejemplo, para determinar la versión del compilador y la biblioteca de tiempo de ejecución que se usaron para compilar su código, puede usar {$ IF} con CompilerVersion , RTLVersion y otras constantes.

Aquí está el código completo que detecta las versiones de Delphi de 6 a 10.3 (Rio):

{$IFNDEF FPC} {$IF CompilerVersion >= 33.0} {$DEFINE DELPHI_10_3_RIO_UP} {$IFEND} {$IF CompilerVersion >= 32.0} {$DEFINE DELPHI_10_2_TOKYO_UP} {$IFEND} {$IF CompilerVersion >= 31.0} {$DEFINE DELPHI_10_1_BERLIN_UP} {$IFEND} {$IF CompilerVersion >= 30.0} {$DEFINE DELPHI_10_SEATTLE_UP} {$IFEND} {$IF CompilerVersion >= 29.0} {$DEFINE DELPHI_XE8_UP} {$IFEND} {$IF CompilerVersion >= 28.0} {$DEFINE DELPHI_XE7_UP} {$IFEND} {$IF CompilerVersion >= 27.0} {$DEFINE DELPHI_XE6_UP} {$IFEND} {$IF CompilerVersion >= 26.0} {$DEFINE DELPHI_XE5_UP} {$IFEND} {$IF CompilerVersion >= 25.0} {$DEFINE DELPHI_XE4_UP} {$IFEND} {$IF CompilerVersion >= 24.0} {$DEFINE DELPHI_XE3_UP} {$IFEND} {$IF CompilerVersion >= 23.0} {$DEFINE DELPHI_XE2_UP} {$IFEND} {$IF CompilerVersion >= 22.0} {$DEFINE DELPHI_XE_UP} {$IFEND} {$IF CompilerVersion >= 21.0} {$DEFINE DELPHI_2010_UP} {$IFEND} {$IF CompilerVersion >= 20.0} {$DEFINE DELPHI_2009_UP} {$IFEND} {$IF CompilerVersion >= 19.0} {$DEFINE DELPHI_2007_FOR_NET_UP} {$IFEND} {$IF CompilerVersion >= 18.5} {$DEFINE DELPHI_2007_UP} {$IFEND} {$IF CompilerVersion >= 18.0} {$DEFINE DELPHI_2006_UP} {$IFEND} {$IF CompilerVersion >= 17.0} {$DEFINE DELPHI_2005_UP} {$IFEND} {$IF CompilerVersion >= 16.0} {$DEFINE DELPHI_8_FOR_NET_UP} {$IFEND} {$IF CompilerVersion >= 15.0} {$DEFINE DELPHI_7_UP} {$IFEND} {$IF CompilerVersion >= 14.0} {$DEFINE DELPHI_6_UP} {$IFEND} {$ENDIF}

La lista completa de la versión del compilador se puede encontrar por ejemplo here


Para el beneficio de que alguien venga a encontrar esta pregunta en el futuro, pensé que valdría la pena documentar mi solución final, ya que tomó la combinación de pequeños fragmentos de todas las respuestas y comentarios para hacerla funcionar, y me costó encontrar algunos más. Ejemplos para entender realmente cómo usar algunas de las sugerencias anteriores.

Para manejar las versiones anteriores a Delphi 6 que no son compatibles con {$IF} , las dejé como están. A lo sumo tendrías 5 de esos, pero en mi caso solo fueron 2:

{$IFDEF VER120} { Delphi 4 } {$DEFINE DELPHI4} {$DEFINE DELPHI4_UP} {$ENDIF} {$IFDEF VER130} { Delphi 5 } {$DEFINE DELPHI4_UP} {$DEFINE DELPHI5_UP} {$ENDIF}

Y luego, para las versiones que admiten {$ IF} (Delphi 6+) las envolví en un bloque {$IFDEF CONDITIONALEXPRESSIONS } según lo sugerido por Uwe. La documentación de Embarcadero resultó ser un buen ejemplo de esto , una vez que conocí los términos de búsqueda correctos.

Eso, combinado con la sugerencia de Warren de usar bloques IF en mayor o igual que la versión del compilador simplificó las cosas significativamente:

{$IFDEF CONDITIONALEXPRESSIONS} { Delphi 6+ } {$IF CompilerVersion >= 14.0} { Delphi 6+ } {$DEFINE DELPHI4_UP} {$DEFINE DELPHI5_UP} {$DEFINE DELPHI6_UP} {$IFEND} {$IF CompilerVersion >= 15.0} { Delphi 7+ } {$DEFINE DELPHI7_UP} {$IFEND} {$ENDIF}

Embarcadero tiene una tabla completa útil con todas las versiones de Delphi y sus constantes nombradas, y el nombre del paquete habitual. Entre eso y esta respuesta de desbordamiento de pila pude completar todas las constantes de la versión del compilador.

Una vez que conseguí este bloque allí, ni siquiera necesité los bloques Delphi 2005/2006 en mi pregunta y XE4 compila alegremente.

Me gustó la sugerencia de Uwe de codificar para la versión X e inferior en lugar de Y y superior cuando fue posible, aunque no terminé usando esa sugerencia de inmediato, ya que habría sido tanto volver a trabajar los IF y los IFDEF, sería deshacer el soporte para Delphi 3 en primer lugar ;-).


Si fuera un proveedor de componentes (TMS, DevEx), podría sentirme obligado a seguir la sintaxis larga y detallada que CADA versión de Delphi admite. Es por eso que ese gran lío está en la mayoría de las bases de código de componentes.

Sin embargo, para mis propios componentes internos, no actualizo todas las versiones que aparecen porque mi archivo ver.inc tiene este aspecto, y no admito las versiones de Delphi que no admitan esta nueva sintaxis:

{ver.inc} { MYSOFT VERSION DEFINES } {$IF CompilerVersion >= 22.0} {$DEFINE RTL220_UP} {$DEFINE XE_UP} {$IFEND} {$IF CompilerVersion >= 23.0} {$DEFINE RTL230_UP} {$DEFINE XE2_UP} {$IFEND} {$IF CompilerVersion >= 24.0} {$DEFINE RTL240_UP} {$DEFINE XE3_UP} {$IFEND} {$IF CompilerVersion >= 25.0} {$DEFINE RTL250_UP} {$DEFINE XE4_UP} {$IFEND} {$IF CompilerVersion >= 26.0} {$DEFINE RTL250_UP} {$DEFINE XE5_UP} {$IFEND} {$DEFINE OTHER_THING}

Nada en el código anterior se rompe cuando sale una nueva versión de delphi. Tenga en cuenta que NO tengo que admitir Delphi 5 hasta 2010 con mis bases de código. De hecho, solo soporta XE2 y superiores.

Se podría usar una versión ligeramente más larga del formulario anterior para admitir todas las versiones de Delphi 6 y superiores, sin bloqueos repetidos, y sin romper cada vez que se lance una nueva versión de delphi.

Además, vea la respuesta de Uwe para una técnica en la que puede crear un archivo .inc que admita CADA versión y solo use el formulario antiguo para las versiones antiguas de Delphi.