Pregunta

Más específicamente, dado un nombre de paquete arbritary que necesito para recuperar el mismo campo library-dirs que se puede obtener con el comando ghc-pkg describe desde dentro de un programa de Haskell en funcionamiento.

¿Fue útil?

Solución

Esto es lo que podría llegar a por asomándose en el código fuente ghc-pkg.

La función getPkgInfos devuelve las definiciones de paquetes para todos los paquetes instalados (esperemos incluidos los paquetes instalados por el usuario). Con esto en sus manos, puede recuperar los directorios de la biblioteca y otra información del paquete. Ver la documentación para detalles.

La variable GHC_PKGCONF necesita apuntar al archivo de configuración del paquete global para sistemas en los que no se encuentra en el lugar habitual. ghc-pkg resuelve este problema mediante la recepción de una marca de línea de comandos a través de un script de envoltorio en Ubuntu, por ejemplo.

import qualified Config
import qualified System.Info
import Data.List
import Distribution.InstalledPackageInfo
import GHC.Paths
import System.Directory
import System.Environment
import System.FilePath
import System.IO.Error

getPkgInfos :: IO [InstalledPackageInfo]
getPkgInfos = do
    global_conf <-
        catch (getEnv "GHC_PKGCONF")
              (\err ->  if isDoesNotExistError err
                            then do let dir = takeDirectory $ takeDirectory ghc_pkg
                                        path1 = dir </> "package.conf"
                                        path2 = dir </> ".." </> ".." </> ".."
                                                    </> "inplace-datadir"
                                                    </> "package.conf"
                                    exists1 <- doesFileExist path1
                                    exists2 <- doesFileExist path2
                                    if exists1 then return path1
                                       else if exists2 then return path2
                                       else ioError $ userError "Can't find package.conf"
                            else ioError err)

    let global_conf_dir = global_conf ++ ".d"
    global_conf_dir_exists <- doesDirectoryExist global_conf_dir
    global_confs <-
        if global_conf_dir_exists
            then do files <- getDirectoryContents global_conf_dir
                    return  [ global_conf_dir ++ '/' : file
                            | file <- files
                            , isSuffixOf ".conf" file]
            else return []

    user_conf <-
        try (getAppUserDataDirectory "ghc") >>= either
            (\_ -> return [])
            (\appdir -> do
                let subdir = currentArch ++ '-':currentOS ++ '-':ghcVersion
                    user_conf = appdir </> subdir </> "package.conf"
                user_exists <- doesFileExist user_conf
                return (if user_exists then [user_conf] else []))

    let pkg_dbs = user_conf ++ global_confs ++ [global_conf]
    return.concat =<< mapM ((>>= return.read).readFile) pkg_dbs

currentArch = System.Info.arch
currentOS = System.Info.os
ghcVersion = Config.cProjectVersion

escribí este código a mí mismo, pero estaba inspirado en gran medida por GHC-paquete (con algunas piezas copiadas textualmente). El código original fue licenciado bajo una licencia de tipo BSD, creo que esto puede ser distribuido bajo la licencia CC-wiki de todos los contenidos Stackoverflow es bajo, pero no estoy muy seguro. De todos modos, como cualquier otra cosa, hice algunas pruebas iniciales y parece que funciona, sino que lo utiliza a su propio riesgo.

Otros consejos

El formato de la base de datos instalado paquetes es Distribution.InstalledPackageInfo .

import Distribution.InstalledPackageInfo
import Distribution.Package
import Distribution.Text
import GHC.Paths
import System
import System.FilePath
main = do
    name:_ <- getArgs
    packages <- fmap read $ readFile $ joinPath [libdir, "package.conf"]
    let matches = filter ((PackageName name ==) . pkgName . package) packages
    mapM_ (print . libraryDirs) (matches :: [InstalledPackageInfo_ String])

Esto no obedece configuración del paquete del usuario, pero debe ser un comienzo.

Haz Duncan Coutts en la listas de correo Cabal Haskell-café o @. (Lo digo en serio. Esa es una mejor foro de preguntas que Cabal desbordamiento de pila).

A veces sólo hay que señalar a la gente en un foro diferente.

Si está utilizando Cabal para configurar y construir su programa / biblioteca puede utilizado el Paths_ autogenerado * módulo.

Por ejemplo, si tiene un archivo foo.cabal, cábala generará un módulo Paths_foo (ver su fuente bajo dist/build/autogen), que puede importar. Este módulo exporta una getLibDir :: IO FilePath función que tiene el valor que está buscando.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top