Multiplataforma de la buena (mismo código fuente)

Antes de empezar, y de que me deis caña de la buena, quiero decir que todo esto son elucubraciones personales mías y que lo más seguro nadie esté de acuerdo conmigo. Dicho esto, vamos al meollo del asunto.

Ya sabéis que me he ido distanciando un poco de la plataforma Windows a la vez que me he acercado a la de Apple sin realizar el cambio total. De Linux no quiero hablar, porque cada vez que tengo que hacer algo con él, sudo tinta china y al final, tras muchos cabezazos, suelo terminar desistiendo.

Lo último fue compilar el SDK de lector del libros electrónicos Boox i62HD. Tras instalar una Debian 6 x86 virtual en vmWare Fusion (el Workstation del MAC) por segunda vez, ya que la primera falló estrepitosamente porque el instalador sí que reconoció el discos duro SCSI pero luego el kernel instalado no, fui incapaz de compilarlo. 

Primero me encontré con una serie de paquetes que no estaban presentes y que el comprobador del SDK no avisó que faltaban, lo que te obliga a recorrer la cadena de errores para descubrir que te falta esto o aquello.

Lo último, y que todavía está sin solucionar, es que falta una dependencia en un fichero de proyecto, en concreto incluir “-l z” en el lugar correcto, que es enlazar con la biblioteca zlib. En mi caso el problema no es saber qué falta, sino dónde añadirlo. Tras varios intentos infructuosos y muchas páginas de internet leídas, no conseguí solucionarlo.

Había un bug similar si instalabas el SDK en un linux x64, pero el mío era x86, y el parche existente intentaba modificar ficheros que no existen (al menos en mi instalación). 

Pues bien, ni me han hecho ni puto caso ni tampoco lo han solucionado, lo que me lleva a preguntarme cómo cojones están programando. Y menos mal que usé una Debian, que es la misma distribución que usan los que han creado el SDK, que si llego a instalarme otra cosa…

Esto es un ejemplo de la desidia reinante en Linux. Lo dije en un foro hace tiempo. Los programadores de linux me parecen muy poco profesionales, tendentes a montar cualquier cosa que les parezca c00l y luego, cuando viene la hora de la verdad y demostrar que se es un programador con dos cojones, pasan del tema porque eso de solucionar bugs ya no es tan fascinante como lo otro, y encima solventar cualquier cosa son un montón de horas en las que no estamos subiendo nuestra supuesta caché c00l en la comunidad.

Aparte de deleznable, me parece una práctica muy poco seria y que sigue dejando a Linux como lo que es: o bien un juguete para niños falsamente interesantes, o bien algo destinado a servidores de bajo coste, y si no contadme cómo es el único sistema operativo que ha reventado con el segundo extra añadido hace unos días.

Por lo tanto, para mi el desarrollo en Linux queda completamente descartado a corto y largo plazo, por lo menos hasta que se pongan un cohete en el culo, cosa que dudo mucho que ocurra jamás (y espero equivocarme).

***

Luego vino el tema del swtiching. Lo cierto es que tras el entusiasmo inicial, la cosa deja mucho que desear en cuanto a usabilidad y, sí, rendimiento. Ya lo he ido comentando por este blog con anterioridad. OS X Lion y Mountain Lion, si los comparamos con XP, son la rehostia, pero comparados con Windows 7 dejan mucho, pero mucho que desear. La usabilidad es pésima, aparte de ciertos problemas de ergonomía a los que al final uno termina acostumbrándose.

También es cierto que cuando le coges el tranquillo ya no hay vuelta atrás, más que nada por la integración de todos los elementos, más todavía si tienes un iPad o un iPhone. Puedes conseguir casi lo mismo en Windows, pero no de forma tan integrada ni coherente.

Respecto al rendimiento, diré que por fin tengo un MAC que funciona como yo quiero, tras gastarme más de 300 euros en añadirle un segundo disco SSD al iMac de 27”. Es decir, en este momento mi máquina principal es un iMac de mediados del 2011 con un i7 a 3.4 GHz, un disco SSD de 256GB como disco de sistema para el OS X y uno de 1TB como secundario para datos. En este momento el disco FireWire de 2TB que usaba como secundario lo tengo como copia de Time Machine y, aparte de que arranca en 8 segundos (antes tardaba más de dos minutos y el disco seguía rascando hasta casi los diez), sólo veo la roseta multicolor de la muerte cuando se para el disco mecánico y tiene que arrancar. Además, la carga de aplicaciones, incluso las pesadas como Pages o Word, es prácticamente instantánea.

Y justo ahora, mientras escribo esto en Scrivener, tengo abierta una máquina virtual en Unity con Windows 7 x86 en la que se está instalando el SP1 de Visual Studio 2010 porque he instalado el AtmelStudio, que es un IDE basado en el Microsoft para generar ejecutables para los microprocesadores de Atmel.

***

Acabo de hacer una pausa para lanzar el JTAG MK-II, conectarlo a Windows y verificar que el AtmelStudio lo reconoce y funciona, todo ello virtualizado. Que es una de las cosas a las que quería llegar. Con un buen producto de virtualización, uno puede tener lo mejor de ambos mundos. Un equipo silencioso a más no poder que ejecuta de forma transparente tanto aplicaciones Windows como OS X sin mayor complicación que molestarse un poco en configurar las cosas, y encima con un rendimiento equivalente a si se ejecutara en real.

Evidentemente tenemos BootCamp, pero os aseguro que Windows no funciona igual que en un PC real, y perdemos todas las cosas buenas que puedes hacer con un MAC.

***

Pero no es a eso a lo que me refiero. Más bien todo esto es una especie de parche o pegote. De lo que realmente quiero hablar es de desarrollar para al menos Windows y MAC sin tener que crear dos programas diferentes.

Descartamos de entrada que un mismo ejecutable pueda funcionar en ambas plataformas. Por parte de los dos contendientes queda descartado. Microsoft podría haber hecho .NET para OS X o Apple Cocoa para Windows, pero no creo que eso vaya a ocurrir nunca jamás.

La única posible solución es Mono, pero ignoro sin un EXE de Windows se lanzará en un MAC o no, y lo voy a descartar por razonamientos que expondré más adelante.

***

Por lo tanto, la otra posible solución es compatibilidad en el código fuente. Que yo conozca, sólo tenemos dos grandes contendientes: QT y lo que ahora es Embarcadero pero que todos conocemos como Delphi y/o C++Builder.

De QT he hablado ya por aquí, pero no como plataforma cruzada. He estado usándolo un poco, en un proyecto en donde trabajaba, pero sólo para generar aplicaciones Windows. 

En principio QT es multiplataforma si no te sales del propio Framework, y de hecho he podido compilar un mismo código fuente en ambas plataformas sin más que compilar o bien desde Windows o bien desde OS X. Hay que tener mucho cuidado y usar el propio Creator de QT, y todos los ficheros servirán sin problema. Eso sí, necesitas dos ordenadores, uno para cada plataforma. Tres si quieres también Linux.

Esto nos trae a lo que hemos tratado antes. Como no es posible ejecutar OS X desde una máquina Windows (no sin violar licencias y sin hacks y sin limitaciones y fallos aleatorios), la única solución es tener un MAC más o menos potente y usar un Windows virtualizado, compartiendo la carpeta de desarrollo.

En mi caso, pese a no estar haciendo nada más que estudiar ahora que estoy en paro y tengo tiempo para jugar con todo esto, tengo una carpeta en donde está todo mi código fuente, carpeta que está compartida con SkyDrive y de ese modo puedo verla también en mi ordenador Windows (no el virtualizado), aparte de hacer copia de seguridad de forma automática.

Ojo con sincronizar mediante SkyDrive entre real y virtual, porque el tema no es instantáneo y puedes armar un buen jaleo. La solución es compartir una carpeta de tu MAC en tu Windows virtual. Con Fusion la cosa funciona muy bien, y hasta Embarcadero ha solucionado los problemas que tenía para compilar sobre carpetas de red (Microsoft siempre lo ha tenido resuelto, incluso dando la posibilidad de cachear localmente los ficheros intermedios). 

Si nos damos cuenta, con QT tenemos que compilar y ejecutar en cada máquina, lo que en principio no es un gran problema, pero sí cuando quieres algo que no está en el Framework. Ahí si que tienes que, mediante compilación condicional, sacarte tu mismo las castañas del fuego. Dada mi escasa experiencia con QT multiplataforma, no puedo asegurar si es algo muy habitual o no.

***

El otro participante es Embarcadero, con su FireMonkey bajo Delphi/C++ Builder. La historia de todo esto es un poco rocambolesca, ya que la empresa ha llevado muchos años implementando compilación condicional en su VCL. Sólo hay que mirar el código fuente de cualquier versión (creo que desde la 2009) y ver cómo muchos ficheros tienen secciones para Windows, MAC y Linux.

Uno, por tanto, se esperaba que cualquier día anunciaran que la VCL se había convertido en multiplataforma y que se podría compilar para estos tres sistemas operativos. 

Pero no, Embarcadero compró un producto a medio hacer y en seis meses lo transformó en su FireMonkey, que anunció a bombo y platillo con su nueva versión de RAD Studio XE2. Que por cierto se encuentra completamente lleno de bugs y no hay entrada de blog explicando esta o aquella característica que no hable de que hay un problema y que han tenido de resolverlo de alguna manera. Y es que seis meses es muy poco tiempo.

FireMonkey es una gran idea implementada muy pobremente. La idea es usar el IDE de Delphi o de C++ Builder para, a partir de un mismo código fuente, generar un ejecutable Windows o MAC, pero siempre desde Windows, por lo que estamos ante el mismo problema que antes.

La ventaja aquí es que puedes hacerlo todo desde Windows, hasta depurar. Es decir, es necesario instalar un servidor en el lado MAC, servidor que te va a permitir enviar el bundle OS X al MAC y depurarlo.

Y como todo primer producto, está completamente lleno de bugs y da muchos problemas, tanto el IDE como la depuración remota y el framework en sí. Embarcadero lleva sacados cinco parches, uno de ellos tan grande que exige reinstalarlo todo, que mejoran algo pero no mucho.

Y para más INRI, son aplicaciones de 32 bits, cosa que en los MAC se está acabando a pasos agigantados.

Esperemos que el XE3, que saldrá este verano, mejor algo la cosa.

***

Nos falta comentar Mono, el C# multiplataforma y de código abierto. Ya he hablado algo de él aquí con anterioridad, pero ahora voy a matizar un poco más. Mono engloba una serie de tecnologías más o menos integradas que comparten un mismo lenguaje de programación: C#. 

Basado en ports, todo el meollo se centra en un IDE (disponible para ambas plataformas, como el de QT) que permite crear aplicaciones basadas en los ya citados ports, de los que disonemos de varios según qué plataforma.

Por un lado tenemos el de Windows.Forms, que nos permitirá generar código compatible con la tecnología de Microsoft y ejecutar en Windows, MAC y Linux. GTK# es otro de ellos. También está MonoMAC, en exclusiva para MAC. Hay más pero nos detenemos aquí.

La idea es que cada port conserva la idiosincrasia de cada origen. Es decir, el API de GTK# es el GTK pero traducido a C#, y así con todos. Es una buena idea y en general, se puede generar código para Windows y MAC sin problemas mayores que los que tendríamos con QT.

***

Pero ahora viene el tío de la rebaja. Hemos visto algunas pegas que tienen todos estos sistemas de desarrollo, pero no son las peores de todas. De todos modos, si desarrollas para MAC necesitarás un MAC, y lo mismo para Windows, así que llevar a cabo esas tareas en ambas máquinas no es todo lo malo que se puede esperar, y de hecho en todos los casos existen soluciones bastante óptimas, aunque lo más deseable sería el acercamiento de Embarcadero, con compila en un sitio, ejecuta en dos.

La mayor pega de todas consiste en que prácticamente ninguno de estos sistemas pinta los controles como nativos. QT podría salvarse por los pelos, pero ni FireMonkey ni Mono, salvo MonoMac, aparecen como aplicaciones nativas. En la documentación de algunos productos la llaman hasta “alien”. Ya os podéis imaginar. Y si bien en Windows un usuario normal puede aceptar ciertos interfaces exóticos, un fanboy (perdón, maquero) de pro seguro que te manda a la mierda con todas sus palabras, y encima con razón.

El caso de MonoMac no se aplica, ya que no podremos compartir código fuente con Windows puesto que se trata de un envoltorio sencillo sobre el propio Cocoa con la idiosincrasia de OS X.

Por lo tanto, el único Framework que sé de forma fehaciente que ha entrado en la App Store de los MAC ha sido QT tras aplicar unos parches para evitar que el propio QT modificara ficheros dentro del bundle. De todos modos no sé qué pasará con el Sandboxing y si QT (y los demás) lo soportan.

Finalmente, está completamente claro que, a fecha de hoy, desarrollar en multiplataforma de manera coherente continua prohibido, principalmente por limitaciones de los Frameworks existentes que de problemas técnicos, dado que el rendimiento y las herramientas base (como compiladores de plataforma cruzada o lenguajes comunes en diferentes plataformas), están más que maduros. 

Tan sólo habría que crear un Framework que utilizara los controles nativos de cada plataforma, cosa que a fecha de hoy no existe (más sobre esto luego).

***

¿Qué nos queda, pues? Tan sencillo y tan complejo como dividir nuestra aplicación en dos partes. La primera, la parte visual, tendremos que hacerla diferente para cada plataforma. Objective-C en MAC, Win32 (MFC, o cualquier otro que pinte nativo), y la parte no visual o el núcleo de nuestro programa en algún lenguaje común, como puede ser C++ y STL y mantener al loro todo el tema para que compile y funcione en todos los sistemas de destino…

Es más trabajo, pero creo que es la única forma de mantener un interfaz visual nativo y coherente. El problema viene cuando nuestra aplicación es demasiado simple de modo que mantener esta estructura es más costoso que crear dos programas de forma independiente. 

Aparte, claro está, la bajada de rendimiento al tener que desacoplar ambas partes, aunque esto es muy bueno y debería ser una constante en cualquier desarrollo no trivial, aunque estemos haciéndolo solo para Windows o sólo para MAC. No obstante, a veces la caída de rendimiento es tal, o el programa es tan meramente visual que este acercamiento no es aplicable.

***

Si os dais cuenta no he entrado en el tema de código abierto versus código cerrado, y es que para el programador medio, se la trae floja si tiene el fuente o no de lo que esté usando: no lo va a mirar porque o bien no tiene tiempo o bien no está capacitado.

Tampoco he cubierto el tema Metro de Windows 8, que está de lado del tema móvil, en el que no he entrado pese a haber también Frameworks genéricos. Aquí estamos igual, pero ahora las plataformas son Windows Phone, Windows Metro (o RT), Android e iOS, y si las de Windows y MAC son disparejas, no os digo estas. Y, a fecha de hoy, que yo sepa, no hay ningún Framework multiplataforma y compatible. FireMonkey promete llegar a Android, Metro y a C++ en próximas versiones, pero si ya con dos plataformas la cosa está como está, no quiero saber cuando haya tantas…

***

Me falta hablar de un jugador que no he nombrado y que tiene muy buena pinta, quizás la mejor de todas pero, como apenas lo he probado, lo dejo para una futura entrada. Se llama wxWidgets y hace tiempo que hablé de él aquí, pero para Windows. Estamos ante un Framework con mucha solera en el mundo del desarrollo y que usan empresas como Google en su producto Google Drive a través de wxPython.

Y la mayor ventaja está en que, aparte de estar disponible para alguna que otra plataforma embebida, los controles son los nativos de cada sistema operativo.

***

QT en Windows y OS X (Fijaos cómo los controles son casi nativos en cada sistema).

 

FireMonkey en Windows y OS X (Esto no pasa la MAC App Store ni a golpe de talonario. Por no aparecer ni el menú aparece donde debe).

 

 

WxWidgets en OS X (Todos los controles son nativos).

4 comentarios en “Multiplataforma de la buena (mismo código fuente)”

  1. Me gusta mucho tu blog, es raro encontrar gente pegándose con estas cosas. Sin embargo, no estoy de acuerdo con esto:

    “…tendentes a montar cualquier cosa que les parezca c00l y luego, cuando viene la hora de la verdad y demostrar que se es un programador con dos cojones, pasan del tema porque eso de solucionar bugs ya no es tan fascinante como lo otro…”

    Completamente cierto, pero pásate por CodePlex y verás que eso de dejar proyectos a medias y no dar soporte no es específico de los programadores en plataforma linux. De hecho, yo más bien diría que es al revés.

  2. Interesante artículo, felicidades :).

    Creo que mientras no exista una solución universal para compilar en nativo para distintas plataformas, la mejor opción pasa por compartir la lógica, frente a un diseño que no guarde el look&feel de la plataforma sobre todo de cara a OSX y a apps móviles.

    Sin entrar en C++ (bendito sea) con C# se pueden hacer este tipo de apaños. Para el primer caso, que aún queda mucho, hay un proyecto que se llama XWT y francamente pinta muy interesante.

    Respecto a la segunda parte, me consta que puedes utilizar librerías compatibles con MonoMac y Metro como por ejemplo las librerías de clases portables. En mi caso he desarrollado apps multiplataforma con MonoTouch/WP7 y he podido compartir sin mayor problema, toda la lógica de la app. Eso sí, tuve que añadir algunas sentencias de preprocesador (pero no sobre la librería portable).

  3. Le he echado un vistazo a XWT… y de momento da la impresión que es para hacer cosas sencillas. Por lo que veo sólo tiene hecha la parte visual, controles visuales y ya está, por lo que hay que terminar añadiendo más librerías…

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *