如何以编程方式检索 GHC 包信息?
题
更具体地说,给定一个任意的包名称,我需要检索相同的包名称 library-dirs
可以通过以下方式获得的字段 ghc-pkg describe
来自正在运行的 Haskell 程序内部的命令。
解决方案
这是我能想出的窥视到ghc-pkg
源代码。
在getPkgInfos
函数返回所有安装的软件包(希望包括用户已安装的包)的包定义。有了这个在你的手中,你可以检索库目录和其他包的信息。请参见的文档的的信息。
在GHC_PKGCONF
变量需要指向对于其中它不位于通常的地方系统的全球包配置文件。 ghc-pkg
通过经由在Ubuntu包装脚本接收命令行标志,例如解决了这个问题。
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
我写这个代码自己,但它在很大程度上是由GHC-PKG启发(有一些片逐字复制)。原始代码是在BSD风格的许可证许可的,我认为这是可以根据cc-wiki许可证的所有内容#1正在分发,但我真的不知道。无论如何,别的,我做了一些初步的测试,它似乎工作,但需要您自担风险使用它。
其他提示
已安装软件包数据库的格式为 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])
这不遵循用户的包配置,但应该是一个开始。
向邓肯库茨上Haskell的咖啡厅或@小集团邮件列表。 (我是认真的,这是惊天动地的问题比栈溢出更好论坛)。
有时候,你必须在不同的论坛,以点人。
如果您正在使用阴谋配置和构建你的程序/库,你可以使用自动生成的Paths_ *模块。
例如,如果有一个文件foo.cabal
,小集团将生成Paths_foo
模块(参见其下dist/build/autogen
源),其可以导入。该模块导出的函数getLibDir :: IO FilePath
其中有您正在寻找的价值。
不隶属于 StackOverflow