viernes, 25 de mayo de 2012

Toolchains alternativos en ZinjaI

Wikipedia en inglés empieza la definición de toolchain con algo que traducido sería más o menos "el conjunto de herramientas de programación que se utilizan para crear un producto...". Esta definición involucra compilador, editor, depurador, etc. Pero en la práctica he visto usar este término para referirse mayormente al conjunto de herramientas que verdaderamente producen el ejecutable; es decir el compilador en sentido general, que incluye preprocesador, compilador, ensamblador, enlazador, y cualquier otra cosa que pueda ser necesaria para pasar del fuente al ejecutable. Mi compilador amigo es el archiconocido gcc en GNU/Linux (y su port para Windows de 32 bits, mingw32), pero existen muchos otros. Entre las alternativas puedo mencionar al compilador de intel (que nunca probé, pero que tiene muy buena fama en el ambiente científico porque logra ejecutables más rápidos en ciertas configuraciones y un set interesante de herramientas auxiliares), o al flamante conjunto LLVM+Clang. LLVM es un conjunto de herramientas que forman parte de un toolchain propio modular y flexible. Clang es el módulo que le falta para completar un conjunto enteramente basado en llvm que compile de principio a fin código C++. Su creciente popularidad y su rápida evolución, junto con otras ventajas que forman parte de su concepto me hacen pensar en integrarlo en ZinjaI. Y ya que voy a estar en el baile, pretendo hacer esta integración de una forma más o menos genérica para que al final ZinjaI permita configurar fácilmente toolchains alternativos, o incluso diferentes formas de construir un proyecto independientemente del toolchain.

Se supone que llvm+Clang tiene dos grandes ventajas frente a gcc desde el punto de vista del usuario final: mensajes de error más detallados y útiles, y mayor velocidad. Sabido es que los mensajes de error de gcc suelen ser horribles (muy técnicos, o muy ligados a la forma en que gcc parsea, y recuerden que ZinjaI está pensado en gran parte para utilizarse mientras se aprende a programar en C++). ZinjaI hace algún esfuerzo por simplificarlos (por ejemplo, el reemplazo en los errores que involucran templates), pero no es suficiente. Con Clang veremos en general errores mucho más fáciles de entender y corregir. Y el tema de la velocidad en principio no necesita mucha explicación, pero sí tiene una potencial consecuencia muy importante: el parseo que hace Clang intenta ser lo suficientemente rápido como para que el IDE pueda utilizarlo para obtener la información de autocompletado o para que marque los errores y warnings en tiempo real (es decir, mientras escribe, sin esperar la compilación, como pasa por ejemplo en Eclipse). Esto no es un detalle menor y puede ser explotado aún cuando la intención sea finalmente utilizar otro compilador para generar el ejecutable, así que me gustaría investigarlo. Como siempre, no todo es color de rosas, y como desventaja puedo decir que Clang es un proyecto más joven, que no tiene la madures de gcc, que no tiene el mismo grado de compatibilidad o soporte del lenguaje (habrá aspectos de C++ aún no contemplados o faltarán extensiones muy comunes como OMP), y que por ende no parece todavía taan general y confiable. Sin embargo, la velocidad a la que avanza es increíble y ya se está utilizando para cosas serias y empezando a pasar pruebas de fuego importantes.

Volviendo al tema de los toolchains en ZinjaI, entre los ejemplos de diferentes compiladores ya mencioné gcc, llvm, al de intel, y amd creo que también tiene uno propio; en Windows podría optar entre mingw32 y mingw64, etc. También serviría para poder utilizar de distintas formas o distintas versiones de un mismo compilador. Por ejemplo, en mi GNU/Linux tengo el gcc de mi distribución, tengo dos versiones más para compilar cruzado y generar los ejecutables para Mac (gracias a IMCROSS), y utilizó también wine para compilar, mingw32 mediante, los ejecutables para Windows. Una forma genérica de definir toolchains alternativos en ZinjaI permitiría manejar todas estas situaciones. Sin embargo, más allá de que el C++ debería ser siempre el mismo independientemente del compilador, el tema de las opciones de compilación y enlazado sí puede variar mucho, tanto en cuales hay disponibles, como en cómo indicarselas al compilador. Para dar soporte a compiladores con interfaces muy diferentes a gcc debería tener un sistema genérico para definir los argumentos y qué opciones son configurables (básicamente, el diálogo de Opciones de Compilación y Ejecución en ZinjaI). Por otro lado, el análisis y la reinterpretación que hago actualmente de la salida que arroja el compilador también podría variar drásticamente.

Analizando todo esto, el cambio en mi gestión de proyecto y en la forma de construirlo sería muy grande. De momento no voy a contemplar todas estas posibilidades y voy a optar por una solución intermedia a la que puedo llegar rápidamente por un camino mucho más corto, y cuyos resultados me servirán como resultados parciales si más adelante quiero pasar al siguiente nivel. La idea entonces es la siguiente: dar soporte a compiladores tipo gcc, y como alternativa la posibilidad de delegar la construcción del proyecto a una herramienta externa. En el grupo de compiladores tipo gcc están el mismísimo gcc y sus ports como mingw32 y mingw64, mingw invocado a través de wine, versiones alternativas de gcc para compilación cruzada, y sobre todo Clang, ya que quienes diseñaron Clang tuvieron la buena idea de hacerlo compatible en cuanto a su uso y argumentos con gcc (en realidad, casi podría usar Clang en ZinjaI tal cual está ahora gracias a esto). Sólo tendré que revisar el parseo de los errores para tener en cuenta algunas diferencias y desactivar mis simplificaciones cuando no correspondan.

La idea es que ZinjaI tendrá en algún directorio archivos con las configuraciones de los toolchains disponibles (así como ahora tiene archivos con las combinaciones de colores por ejemplo), y que los proyectos podrán elegir uno de estos en cada perfil de compilación, y eventualmente proveer alguno propio. Y para tener más libertad sin cambiar tanto el IDE, habrá un tipo especial de toolchain que en realidad no va a definir cómo debe ZinjaI construir el proyecto utilizando tal o cual compilador, sino que va a servir para delegarle la responsabilidad a una herramienta o script externo, como por ejemplo make, cmake, scons, etc. De esta forma, si se quiere utilizar ZinjaI como editor, depurador, y por las herramientas integradas, pero establecer reglas de compilación que no soporta, se podrá hacer a través de alguno de estos mecanismos. Además, servirá también para abrir rápidamente en ZinjaI proyectos generados con otras herramientas.

Resumiendo, ZinjaI va a seguir por mucho tiempo basándose en gcc, pero irá abriendo las puertas a quien quiera experimentar con otras alternativas, o a quien necesite hacer cosas no previstas. Además, yo personalmente quiero jugar un poco con clang y llvm para ver si algunas de sus ventajas se pueden aprovechar en el editor como mencioné antes. No se cuando tendré tiempo de hacer los cambios, ni sé exactamente cuán grandes serán estos (aunque estimo que no serán terribles), así que por el momento son sólo ideas que van tomando forma. Si algún lector esperaba algo parecido puede aprovechar para comentar o plantear escenarios alternativos a considerar ahora de forma que cuando finalmente lo implemente deje conforme a la mayor cantidad de usuarios posibles. Y quien no necesite esta alternativa, no tendrá que hacer nada, ya que en las configuraciones por defecto todo seguirá como hasta ahora.


3 comentarios:

  1. Hola, Utilizo demasiado Zinjai, y para programar microcontroladores
    "CodeWarrior Development Studio for StarCore Eclipse IDE"
    http://www.eclipse.org/platform/

    Anteriormente Codewarrior no usaba eclipse, pero con este ultimo la diferencia de la interface es enormemente mas amigable, por ejemplo todas las funciones en el editor inician colapasadas, al igual que los comentarios, se puede configurar ademas las plantillas, no se tal ves , seria muy bueno que "clonaras" estas caracteristicas y las implementaras en Zinjai

    Gracias

    ResponderEliminar
  2. Hola que tal antes que nada felicitarlo por este gran proyecto y aprovecho para hacer una sugerencia

    archivo 1
    //Fecha.h
    class Fecha{
    public:
    int getDia();
    };

    archivo 2
    //Fecha.cpp
    int Fecha::getDia( int dia )
    {
    // implementacion
    }

    seria muy bueno si se subrayara la linea(estilo eclipse)
    int Fecha::getDia( int dia ) ya que el método getDia no recibe parámetros
    creo que esto es posible ya que ZinjaI conoce la definición del método.

    Gracias.

    ResponderEliminar
    Respuestas
    1. A ese tipo de cosas me refiero con "aprovechar las ventajas de llvm". Con gcc también se puede plantear algo parecido, aunque es un poco más lento y los errores menos descriptivos. De todas formas estuve dándole algunas vueltas al asunto. Me quedan unas cuantas dudas respecto a como meterlo en la interfaz, cuestiones de usabilidad o similares, para que sea útil y no molesto. Respecto a esto último, empecé por hacer pruebas en PSeInt que es más simple y ahí controlo todas las herramientas involucradas. Planeo escribir algo al respecto en el próximo post.

      Eliminar