10 de diciembre de 2014

Racket, Dropbox and .zo files

I have my .rkt Racket files in my Dropbox directory. So all copies are automatically kept in sync on my computers. (Do I really need to explain what is Dropbox?) One of the machines is a slightly slow netbook, so I usually compile all files of the programs to make them start faster later. (This does not change the speed at which they run, only decrease the boot time.)

To compile, I use a mini program in Racket:
#lang racket/base
(require compiler/compiler)
(requires setup/getinfo)

(compile-directory-zos (current-directory)
                       (get-info / full (current-directory)))

This creates a compiled subdirectory with the corresponding .dep and .zo files. The problem is that if the program has a (require "something.rkt"), then these files have the absolute path of the file something.rkt. Then when they are copied to another computer, they are bad and a strange error appears, which is fixed by deleting the .zo. But now the new .zo doesn't work in the other computer ...

I started using the selective synchronization options in Dropbox. I simply marked the compiled directories as non-synchronized. Well, I had to mark allll the compiled directories as non-synchronized and then go to the other computer and repeat the operation. Every time I added a new directory had to add the respective compiled   subdirectory on both machines. Every time I added a machine, I had to mark all directories again (fortunately this does not happen very often, but a disk reformatting is more usual).

However, the biggest problem was deleting (or moving) a subdirectory. As Dropbox had the directory marked as not synchronized, it recreate the directory just after I delete it. So I had to go to both computers and ununsyncronize it and then delete the directory. This operation was not so common, but it was a headache.

The Solution

It turns out that there is an environment variable PLTCOMPILEDROOTS that lets you choose where .zo files are saved (reference, original discussion). I chose to put them inside %USERPROFILE%\AppData\Local\Racket_Compiled; (With a ; at the end to indicate that if the .zo is not there, look in the original directory. For Linux you must use a : instead of a ; .) The temporary directory is %USERPROFILE%\AppData\Local\Temp so this seemed a good place and I hope it does not deserve any reproach :).

The other advantage of this method is that it doesn't mix the compiled directories with the normal directories and programs, so everything is cleaner and tidier.

(It's always hard for me to find the window to change the environment variables. (I miss the DOS days.) There are many pages with instructions. And the usual warning: Don't change the environment variables unless you know what you are doing .)

Racket, Dropbox y archivos .zo

Tengo mis archivos .rkt de Racket en mi directorio de Dropbox. Así se mantienen todas las copias sincronizadas automáticamente en mis computadoras. (¿Realmente necesito explicar qué es Dropbox?) 

Una de las maquinas en una netbook un poco lenta, así que en general compilo todos los archivos para que los programas se inicien más rápido después. (Esto no cambia la velocidad a la que se ejecutan, sólo achica el tiempo de arranque.)

Para compilar uso un mini programa en Racket:
#lang racket/base
(require compiler/compiler)
(require setup/getinfo)

(compile-directory-zos (current-directory)
                       (get-info/full (current-directory)))

Esto crea un subdirectorio compiled con los archivos .dep y .zo correspondientes. El problema es que si hay un (require "algo.rkt"), esos archivos tienen el path absoluto del archivo algo.rkt. Entonces cuando se copian en la otra computadora, andan mal y aparece algún error extraño, que se arregla borrando el .zo. Pero ahora el nuevo .zo no anda en la otra computadora ...

Comencé a usar las opciones de sincronización selectiva de Dropbox. Simplemente marcaba los directorios compiled como no sincronizables y listo. Bueno, tenía que marcar tooodos los directorios compiled como no sincronizables y después ir a la otra computadora y hacer lo mismo. Cada vez que agregaba un directorio nuevo tenía que agregar el respectivo subdirectorio compiled en ambas maquinas. Cada vez que agregaba una maquina, tenía que marcar todos los directorios (por suerte esto no pasa muy habitualmente, aunque un reformateo de disco es mas usual).

De todas maneras, el problema más grande era borrar (o mover) un subdirectorio. Como Dropbox tenía marcado el directorio como no sincronizable, cuando yo lo borraba Dropbox lo volvía a crear, así que tenía que ir a las dos computadoras y desdessincronizarlo y después borrar el directorio. No es algo tan habitual, pero era un dolor de cabeza.

La solución

Resulta que hay una variable de entorno PLTCOMPILEDROOTS que permite elegir en donde se guardan los archivos .zo (referencia, discusión original). Yo elegí ponerlos adentro de %USERPROFILE%\AppData\Local\Racket_Compiled; (con un ; al final para indicar que si no encuentra los .zo ahí los busque en el directorio original. Para Linux hay que usar un : en vez de un ; .) El directorio temporal está en %USERPROFILE%\AppData\Local\Temp así que ese parecía un buen lugar y espero no merecer ningún reproche :).

La otra ventaja de este método es que no aparecen mezclados los directorios compiled  con los directorios normales y los programas, así que queda todo más limpio y ordenado.

(Siempre me cuesta encontrar la ventana desde la cuál se cambian las variables de entorno. (Extraño los tiempos del DOS.) Hay muchas páginas con instrucciones. Y la advertencia de siempre: No cambie las variables de entono si no sabe lo que está haciendo.)