Al incluir jpegoptim dentro de FileOptimizer, y dado que no existían binarios precompilados para Windows, he tenido que generarlos yo mismo.

C/C++ se define como un lenguaje portable entre plataformas, la traducción de este vocablo al castellano, es en mi opinión mucho más significativa: transportable. Esto quiere decir, que se puede recompilar un programa de una plataforma en otra, pero ello requerirá un conocimiento bastante detallado de ambas.

Durante su conversión, me he encontrado con dos problemas, que afortunadamente están ya solventados. El primero es el manejo de archivos de texto/binarios, que es diferente en plataformas DOS/Windows, de *NIX.

La diferencia es sencilla de explicar, mientras que Windows, usa archivos de texto con saltos de linea en la forma \n\r, en *NIX, estos son simplemente \n. Para mantener la compatibilidad, se agregó a las bibliotecas de C, que al tratar archivos, automáticamente se convirtiera \n a \n\r a la hora de escribir, y \n\r a \n a la hora de leerlos. Naturalmente este mecanismo, que era el modo por defecto, rompía el manejo de archivos binarios, así que se dispuso del modificador b (binario), que permitía seleccionar: lecturas binarias (“rb”); escrituras binarias (“wb”); y otras combinaciones.

De este modo, un programa en UNIX, que abra un archivo, al compilarse sobre Windows/DOS, asumirá que es de texto. Para ello, o bien modificamos el código, o bien usando las opciones de opciones de enlazado
agregamos binmode.obj, que permite que por defecto los archivos se abran en modo binario, sin necesidad de especificar el modificador b, ni asignar la variable global _fmode.

El segundo problema era la expansión de máscaras en los argumentos del programa. En plataformas basadas en UNIX, el proceso de argumentos viene integrado, así si lanzamos un programa con *.*, se expandirá a que argv[1] valga el primer archivo que cumpla la máscara, argv[2] el segundo, y así sucesivamente. Naturalmente argc se actualizará adecuadamente.

En Windows esto es diferente, heredado de los tiempos de DOS, donde ese proceso adicional, requería una sobrecarga que no estaba necesaria. Por tanto ese mismo programa, en Windows tiene argv[1] como *.* y ya está. Lo habitual era que el propio código del programa manejase la expansión, usando findfirst/findnext si es que lo necesitaba.

La solución vuelve a estar en las opciones del linker de Visual C++, agregamos setargv.obj, que añadirá unos 10 Kb. de código extra para realizar el mismo trabajo, y asunto solucionado.

VC++ nos ofrece muchas más opciones de enlazado, algunas de ellas interesantes para simplificar nuestros ejecutables tales como noarg.obj, smalheap.obj, noenv.obj.