2012-02-16 8 views
8

Imagínese un Makefile como el siguiente:"Bootstrapping" con Cabal

stage1 : Stage1.hs 
     ghc -o stage1 Stage1.hs 
Stage1.hs : stage0 
     stage0 > Stage1.hs 
stage0 : Stage0.hs 
     ghc -o stage0 Stage0.hs 

El directorio actual contendría Makefile y Stage0.hs en un primer momento, y producir stage1.

Aquí están las preguntas:

  1. ¿Cómo puedo hacer lo anterior enteramente dentro de Cabal? ¿Se supone que debo hacer esto solo con ganchos? (como this o this.) ¿Qué pasa si el gancho debe depender de otro programa en el paquete que se va a construir?
  2. ¿Qué pasa si Setup.hs se vuelve lo suficientemente complicado como para requerir su propia gestión de dependencias ?
  3. ¿Hay un paquete cabalizado que haga cosas similares? Si Happy incluye un programa de prueba cabalizado que depende de la invocación Feliz, ese hubiera sido un ejemplo perfecto.
+1

En el caso de Happy y Alex, Cabal ya sabe cómo lidiar con eso, por lo que solo necesita enumerar los módulos en 'Módulos expuestos' o 'Otros-Módulos' y Cabal generará el '.hs' archivos y compilarlos automáticamente. – hammar

+0

Eso es verdad. Quizás debería mencionar [preprocessor-tools] (http://hackage.haskell.org/package/preprocessor-tools) en su lugar. – mnish

Respuesta

5

Cabal es complicado cuando se trata de situaciones como estas.

Como dijiste, si puedes incluir todo en Setup.hs, mantendrás el número de dolores de cabeza al mínimo.

Si usted tiene realmente preprocesadores complicados, sugeriría hacer esto:

  1. hacer el paquete una cábala para cada preprocesador, con sus propias dependencias, etc. Así, por stage0, que tendría una cábala de archivo como este:

    Name: 
        mypackage-stage0 
    Version: 
        0.1 
    -- ... 
    
    Executable mpk-stage0 
        Default-language: 
        Haskell2010 
        Main-is: 
        Stage0.hs 
        -- ... 
    
  2. para stage1, es necesario generar el código fuente, por lo que añadir un gancho en su preBuildSetup.hs para mypackage-stage1 que ejecuta el ejecutable mpk-stage0:

    main = 
        defaultMainWithHooks simpleUserHooks 
        { preBuild = 
         -- ... something involving `system "mpk-stage1 Stage1.hs"` 
         -- Note that shell redirection `> bla.hs` doesn't necessarily work 
         -- on all platforms, so make your `mpk-stage1` executable take an 
         -- output file argument 
        } 
    

    te habían continuación, agregar una dependencia de construcción-herramienta en la etapa anterior:

    Executable mpk-stage1 
        -- ... 
        Main-is: 
        Stage1.hs 
        Build-tools: 
        mypackage-stage0 
    

    Esto debería funcionar en las versiones recientes cabal; de lo contrario, es posible que deba agregar una dependencia Build-depends: en su lugar.

  3. Usted se necesidad de reconstruir cada paquete a su vez, cada vez que haces un cambio en cascada (Esto es necesario porque Cabal no logra cambios de dependencias entre proyectos), por lo que necesita un script que hace for project in mypackage-stage0 mypackage-stage1; do (cd $project; cabal install); done o algo similar.

Cabal nunca se construyó para este tipo de proyectos, por lo que se ser difícil si usted quiere hacer algo como esto. Debería considerar usar Template Haskell en su lugar si desea generar código de una manera más coherente.

+1

Muchas gracias por su rápida respuesta, y lo siento por llegar tarde. Que Cabal nunca fue construido para este tipo de proyecto fue de hecho lo que sospechaba. FYI, mi solución temporal fue agregar una bandera a cada ejecutable, y usar el maestro Makefile.am para manejar la compilación. Su sugerencia parece una mejora, pero aparece – mnish

+0

otras preguntas. ¿Qué sucede si no quiero instalar stage0 en el sistema del usuario? ¿Es posible registrar un paquete temporal localmente en el sistema de compilación? ¿Compatible con Template Haskell la generación de código de múltiples etapas? Por último, ¿se supone que debo escribir aquí como comentarios si encuentro las respuestas yo mismo? ¿O publicar otra respuesta respondiendo mi propia pregunta? ¡Gracias! – mnish

+2

Lamentablemente, no puede hacer ejecutables temporales. La plantilla Haskell se puede usar en múltiples etapas; puede usar TH para generar el código TH que genera el código Haskell. Si crees que tu respuesta ayudará a otros, debes publicar tu propia respuesta. – dflemstr

Cuestiones relacionadas