Domanda

In particolare, dato un nome di pacchetto arbritary ho bisogno di recuperare lo stesso campo library-dirs che si può ottenere con il comando ghc-pkg describe dall'interno di un programma di Haskell in esecuzione.

È stato utile?

Soluzione

Ecco quello che ho potuto venire con sbirciando nel codice sorgente ghc-pkg.

La funzione restituisce i getPkgInfos definizioni di pacchetto per tutti i pacchetti installati (si spera inclusi i pacchetti installati dall'utente). Con questo nelle vostre mani, è possibile recuperare le directory di libreria e altre informazioni di pacchetto. Vedere la documentazione per i dettagli.

La variabile GHC_PKGCONF deve puntare al file di configurazione del pacchetto globale per i sistemi in cui non si trova al solito posto. ghc-pkg risolve questo problema ricevendo un flag della riga di comando tramite uno script involucro in Ubuntu, per esempio.

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

Ho scritto questo codice me stesso, ma è stato in gran parte ispirato da GHC-pkg (con alcuni pezzi copiati pari pari). Il codice originale è stato rilasciato sotto una licenza BSD-style, credo che questo possa essere distribuito sotto la licenza CC-wiki tutti i contenuti StackOverflow è sotto, ma io non sono davvero sicuro. In ogni caso, come qualsiasi altra cosa, ho fatto alcuni test iniziale e sembra funzionare, ma usarlo a vostro rischio e pericolo.

Altri suggerimenti

Il formato del database dei pacchetti installati è 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])

Questa non obbedisce configurazione del pacchetto per l'utente, ma dovrebbe essere un inizio.

Chiedi Duncan Coutts sulla mailing list cabala Haskell-Cafe @ o. (Dico sul serio. Questo è un forum per le domande più Cabal di overflow dello stack).

A volte basta puntare la gente in un forum diverso.

Se stai usando cabala per configurare e costruire il vostro programma / libreria si può utilizzare il Paths_ generato automaticamente * modulo.

Ad esempio, se si dispone di un file foo.cabal, cabala genererà un modulo Paths_foo (vedi la sua fonte in dist/build/autogen), che è possibile importare. Questo modulo esporta una funzione getLibDir :: IO FilePath, che ha il valore che stai cercando.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top