Frage

Insbesondere ein arbritary Paketnamen gegeben Ich brauche die gleiche library-dirs Feld abzurufen, die mit dem ghc-pkg describe Befehl aus dem Inneren eines laufenden Haskell-Programm erhalten werden kann.

War es hilfreich?

Lösung

Hier ist, was ich tun konnte, indem sie in den ghc-pkg Quellcode späht.

Die getPkgInfos Funktion gibt die Paketdefinitionen für alle installierten Pakete (hoffentlich einschließlich vom Benutzer installierten Pakete). Mit diesem in der Hand, können Sie die Bibliotheksverzeichnisse und andere Paketinformationen abzurufen. Siehe der Dokumentation Details.

Die GHC_PKGCONF Variable muss Punkt für die globale Paket-Konfigurationsdatei für Systeme, bei denen es nicht an der üblichen Stelle befindet. ghc-pkg löst dieses Problem, indem Sie einen Befehlszeile-Flag über einen Wrapper-Skript in Ubuntu zum Beispiel zu empfangen.

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

Ich schrieb diesen Code selbst, aber es wurde von GHC-pkg weitgehend inspiriert (mit einigen Stücken kopiert wörtlich). Der ursprüngliche Code wurde unter einer BSD-Lizenz veröffentlicht, ich denke, das unter dem verteilt werden kann cc-wiki Lizenz alle Stackoverflow Inhalt unter, aber ich bin nicht wirklich sicher. Wie auch immer, wie alles andere, ich habe einige erste Tests und es scheint zu funktionieren, aber auf eigene Gefahr.

Andere Tipps

Das Format der installierten Pakete Datenbank 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])

Dies ist nicht die Paketkonfiguration des Benutzers gehorcht, soll aber ein Anfang sein.

Stellen Sie Duncan Coutts auf der Haskell-Cafe @ oder Kabale Mailinglisten. (Ich meine es ernst. Das ist ein besseres Forum für Cabal Fragen als Stack-Überlauf).

Manchmal muss man nur zu Punkt Menschen an einem anderen Forum.

Wenn Sie Kabalen zu konfigurieren verwenden und bauen Sie Ihre Programm / Bibliothek Sie die automatisch generierte Paths_ verwendet wird, kann * Modul.

Zum Beispiel, wenn Sie eine Datei foo.cabal haben, Kabale einen Paths_foo Modul (siehe seine Quelle unter dist/build/autogen) erzeugen, die Sie importieren können. Dieses Modul exportiert eine Funktion getLibDir :: IO FilePath, die den Wert Sie suchen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top