【问题标题】:How to programmatically retrieve GHC package information?如何以编程方式检索 GHC 包信息?
【发布时间】:2009-10-05 20:05:17
【问题描述】:

更具体地说,给定一个任意包名称,我需要检索相同的 library-dirs 字段,该字段可以通过正在运行的 Haskell 程序中的 ghc-pkg describe 命令获得。

【问题讨论】:

    标签: haskell ghc cabal hackage


    【解决方案1】:

    通过查看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。跨度>
    • 我试图找到所有 ghc-pkg 找到的,以模仿它的行为。
    【解决方案2】:

    已安装包数据库的格式为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])
    

    这不服从用户的包配置,但应该是一个开始。

    【讨论】:

      【解决方案3】:

      在 haskell-cafe@ 或 cabal 邮件列表上询问 Duncan Coutts。 (我是认真的。这是一个比堆栈溢出更好的 Cabal 问题论坛)。

      有时您只需将人们指向不同的论坛。

      【讨论】:

        【解决方案4】:

        如果您使用 cabal 来配置和构建您的程序/库,您可以使用自动生成的 Paths_* 模块。

        例如,如果您有一个foo.cabal 文件,cabal 将生成一个您可以导入的Paths_foo 模块(参见dist/build/autogen 下的源代码)。此模块导出一个函数getLibDir :: IO FilePath,它具有您要查找的值。

        【讨论】:

        • 感谢您的回答,但这不是我想要的。我需要检索其他已安装包的 lib 目录,而不是我自己的。
        猜你喜欢
        • 2016-12-04
        • 1970-01-01
        • 1970-01-01
        • 2014-03-18
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多