【发布时间】:2009-10-05 20:05:17
【问题描述】:
更具体地说,给定一个任意包名称,我需要检索相同的 library-dirs 字段,该字段可以通过正在运行的 Haskell 程序中的 ghc-pkg describe 命令获得。
【问题讨论】:
更具体地说,给定一个任意包名称,我需要检索相同的 library-dirs 字段,该字段可以通过正在运行的 Haskell 程序中的 ghc-pkg describe 命令获得。
【问题讨论】:
通过查看ghc-pkg 源代码,我可以得出以下结论。
getPkgInfos 函数返回所有已安装包的包定义(希望包括用户安装的包)。有了它,您可以检索库目录和其他包信息。详情请见the documentation。
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 许可下分发所有 Stackoverflow 内容,但我不太确定。无论如何,和其他任何事情一样,我做了一些初步测试,它似乎有效,但使用它需要您自担风险。
【讨论】:
%GHC_ROOT%/package.conf。跨度>
已安装包数据库的格式为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-cafe@ 或 cabal 邮件列表上询问 Duncan Coutts。 (我是认真的。这是一个比堆栈溢出更好的 Cabal 问题论坛)。
有时您只需将人们指向不同的论坛。
【讨论】:
如果您使用 cabal 来配置和构建您的程序/库,您可以使用自动生成的 Paths_* 模块。
例如,如果您有一个foo.cabal 文件,cabal 将生成一个您可以导入的Paths_foo 模块(参见dist/build/autogen 下的源代码)。此模块导出一个函数getLibDir :: IO FilePath,它具有您要查找的值。
【讨论】: