miércoles, 22 de marzo de 2023

El proceso de publicar una versión de PSeInt

Últimamente estuve escribiendo sobre los cambios internos de PSeInt. Todavía estoy muy lejos de donde quiero estar en este sentido, pero hice una pausa en un punto razonable como poder sacar una versión. Para actualizar los perfiles, publicar algunas correcciones a bugs u otras mejoras menores, actualizar las opciones de descarga, etc... El mantenimiento que vengo posponiendo hace más de un año.

Pero aún así, aunque el código nuevo anda, todavía no pude publicarlo. ¿Qué me está frenando?

 

Los perfiles

Aunque no lo parezca, agregar los perfiles nuevos que van solicitando los usuarios demanda mucho tiempo. Los recibo por correo y rara vez listos para agregar al repositorio. Usualmente tengo que editar la descripción, elegir un nombre que no se pise con los preexistentes, buscar el sitio web de la institución para obtener un ícono (con suerte en algunos casos lo envían) y ajustarle tamaño y formato, registrar los datos en una planilla interna mía y responder el mail, ubicar los archivos donde corresponde en el repo y documentarlo en el changelog. A veces hasta tengo que intercambiar algunos mails adicionales porque me envían los datos de la institución pero no la configuración del lenguaje.

En fin, digamos que cada perfil me consume de 5 a 10 minutos. Luego de tanto tiempo sin sacar una versión, se me acumularon más de 70 correos solicitando agregar o actualizar perfiles. Son varias horas de trabajo tedioso cargarlos todos. Y no quedaría bien que publique la actualización sin incluir los que llegaron suficientemente a tiempo.

 

Las herramientas de compilación 

Tengo varios toolchains que uso para generar las versiones para los distintos sistemas. Usualmente, como suelo automatizar la mayor parte del empaqueto con scripts de bash, generar una release suele ser bastante rápido. Pero esta vez tuve que actualizar todo porque el nuevo código requiere C++17, y los compiladores que usaba eran demasiado viejos (además de que Apple cambió oootra vez su arquitectura de hardware).

 

En el caso de Windows, usaba el mingw32 que armé para ZinjaI (que se había estancado en gcc6), mediante wine. Ahora planeo lanzar un ZinjaI basado en mingw64 (con 2 versiones, una de 32bits y otra de 64bits). Ya estuve actualizando estos otros scripts que descargan y acomodan estos archivos para ZinjaI.

Pero un cambio de compilador implica también recompilar todos los complementos (y de paso, actualizar sus versiones). Esa es la parte lenta y tediosa. La mitad de las veces hay que ajustar el script de compilación o hacer algún parche para que funcione (lo cual implica googlear un buen rato para entender el error y encontrar/armar el parche). Y para PSeInt necesito algunos de esos complementos (empezando por el de wxWidgets).

 

En el caso de MacOS es todavía peor. Uso un compilador cruzado (una versión de gcc o de clang compilada en GNU/Linux pero que genera binarios para MacOS). Obtener la versión adecuada del SDK de macOS, y compilar el compilador implica varios pasos que nunca funciona a la primera. Y siempre pasan cosas "raras" con los SDKs de MacOS (ejemplo más abajo). 

Actualicé todo esto, y ahora puedo compilar binarios para los nuevos procesadores ARM64. Peeero... No los puedo testear, porque no hay máquina virtual para emular eso en una notebook Intel (y entonces ¿cómo se qué estoy distribuyendo?... todavía no tengo respuesta). Solo pude testear la versión alternativa compilada para procesadores Intel en una máquina virtual con un macOS que ya está bastante viejo.


En el caso de GNU/Linux, las cosas suelen ir más sobre rieles. Porque es la plataforma que compilo nativa, y la que más conozco como para resolver cualquier problema. Aquí empecé teniendo que cambiar de distribución porque ahora la mayoría ya no dan versiones de 32bits (entre ellas Ubuntu, que es la que estaba usando). Pero armé una VM nueva basada en Linux Mint 19 de 32bits, y pude compilar todo.

Luego quise probar con Ubuntus 18.04 LTS y 19.10 para los 64bits pero los repos ya no funcionan, y entonces una vez instalado el sistema base no puedo agregar lo que me falta para compilar wx. Creo que no habría problemas si parto de 20.04 LTS, pero trato de evitarlo porque si uso una versión demasiado "reciente" corro el riesgo de que los binarios dependan de algo relativamente nuevo y no les funcione a los usuarios con sistemas más viejos/desactualizados (que son muchos más de los que deberían). Ya veré si puedo hacer andar algo intermedio.


Y las versiones cada vez son más: win32, win64, mac-arm64, mac-x86_64 (ya deprequé mac-i686 y mac-ppc), linux32, linux64... y podrían aparecer más, como una para Chromebooks, o una para Rapsberry Pi, si supiera cómo hacerlas y probarlas. Pero entonces también tuve que reestructurar los scripts de compilación del propio PSeInt. Ya no era sostenible tener un makefile por módulo y por plataforma. Mejoré esto, pero como todo, también llevó su tiempo.

Lo bueno es que aproveché el tener que reconstruir casi todo para documentar el proceso; muchos detalles ahora están aquí.


Las pequeñas diferencias entre plataformas

Aún en código relativamente básico (que solo usa C++ estándar) me encuentro con problemas al cambiar de compilador. 

Por ejemplo, en macOS, si queremos soportar versiones previas a 10.13*, hay partes muy específicas de la biblioteca estándar que no tendremos disponibles. Me topé con el problema al usar la función std::get (para extraer un dato de un std::variant). Encontrar el por qué del problema ya fue un problema, y luego buscar una corrección que no me obligue a ensuciar todo el código con workarounds por culpa de una sola plataforma también se llevó su tiempo.
*no se si es muy necesario, no estoy familiarizado con el "ecosistema" de macs.

Otro ejemplo apareció al activar C++17 con el nuevo mingw64. Este deriva de una mala práctica que yo tenía cuando empecé a programar: poner el "using namespace std" en headers. Como en C++17 se define un significado para "byte" y Windows en sus propios headers también quiere definir otro significado para "byte", entran en colisión. Nuevamente, entender la raíz del problema lleva un rato de investigar, y después agregar toneladas de "std::"s para solucionarlo otro poquito más.

 

Todo lo demás

Finalmente, hay que hacer otras cosas como actualizar la ayuda de acuerdo a los cambios, actualizar la imagen de la splash-screen, completar el changelog, correr los antivirus (y rezar para que no salten falsos positivos), subir los archivos, actualizar en el sitio web (la lista de opciones de descarga, los números de versiones, los hashes de los nuevos archivos, agregar una noticia...), etc, etc, etc.


Sumando todo esto, la release está requiriéndome muchísimo tiempo. Y recuerden que esto consume de mi "tiempo libre". El trabajo en la Universidad (que es mi verdadero "trabajo") también se complicó últimamente, ni hablar del tiempo que se lleva la bebé, y que finalmente debo destinar otro poco de tiempo a otras cosas, como hacer deporte para no perder la cabeza. Así que por estos motivos la nueva versión viene muy muy demorada. Pero la buena noticia es que ya falta muy poquito, el 90% de lo que mencioné ya está hecho.

8 comentarios:

  1. Todo buen trabajo lleva tiempo y ahora todo corre más rápido, no nos alcanza las horas del día para hacer todo lo que deseamos.

    Sobre los perfiles yo antes usaba el mismo para todo un curso, ahora lo voy adaptando en el trascurso del semestre (4 meses), uso uno por cada mes, por ejemplo, el primer mes exijo a los estudiantes cargar el perfil más cercano al seudocódigo y luego lo vamos cambiando a medida que se va complejizando la lógica algorítmica y el uso de las estructuras de programación.

    Tengo un problema con los perfiles, es que los estudiantes no me cargan el perfil pedido y cuando evalúo desarrollan el código diferente a como lo pedí, por mas que repito fallan al leer el perfil, una idea es que en el encabezado se coloque el nombre del perfil seleccionado como comentario cuando se crea un archivo neuvo, así creo que reduce la posibilidad de usar otro perfil

    // Perfil "XY.ppsc"
    Algoritmo sin_titulo
    // TODO: Implementar funcionalidad aquí
    FinAlgoritmo


    Además creo que pseint debe ofrecer 4 perfiles por defecto de codificación de más cercano a seudo código a menos seudocódigo, nombrados y con extensión

    “.perfilPsc” -> .ppsc

    “1 pseudocodigo inicial.ppsc”
    “2 pseudocodigo intermedio.ppsc”
    “3 pseudocodigo avanzado.ppsc”
    “4 pseudocodigo estricto.ppsc”

    de este modo reduce el envío de solicitar incluir perfiles en el próximo lanzamiento y facilita al estudiante la carga e identificación de estos.

    Sugiero el siguiente orden de más cercano a seudocódigo a menos seudocódigo en las opciones del perfil, lo que no se pueda incorporarlo en el siguiente lanzamiento puede quedar atenuado para una futura actualización. =)

    Para una codificación mucho más poderosa de seudocódigo y practica se puede agregar situaciones específicas de interpretación
    Se puede agregar una ayuda para cada ítem, para que el usuario sepa de que se trata cada flag.

    1: Exigir el uso (;) al final de cada sentencia
    Ayuda: Seudocódigo nivel inicial no usa esta característica salvo entre sentencias en una misma línea.
    Algoritmo sin_titulo
    Z = "hola"; W = "mundo"
    escribir Z " " W
    FinAlgoritmo


    2: Exigir declarar los tipos de variables.
    Ayuda: Seudocódigo nivel inicial no usa declaración de tipos de variables
    Se entiende declarar como definir tipo de dato
    Algoritmo sin_titulo
    Definir Z, W Como Caracteres;
    Z = "hola"; W = "mundo"
    escribir Z " " W
    FinAlgoritmo


    3: Generar un error si no define contenido de una variable cuando se la usa.
    Ayuda: Una sentencia no puede contener variables sin valor asignado
    Algoritmo sin_titulo
    escribir Z " " W // Error variable Z y W sin definir valor
    FinAlgoritmo

    3.1 No permitir utilizar variables o posiciones de arreglos sin inicializar
    Algoritmo sin_titulo
    definir arreglo Como Entero
    dimension arreglo[3]
    escribir arreglo[1] // Lin 3 (inst 1): ERROR 288: Valor de posición no inicializada
    FinAlgoritmo


    4: (nueva opción) Exigir concatenar variables de texto con el operador ‘,’
    Nota: Esto permite aprender el uso del operador coma (,).
    Ayuda: seudocódigo nivel inicial concatena expresiones sin operadores esto es solo con el uso de espacios (spc)
    Algoritmo sin_titulo
    Z = "hola"
    W = "mundo"
    escribir Z, " ", W
    FinAlgoritmo

    ResponderEliminar
  2. Parte 2:
    5: (nueva opción) Exigir concatenar variables de texto con el operador ‘+’
    Algoritmo sin_titulo
    Z = "hola"
    W = "mundo"
    escribir Z + " " + W
    FinAlgoritmo

    Nota: Si la opción 4 y 5 están fijadas o seleccionadas implica que se pueden usar los dos operadores para concatenar (,/+) si no están fijas solo se permite concatenar con espacios. Si esta fijada una sola no se permite la combinación del uso (,) con (+)

    6: (nueva opción) permitir concatenar sin verificar igualdad en tipos de datos
    Ayuda: seudocódigo nivel inicial concatena sin verificar igualdad en tipos de datos
    Nota: Esto permitiría usar los operadores (,/+) sin conversión de tipos de datos
    Algoritmo sin_titulo
    Z = "hola"
    W = "mundo"
    X = 123
    escribir Z " " W " " X
    escribir Z , " " , W , " ", X
    escribir Z + " " + W + " " + X // escribir Z + W + convertirAtexto(X)
    FinAlgoritmo

    7: Permitir asignar con el operador signo igual (=)
    Ayuda: seudocódigo nivel inicial usa el operador flecha hacia la izquierda(←)
    Algoritmo sin_titulo
    Z = "hola"
    W = "mundo"
    X = 123
    escribir Z " " W " " X
    FinAlgoritmo


    8: (nueva opción) Exigir la comparación de igual con el operador doble signo igual (==)
    Ayuda: seudocódigo nivel inicial usa el operador signo (=)
    Algoritmo sin_titulo
    Z = "hola"
    W = "mundo"
    escribir Z == W
    FinAlgoritmo


    9: Permitir las palabras ‘Y’, ‘O’, ‘NO’ y ‘MOD’ para los operadores lógicos ‘&/∧’, ‘|/∨’, ‘~/¬’ y ‘%’
    Ayuda: Seudocódigo nivel inicial usa palabras para operadores lógicos


    10: (nueva opción) Si un algoritmo o subalgoritmo no recibe argumentos exigir paréntesis vacíos
    Ayuda: Seudocódigo nivel inicial no usa paréntesis vacíos

    Algoritmo principal()
    secundario()
    FinAlgoritmo


    Subalgoritmo secundario()
    Z = "hola"
    W = "mundo"
    X = 123
    escribir Z + " " + W + " " + X
    FinSubAlgoritmo

    11: (nueva opción) permitir argumentos en el algoritmo principal

    Algoritmo suma(a, b)
    Escribir "la suma de a=" + a + " y b=" + b + " es " + a+b;
    FinAlgoritmo

    Nota: en este caso la consola espera dos entradas, así el estudiante aprende a codificar algoritmos con parámetros iniciales muy común en lenguajes como maxima, Matlab, y otros inclusive muchos como C, C++, Java lo pueden efectuar.

    ResponderEliminar
    Respuestas
    1. Se supone que los perfiles no se cambian con frecuencia. El 99% de los usuarios solo debe configurarlo la primera vez. En los cursos como el suyo donde hay dos o mas niveles, solo unas pocas veces. Entonces no es algo para andar cambiando con frecuencia como para que esté tan a mano y tan explícito. Y sería introducir ruido/complejidad ese comentario.

      Por otro lado, PSeInt muestra el perfil actual al iniciar, en la barra de estado. Eso alcanza para saber rápido si está bien configurado. Entre mis alumnos también muchos no lo configuran bien; pero mi respuesta es que yo corrijo en el parcial en base al perfil que les pedí, si no prestan atención y eligen el que va, van a tener problemas en el parcial :).

      Sobre las opciones. Actualmente tienen una pequeña ayuda (implementada como tooltip), pero ya tengo pensado un rediseño para el cuadro de configuración, ya que habrá muchas opciones nuevas, con sus correspondientes ayudas/ejemplos. Eso vendrá más adelante.

      Finalmente, sobre los 11 puntos, esto ya es demasiado largo para discutirlo en un comentario (de hecho el comentario es más largo que el post!). Pero hay cosas que comparto y otras que no, como por ej pensar la coma como un operador que concatena (y entonces ¿cómo aplica en la lectura, o los indices de una matriz?), o permitir argumentos al algoritmo principal que se lean igual que un leer (sería confuso, ya existen los subalgoritmos para ese concepto), etc. Y en general, los docentes no se ponen de acuerdo en cuáles opciones son para un nivel y cuáles para otro, así que no lo mencionaría de esa forma en la descripción. Sólo que hace, luego que el docente decida cuándo le sirve y para qué.

      Eliminar
    2. Hola. una respuesta corta, creo que es mejor discutirla en el foro
      En muchas aulas tienen por ejemplo instalado versiones de PseInt muy antiguas, y me toca usar la versión portable entonces cada sesión de clase hay que cargar los perfiles porque hay unos docentes jefes que no les gustan los cambios, ya que entre más poderoso sea el intérprete tendrían que adaptar lo que venían haciendo, mi filosofía es adaptarme a los cambios y evolución y PseInt es una de esas aplicaciones que ha evolucionado mucho y espero que siga así, ojala con ayuda de terceros , por ejemplo si ya viene una versión personalizable de palabras clave, e idioma de interfaz puede ser que muchos se unan al proyecto, yo no tengo esa capacidad, pues soy Ing. en electrónica y como programamos microcontroladores debemos los profes de estos cursos enseñar lógica algorítmica. sigo el foro =)

      Eliminar
  3. Cordial saludo.

    Creo que se debería incluir POO y Manejo de Archivos de texto, al estilo Latino Lenguaje

    ResponderEliminar
    Respuestas
    1. Hola

      Dentro de los paradigmas de programación en la formación de sistemas computacionales hay que estudiar POO. Pienso que PseInt algún día llegue a soportar POO, pero por ahora si por lo menos permitir declarar variables fuera de Proceso - FinProceso. Para dar preámbulo a POO, ya que este tipo de variables son las propiedades de una clase.
      Mas detalle en el foro. Bueno espero la opinión de otros docentes y usuarios

      Gracias

      Eliminar
  4. Gracias por tu gran labor, Pablo. No tengas prisa. PSeInt es una gran herramienta ya tal y como está. Si llegan mejoras, bien; si no, aun así será útil para mucha gente. Y enhorabuena por la bebé!

    ResponderEliminar
  5. HOla Pablo, mi hija empezó este año Sistemas en la UTN FRSF, usan Zinjai. Lo quise instalar en una NB vieja que le pusimos linux porque con Win era un carretón, el problema es que me dice que faltan dos librerias, las quiero instalar, pero linux (Ubuntu) no las encuentra. Las librerias son:
    libgtk-x11-2 y libgdk-x11-2
    Si me podrías tirar una ayuda, porque estaría bueno que mi hija pueda llevar esta NB a la facu porque no hay tantas PCs para todos. y de paso quiero que empiece a ver linux, pero no quiero tirarle de entrada un problemón y que ya se frustre

    ResponderEliminar