RAD Studio XE2: ¿Pruebas de integración? ¿Para qué?

Ya las hará el cliente y protestará. En el caso de que tengamos ganas, le ayudaremos. Si no, que se joda.

Esa parece ser la filosofía de Embarcadero para su producto RAD Studio XE2. Para hacernos una idea, lo que ahora trae el XE2 es lo que debería haber traído el XE original, pero ya sabemos, después de varios (muchos) años intentando convertir a la VCL en multiplataforma, llegan, compran un producto cualquiera, y en menos de seis meses lo integran en su RAD Studio, sustituyendo a la vetusta VCL que, por cierto, dio nacimiento a .NET cuando Microsoft se llevó a Anders de Borland.

El sistema de desarrollo es un tanto churrimangui, aunque parece ser que funciona. La idea es tener una máquina Windows con RAD Studio instalado. Puede ser una máquina virtual corriendo dentro de OS X, pero tened mucho cuidado con la compartición de perfiles y demás: en un tris tenéis que volver a activar, porque una de las cosas que mira el entorno para detectar que no lo han tocado es el nombre del equipo en la red. En fin.

Luego instalas un servidor en OS X, lo que, junto a un debugger de plataforma cruzada, puedes editar y compilar en la máquina Windows y ejecutar y depurar en el MAC. Digo churrimangui porque no es a lo que nos tiene habituados Borland, digo Embarcadero. Encima todo el tema al lado del MAC es por línea de comandos. Cualquier programador de hardware, o ya puestos de teléfonos y similares, verá el paralelismo evidente.

***

Pero bueno, no es de eso de lo que quiero hablar aquí. Hasta el 32 de diciembre del 2011, hay una oferta que si compras alguna versión del producto, te regalan otros. A veces ha sido comprar C++ Builder (o Delphi) y obtener el otro gratis. La de este año consiste en que te regalan más componentes y otros programas de la casa.

Uno de los productos es FastCube, componentes que te ayudan al análisis de datos. En mi caso no creo que me hagan falta, pero podría ser interesante para aquellos que hagan programas de gestión y tengan que presentar datos analizados.

Pues bien, las pruebas de integración de este producto con RAD Studio no se han hecho. No porque si instalas el componente, el producto deja de funcionar. No se trata de algunas configuraciones en concreto, ni que ocurra en ciertas máquinas: pasa siempre.

Si uno se pone a buscar en internet el error que da C++ Builder (que es el que falla, Delphi funciona bien), no encuentras absolutamente nada sobre el tema. Aplicando un poco de lógica, podemos llegar a varias posibles conclusiones:

  • Nadie está usando C++ Builder, o si lo está, no ha instalado dichos componentes.
  • Desde que han sacado la oferta, no han vendido ni una sola copia de C++ Builder o de RAD Studio.
  • Nadie está usando el producto.

Os dejo con la reflexión antes de pasar a la solución.

***

El problema se genera cuando la instalación del producto (que no es de Embarcadero, pero deberían haber hecho el test de integración antes de ponerlo a disposición de la gente tan alegremente) estropea por completo las rutas por defecto del compilador. Es decir, si abrimos el IDE (ya sea la versión completa de RAD Studio o personalidad de C++Builder), y nos vamos a Tools -> Options -> C++ Options -> Paths and Directories, las rutas de Include Path y de Library Path quedan completamente inutilizadas porque FastCube, en su soberana sabiduría, ha decidido que nadie más que él debe estar ahí.

Desinstalar el producto no soluciona nada, porque dichas rutas se quedan sin restaurar.

Por lo tanto, la solución pasa por volver a colocar allí dichas rutas. En mi caso son:

  • Include: $(CG_BOOST_ROOT)boosttr1tr1;$(CG_BOOST_ROOT);$(BDSINCLUDE);$(BDSINCLUDE)dinkumware;$(BDSINCLUDE)windowscrtl;$(BDSINCLUDE)windowssdk;$(BDSINCLUDE)windowsrtl;$(BDSINCLUDE)windowsvcl;C:Program Files (x86)FastReportsLibD16;$(BDS)RaveReportsLib;C:Program Files (x86)RaizeCS5LibRS-XE2Win32
  • Lib: $(BDSLIB)win32release;$(BDSLIB)win32releasepsdk;C:Program Files (x86)FastReportsLibD16;$(BDS)RaveReportsLib;C:Program Files (x86)RaizeCS5LibRS-XE2Win32

No te garantizo que la instalación haya tocado otras cosas, pero en mi caso, con volver a colocar ahí dichas cadenas, se soluciona el tema.

***

Por lo tanto, otro coscorrón más para Embarcadero. Y ya os diré cómo funciona el producto, porque voy a usarlo para un proyecto personal.

 

Win/MAC: arranque dual y jodimiento de particiones

Os lo juro. Estoy hasta los putísimos cojones de Windows, de MAC y de la madre que los parió a todos. El primero por pensarse que todo le pertenece, incluyendo las particiones  HFS+, y el segundo por pensar que todos los usuarios son tontos del culo.

No tengo muchas ganas de escribir, así que voy a ser bastante escueto.

Escenario: Windows/MAC con Boot Camp y arranque dual. Como Windows asigna las unidades como le sale de los cojones, entro en el Administrador de Discos y las cambio a los valores que quiero.

Vale, todo bien en Windows. Inicio OS X y… una de las tres particiones no se carga. Es decir, habiendo cambiado la letra de unidad a dos particiones HFS+ desde Windows, una de ellas luego no se carga desde OS X porque Windows, en su maravilloso afán de poseerlo todo, ha decidido cambiar cierta cadena de las tablas internas del disco por “Microsoft Basic Data”. Hay que joderse con tomate. ¿No saben reconocer una partición ajena y no tocar nada? Pues parece ser que no, que tienen ganas de joder la marrana.

Bueno, la Utilidad de Discos de OS X se ve incapaz de recuperar la partición. Hala, nueva pérdida de datos. Cuatro máquinas virtuales y un montón de descargas.

***

Pues no, hay solución. Está aquí. Otro geek de la más alta alcurnia se ha encontrado con el mismo problema y ha creado una aplicación en Python para solucionar el problema. Lo único que hace es cambiar dicha cadena por su valor por defecto. Y entonces OS X reconoce la partición como suya y la monta.

Olé sus cojones.

Os cuento cómo hacerlo.

***

Desmonta el disco completo en donde esté la partición afectada. Luego graba el fichero gpt_surgeon.py en disco (ojo con grabar el html y no el contenido del mismo). Aquí viene cuando Apple piensa que somos imbéciles o así. Tu grabas un archivo, que te lo pone como texto de lectura escritura. Pero tu lo quieres de ejecución, porque si no ya puedes darle de sopapos porque se negará a correr.

Hay que añadir el bit de ejecución. ¿Cómo? Ahí está el problema. Desde la interfaz gráfica no se puede, porque CMD-I sólo te dejar cambiar entre lectura y escritura, pero no ejecución.

Quizás haya algún botón por algún lado para activarlo, pero no lo he encontrado, así que tienes que abrir una ventana de terminal y cambiarlo ala UNIX: “chmod u+x gpt_surgeon.py”. Claro, puede que algún imbécil siga la secuencia desde el Finder y sea capaz de cambiarle los permisos a un troyano. En fin, viva la ergonomía y usabilidad maqueras.

Luego sigues la secuencia explicada en el enlace de arriba:

  • ./gpt_surgeon.py list /dev/disk<n>, en donde <n> es el disco malo.
  • Localiza la partición jodida, en la que debe aparecer el infame texto de “Microsoft Basic Data”.
  • sudo ./gpt_surgeon.py repair /dev/disk<n> <y>, en donde <y> es la partición rota.
  • Al poco, OS X (o el script) montará todas las unidades, habiendo reparado la estropeada.

Y ya está, esta ha sido la crónica del día de hoy. Cagontó…

 

C++/CX (II). C++/CX vs WRL

Bueno, una vez que hemos visto lo que hay dentro del nuevo Windows 8, y comprobado que WinRT no es un subsistema sino algo por encima de Win32 como es .NET, vamos a contaros las dos formas que hay de programar con C++ para la interfaz Metro.

Ya lo he comentado antes, pero voy a repetirlo aquí por mor de claridad. En Windows 8 hay dos escritorios diferentes. Por un lado tenemos el clásico de toda la vida que es prácticamente idéntico al de Windows 7, y por otro el de la interfaz Metro. Si no cambian las cosas, los equipos que lleven un procesador x86 tendrán acceso indistinto a los dos, mientras que aquellos que lleven procesador ARM sólo verán la interfaz Metro.

Eso quiere decir que habrá dos tipos de aplicaciones: las clásicas y las Metro. Las primeras sólo podrán compilarse para x86 (de 32 o de 64 bits) y sólo funcionarán en las máquinas Intel. Si estamos en la interfaz Metro y lanzamos una aplicación de este tipo, el sistema cambiará al escritorio clásico.

Las segundas podrán compilarse para x86 o para ARM y en ambos casos funcionarán en sus propios sistemas, pero siempre bajo la interfaz Metro. Es decir, si queremos que nuestra aplicación Metro escrita con código nativo pueda correr en los dos tipos de arquitectura, tendremos que proveer dos compilaciones.

Con .NET (C# y VB.NET) viene a pasar lo mismo, aunque en este caso creo que con especificar AnyCPU será suficiente para que la aplicación corra en ambas arquitecturas. Y de nuevo tendremos los dos tipos de aplicaciones: de escritorio y Metro, con las mismas reglas.

Por lo tanto, cualquier programa escrito en cualquier lenguaje que funcione ahora mismo en Windows 7, no debe tener ningún problema en ejecutarse en la siguiente versión, pero siempre en el escritorio clásico. Y podremos seguir escribiéndolos como hasta ahora.

***

Eso quiere decir que tenemos dos API diferentes e incompatibles entre sí. Por un lado tenemos el API de Win32 clásico y tradicional, sobre el que se construyen bibliotecas de terceros y el .NET. Aquí podemos meter VB6, Delphi, C#, C++/CLI, QT… Vamos, lo que hasta ahora.

Y para Metro hay una nueva API que se llama WinRT. Creo que hay cosas compartidas con Win32, pero no me hagáis mucho caso porque todavía no he visto nada. De todos modos si las hubiera, podemos tomarlas como si fueran nuevas, porque son excluyentes, al menos de momento.

Es decir, o bien desarrollas para Win32 o bien para WinRT, pero no puedes tener un ejecutable que use partes del otro más allá de las que MS ha querido compartir, y entre ellas no se encuentra C++/CX.

Por lo tanto también hay dos versiones de .NET. La de la interfaz Metro se construye sobre WinRT, y la clásica sobre Win32. Nos podemos hacer a la idea de que, aunque tengamos un API con nombres similares, por dentro funciona todo diferente (lo que no es cierto, pero a efectos prácticos sí que lo es, ya que las aplicaciones Metro deberán ir firmadas y el proceso de firmado garantiza que no vas a salirte de las API estándar -¿De qué me sonará eso?).

***

No obstante, WinRT no está escrito con C++/CX si no que está hecho con C++ clásico. Y en cierto modo es lógico, ya que no es más que una extensión a Win32, que es C y C++. Además, independientemente de mis diatribas personales, es algo bueno que le añada funcionalidad a un API que lleva tanto tiempo funcionando con regularidad y sin grandes problemas. Imaginaos los bugs que podría tener algo escrito desde cero.

Por lo tanto, podemos desarrollar aplicaciones para Metro sin usar .NET ni C++/CX. Podemos utilizar C++ y una biblioteca de plantillas llamada WRL (Windows Runtime Library), que viene a ser algo así como el ATL de Metro.

Microsoft no recomienda usarla, más que nada porque es compleja y porque de momento no hay documentación alguna sobre ella, pero está ahí, y es la base de Metro.

Si queremos echarle un vistazo, podemos acercarnos a “Program Files (x86)Windows Kits8.0Includewinrtwrl” y ver qué hay dentro. Tomaos un par de aspirinas antes.

Básicamente se trata de toda la infraestructura y parafernalia para acceder a los objetos COM y componentes de Metro.

***

C++/CX ocupa el nicho de lenguaje nativo para Metro, con lo que es más rápido que C# y que VB.NET, y es con el único con el que se puede acceder a DirectX (y por tanto a la creación de juegos). También es nativo. Es decir, que no es .NET y compila al código máquina que todos conocemos y de hecho es idéntico al C++ de toda la vida.

Lo que ocurre es que contiene una serie de extensiones que nos van a facilitar la vida a la hora de operar con Metro y sus componentes. Soporta clases parciales, se entiende bien con XAML e instanciar o crear un componente COM es un juego de niños comparado a como se hace con Win32.

Digamos que con esas extensiones nos ahorramos una buena faena a la hora de programar, y será el compilador el que sustituya esa azúcar sintáctica por el código necesario.

En siguientes entradas os contaré más sobre C++/CX.

¿WinRT un subsistema? No, no lo es

Bueno, al final no ha costado mucho encontrarlo. Básicamente, el resultado de esta investigación es:

image

O con otras palabras: WinRT y Metro se ejecutan, como todo lo demás, sobre Win32, con las ventajas y los inconvenientes que eso pueda tener. No me malinterpretéis: no hay nada malo que la arquitectura sea diferente a la indicada en el gráfico de arriba, lo que está mal es que Microsoft nos mienta tan descaradamente. Simplemente eso.

Si lo han hecho así, por algo será y sus motivos tendrán, y es entonces cuando, ya definitivamente, yo tenía razón: Windows ya no es Windows NT, y su grandiosa arquitectura por bloques se ha perdido en el camino. Y esto sí que es malo, bastante malo, porque estamos volviendo a un batiburrillo de código como es, por cierto, el OS X (quizás algún día hable de ello).

Vosotros mismos podéis comprobarlo sin problema alguno y de forma muy rápida. Tenéis que construir dos aplicaciones, una WinRT en C++/CX y otra clásica de Win32. No hay más que utilizar las plantillas por defecto sin ningún cambio.

Eso sí, hay que hacerlo a partir de la versión Developer de 64 bits de Windows 8, e instalar una versión de la MSDN, porque la Express creo que no es capaz de generar programas Win32 puros.

He llamado “TestWin32” a mi aplicación tradicional, que genera una ventana de Windows normal y corriente utilizando directamente el API de Win32. A la Metro la he llamado “TestSplitApplication”. Una vez generadas, tenemos que compilarlas. Visual Studio se os quedará más o menos así:

image

Si ahora nos vamos a la carpeta en donde está almacenado el proyecto (que podemos hacer desde el mismo IDE posicionándonos en el nombre de la solución en el Explorador y elegimos Open Folder in Windows Explorer), carpeta Debug, encontraremos el ejecutable del programa nativo (TestWin32.exe) y dentro de la carpeta TestSplitApplication, el de la aplicación Metro.

(Por cierto, en uno de esos lapsus teclae tan habituales en mi, le he dado el nombre de “TestSplitApplicarion” en lugar del correcto.)

Ahora debemos conseguir el Dependency Walker, aunque existen otras herramientas de línea de comandos que nos permiten hacer lo mismo dentro del SDK, lo interesante es utilizar esta porque lo veremos todo de un golpe. El mayor problema es que se trata de una utilidad que hace tiempo que no se incluye en ningún SDK, por lo que hay que conseguirla de forma externa.

Una vez obtenida la versión de 32 bits, porque nuestros proyectos son de dicho tipo, la ejecutamos sobre cada uno de los dos programas. Este es el resultado:

image

¿Lo veis? Ambos programas importan las mismas DLL, las de Win32 como KERNEL32.DLL y USER32.DLL.

Es decir que ambos son aplicaciones Win32 nativas.

***

Si nos diera por abrir, por ejemplo, uno de los dos KERNEL32.DLL, veríamos que ambas DLL son la misma con las mismas dependencias y exportaciones. Por lo tanto, ambas aplicaciones dependen del mismo subsistema.

Reitero que es una tontería, pero no lo es cuando intentan engañarte.

Lo que sí parece han hecho ha sido romper KERNEL32.DLL en otros ficheros más pequeños que contemplan subconjuntos de lo que en versiones anteriores había en él. Quizás de esta forma reduzcan la huella de memoria evitando cargar sub ficheros cuando estos no se vayan a utilizar.

***

Esto nos lleva a un tercer problema: parecer ser que una aplicación Metro no puede ejecutar funciones de Win32, y una de Win32 tampoco de WinRT.

¡¡Pero si es el mismo subsistema!!

Pues bien, estamos ante una limitación artificialmente impuesta por Microsoft sin ningún motivo técnico aparente… con lo guapo que sería hacer aplicaciones Win32 con C++/CX…

Se me ocurren un par de trucos para poder forzar esto, pero no creo que valga la pena hacerlo en una versión tan temprana como esta. Quizás cuando salga la definitiva, si tengo ganas y si nadie más se me adelanta, lo intente.