¿Técnicas para asegurar la compatibilidad multiplataforma (C ++)?

12

Estaba terminando uno de mis primeros proyectos en C ++ que se supone (según el marco) es multiplataforma. Desarrollé el proyecto completamente en Windows y Visual Studio, pensando que dado que todas las bibliotecas son multiplataforma, entonces hacer la compilación OSX "más adelante" sería trivial. Esto resultó no ser el caso, sino que el "código de Windows" no se ejecuta correctamente y se corrigieron algunos errores de compilación.

¿Qué técnicas existen para garantizar de antemano que el código sea compatible con todas las plataformas? ¿Desarrolla todas las plataformas simultáneamente y, por lo tanto, prueba el código en todas las plataformas al mismo tiempo, cuando se agregan nuevas funciones, en lugar de desarrollar las diferentes versiones de la plataforma una tras otra? (*)

La observación específica indica que no depende de las herramientas, sino de los "procesos de desarrollo" que ayudan a la compatibilidad entre plataformas, independientemente de las herramientas que se utilicen. Como el uno (*) arriba.

Específicamente estoy desarrollando un complemento VST con WDL-OL ( enlace ) y algunos DSP multiplataforma bibliotecas Los proyectos WDL-OL tienen configurados los proyectos VS y Xcode, pero creo que los problemas provienen de las bibliotecas y luego las diferencias en los compiladores.

    
pregunta mavavilj 21.06.2016 - 18:39

5 respuestas

13

La creación de código portátil puede ser muy difícil.

Primero algunos consejos obvios relacionados con el lenguaje:

  • utilice C ++ estándar y evite cuidadosamente cualquier comportamiento indefinido
  • depende principalmente de la biblioteca estándar (y de las bibliotecas portátiles como boost )
  • siempre incluye todos los encabezados esperados. No asuma que no necesita un encabezado porque está incluido en otra (es decir, en una implementación específica !): Esto puede causar errores de compilación
  • evite las construcciones que son compatibles con el compilador pero no están garantizadas por el C ++ estándar (por ejemplo, estructura anónima o matriz de longitud variable ): puede causar errores de compilación.
  • use las opciones del compilador para ayudarlo a imponer el cumplimiento (deshabilitando extensiones específicas del compilador, maximice el nivel de mensajes de advertencia devueltos)
  • tenga en cuenta que no es suficiente que el código funcione: hay muchos escollos de portabilidad dependientes de la implementación: tamaño de los tipos de datos (incluso elementales), caracteres que pueden ser firmado o sin firmar por defecto , supuestos sobre endianness , orden de evaluación en las expresiones cuando estos utilizan efectos secundarios , etc.

A continuación, un par de recomendaciones de diseño:

  • Prefiere una biblioteca estándar alternativa a una funcionalidad de sistema operativo equivalente
  • Aísle el uso de las dependencias del sistema operativo tanto como sea posible (por ejemplo, en una función de envoltura controlada con compilación condicional)

Finalmente los puntos delicados:

  • codificación de caracteres: en muchos sistemas puede confiar en utf8 . Pero para Windows es más delicado ya que el sistema espera ansi o utf-16. Por supuesto, puede confiar en un typedef (como TCHAR ), pero esto puede ser desafiante en combinación con la biblioteca estándar (por ejemplo, cout vs wcout para ser usado dependiendo si se usa char o wchar_t )
  • Si para GUI / graphics / Advanced I / O no puede encontrar una biblioteca portátil que se adapte a sus expectativas / requisitos, diseñe la arquitectura general para aislar los componentes específicos del sistema operativo. Los envoltorios pueden no ser suficientes aquí, debido a las diferentes interacciones y conceptos involucrados.
  • Aproveche algunos patrones de diseño interesantes como, por ejemplo, la abstract factory (ideal para diseñar familias de objetos relacionados, como en la IU específica del sistema operativo) o el mediator (ideal para implementar la colaboración entre familias de objetos relacionados) y utilizarlos junto con la compilación condicional.

Pero estos son solo consejos. En esta área no puedes ganar certeza.

    
respondido por el Christophe 21.06.2016 - 22:33
11

No hay nada que pueda garantizar que el código sea compatible con una plataforma que no sea compilarlo, ejecutarlo y probarlo allí. Por lo tanto, el enfoque de todas las personas sanas es construir, ejecutar y probar su aplicación en cada plataforma en la que lo proyecten, se deberá construir, ejecutar y probar.

La Integración Continua (CI) puede aliviar esta carga un poco para proyectos más pequeños, ya que puede obtener agentes de desarrollo gratuitos o gratuitos para algunas plataformas (principalmente Linux), realizar su desarrollo en Windows y simplemente regresar a Linux cuando haya una problema.

Sin embargo, OSX CI es bastante complicado.

    
respondido por el DeadMG 21.06.2016 - 20:21
9

Si solicita "procesos de desarrollo" y su plataforma de desarrollo principal es Windows con Visual Studio, le sugeriría que intente construir su proyecto sin incluir "windows.h". Recibirá muchos errores de compilación que lo llevarán a muchos lugares donde necesitará refactorizar su código. Por ejemplo, 'DWORD' no estará # definido y deberá reemplazarlo con uint32_t en todas partes (busque en google para stdint.h y encontrará información útil sobre los tipos de enteros y sus definiciones de plataforma cruzada). A continuación, deberá reemplazar todas las llamadas a la API de Win32, como Sleep() con su equivalente multiplataforma (nuevamente, Google es su mejor amigo, quien mostrará las preguntas y respuestas relevantes en los sitios de stack * .com). Probablemente no logrará encontrar todos los reemplazos de plataforma cruzada relevantes para su código y tendrá que devolver su directiva include "windows." pero ponerla debajo de #ifdef _WIN32 - más detalles here

Siga haciendo preguntas más concretas y obteniendo respuestas: esta es una sugerencia general para "lo que debería ser un proceso de desarrollo"

EDIT 1 Otra sugerencia es usar gcc y / o clang en su máquina de desarrollo de Windows (junto con Visual Studio)

    
respondido por el mvidelgauz 21.06.2016 - 20:42
3

Depende de los "algunos errores de compilación" que mencionas. Sin saber qué eran, es imposible ser específico.

Tengo un código multiplataforma para Windows / Linux / iOS / Android / Mac. Cada nueva plataforma trajo algunos errores y advertencias adicionales cuando se agregó por primera vez. Aprenderás rápidamente qué construcciones traen problemas. O evítalos o abstrae las diferencias en un encabezado con #ifdef s. Trate nunca de #ifdef entre plataformas dentro de su propio código.

Un ejemplo:

void myfunction(MyClass &);
myfunction(MyClass());

crea una instancia temporal de MyClass que se elimina después de que myfunction haya regresado. Con algunos de mis compiladores de C ++, esa instancia es de lectura / escritura (y el hecho de que sea temporal y se destruya pronto no preocupa al compilador). Con otros, myfunction tiene que ser redefinido para tomar un const MyClass & , o el compilador se queja. No importa lo que diga el estándar de C ++, o qué compilador es correcto y cuál es incorrecto. Después de encontrar el error un par de veces, sé que (a) o bien declaro una variable temporal de tipo MyClass y pase eso a myfunction o (b) declare la referencia const en myfunction y use mutable aquí y allá para desconstruir.

Conclusión: acumule experiencia y desarrolle sus propios estándares de codificación.

    
respondido por el Martin Kochanski 21.06.2016 - 20:49
3

Una posible forma de ayudar a la portabilidad podría ser confiar solo en las declaraciones y características proporcionadas por C ++ 11 , y mediante el uso de plataformas y marcos multiplataforma como POCO & Qt .

Pero incluso esto no es a prueba de fallas. Recuerda el aforismo

  

no existe tal cosa como un programa portátil, solo hay programas que se han portado con éxito (a alguna plataforma en particular)

Con la práctica, la disciplina y una gran cantidad de experiencia, la transferencia de un programa a otra plataforma podría, por lo general, por lo general realizarse rápidamente. Pero la experiencia y el know-how son muy importantes.

    
respondido por el Basile Starynkevitch 22.06.2016 - 09:33

Lea otras preguntas en las etiquetas