El problema: errores -6206 y -1110 al copiar el programa
Cuando un programa Genero funciona en su carpeta de instalación y falla al copiarlo a otra, casi siempre es cuestión de FGLLDPATH (módulos) y FGLRESOURCEPATH (formularios). El caso típico: copias una versión nueva a una carpeta de pruebas para probarla antes de sustituir la buena, la lanzas, y falla con uno de estos dos errores:
Program stopped at 'app.4gl', line number 5.
FORMS statement error number -6206.
The 42m module 'comun' could not be loaded, check FGLLDPATH environment variable.Program stopped at 'comun.4gl', line number 3.
FORMS statement error number -1110.
Form file (ayuda) not found.El programa no ha cambiado en nada que tenga que ver con comun ni con ayuda. Lo que falta en la carpeta de pruebas son las piezas compartidas, el módulo común y su formulario, que en la instalación sí estaban al lado del programa.
La causa: dos variables y dos órdenes distintos
El runtime busca los módulos (.42m) y los recursos (.42f, .4st, .4ad, .42s…) con variables distintas y en un orden distinto. Según el manual:
| Orden | Módulos .42m (FGLLDPATH) | Recursos .42f… (FGLRESOURCEPATH) |
|---|---|---|
| 1 | Directorio actual | Directorio actual |
| 2 | Directorio del programa | FGLRESOURCEPATH (o DBPATH) |
| 3 | FGLLDPATH | $FGLDIR/lib |
| 4 | $FGLDIR/lib | Directorio del programa |
«Directorio del programa» es donde está el .42m que contiene el MAIN (o el .42r, si el programa está enlazado).
Lo que hay que tener presente:
- Para los módulos, la carpeta del programa es el segundo sitio donde se busca. Para los formularios, es el último.
- Si lanzas el programa instalado con su ruta absoluta desde cualquier carpeta, todo se resuelve por la carpeta del programa y funciona.
- La copia de pruebas tiene como carpeta del programa la de pruebas, donde no están las piezas comunes. Ningún paso de la búsqueda llega a la instalación.
Reproducirlo
Dos carpetas. prod/ tiene el programa, un módulo común y su formulario. pruebas/ tiene solo una copia de app.42m:
-- comun.4gl
PUBLIC FUNCTION abrir_ayuda()
OPEN FORM f_ayuda FROM "ayuda"
DISPLAY "formulario ayuda cargado"
CLOSE FORM f_ayuda
END FUNCTION-- app.4gl
IMPORT FGL comun
MAIN
DISPLAY "arranca app"
CALL comun.abrir_ayuda()
DISPLAY "fin app"
END MAIN-- ayuda.per
LAYOUT
GRID
{
Ayuda
}
END
ENDEl ejemplo solo carga el formulario con OPEN FORM, sin mostrarlo, así que LAYOUT vale también en modo texto. Para mostrarlo en una ventana en modo texto haría falta una sección SCREEN.
cd prod
fglcomp -W all comun.4gl && fglcomp -W all app.4gl && fglform ayuda.per
cp app.42m ../pruebas/Con FGLLDPATH y FGLRESOURCEPATH vacías:
| Cómo se lanza | Resultado |
|---|---|
cd prod; fglrun app.42m | Funciona |
cd /tmp; fglrun /ruta/prod/app.42m | Funciona: todo se encuentra en la carpeta del programa |
cd pruebas; fglrun app.42m | -6206: no encuentra comun.42m |
Igual, con FGLLDPATH=/ruta/prod | -1110: ya encuentra el módulo, pero no el formulario |
Igual, con FGLLDPATH y FGLRESOURCEPATH a /ruta/prod | Funciona |
Corregir solo FGLLDPATH cambia un error por otro. Hacen falta las dos variables.
Un detalle de la salida: «arranca app» se imprime antes del -6206. El módulo importado no se carga al arrancar, sino la primera vez que se usa (línea 5), así que el error puede salir lejos de donde empieza el programa.
La solución
Añadir la carpeta de instalación al final de las dos variables, por ejemplo en el perfil de la shell de quien prueba:
export FGLLDPATH=$FGLLDPATH:/opt/miapp/bin
export FGLRESOURCEPATH=$FGLRESOURCEPATH:/opt/miapp/binLa carpeta de pruebas solo necesita los ficheros propios del programa que se está probando. Lo común se sigue cogiendo de la instalación.
El orden importa, y no es el mismo para los dos tipos de fichero:
- Módulos: el directorio actual y el del programa se buscan antes que
FGLLDPATH. Si en pruebas hay uncomun.42mnuevo junto al programa, se usa ese y no el de la instalación. - Formularios: el directorio del programa es el último, después de
FGLRESOURCEPATH. Si en pruebas hay unayuda.42fnuevo junto al programa y la instalación está enFGLRESOURCEPATH, gana el de la instalación. El nuevo solo gana si está en el directorio actual, es decir, si lanzas el programa desde la carpeta de pruebas (cd pruebas; fglrun app.42m) y no con su ruta desde otra carpeta.
Comprobado con versiones distintas del mismo fichero en cada sitio, lanzando el programa desde una carpeta vacía:
| Mismo fichero en… | Gana |
|---|---|
Carpeta del programa y FGLLDPATH (.42m) | La carpeta del programa |
Carpeta del programa y FGLRESOURCEPATH (.42f) | FGLRESOURCEPATH |
Directorio actual y FGLRESOURCEPATH (.42f) | El directorio actual |
Si el programa se lanza siempre con un script, las mismas dos líneas pueden ir en el script, antes de lanzar fglrun. Así no dependes del perfil de cada usuario.
La otra cara: lo viejo del directorio actual
El directorio actual va primero en las dos búsquedas. Si lanzas el programa instalado desde una carpeta donde quedó un comun.42m antiguo, el programa usa el antiguo sin avisar:
$ cd carpeta_con_restos
$ fglrun /ruta/prod/app.42m
*** comun VIEJO del directorio actual ***
fin appEs la misma regla que en el caso anterior, pero en contra. Antes de buscar un fallo raro en el código, mira desde dónde se lanza el programa.
Diagnóstico rápido
| Error | Qué falta | Variable |
|---|---|---|
-6206 The 42m module ‘X’ could not be loaded | X.42m | FGLLDPATH |
-1110 Form file (X) not found | X.42f | FGLRESOURCEPATH |
Una diferencia práctica entre los dos:
-6206está en la lista de errores no capturables. NiWHENEVERniTRY/CATCHlo interceptan: el programa se para siempre.-1110sí se puede capturar. Pero unTRY/CATCHen el llamante no lo ve si el error salta dentro de una función de otro módulo, salvo que ese módulo lo propague conWHENEVER ERROR RAISE. Eso da para una entrada propia, la de TRY/CATCH.
Conclusión
Si un programa funciona instalado y falla copiado en otra carpeta, casi nunca es el programa. Son dos búsquedas distintas, y la carpeta del programa ocupa un sitio distinto en cada una: segunda para los módulos y última para los recursos. Añadir la instalación al final de FGLLDPATH y de FGLRESOURCEPATH resuelve los dos errores sin copiar nada.
Otra entrada de Genero: Enviar correo desde Genero con base.Channel.
Fuentes
- Manual Genero BDL 6.00: variables de entorno
FGLLDPATHyFGLRESOURCEPATH; tabla de errores (-6206,-1110); Non-trappable errors; Exception actions (WHENEVER ERROR RAISE).