Pergunta

Mais especificamente, dado um nome de pacote arbritary eu preciso para recuperar o mesmo campo library-dirs que pode ser obtido com o comando ghc-pkg describe de dentro de um programa Haskell em execução.

Foi útil?

Solução

Aqui está o que eu poderia vir acima com por espreitar para o código-fonte ghc-pkg.

A função getPkgInfos retorna as definições de pacote para todos os pacotes instalados (espero incluindo pacotes instalados pelo usuário). Com isto em suas mãos, você pode recuperar os diretórios de bibliotecas e outras informações pacote. Consulte documentação para detalhes.

A variável GHC_PKGCONF precisa apontar para o arquivo de configuração pacote global para sistemas onde ele não está localizado no lugar de costume. resolve ghc-pkg esse problema ao receber um sinalizador de linha de comando por meio de um script wrapper no Ubuntu, por exemplo.

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

Eu escrevi este código de mim mesmo, mas foi em grande parte inspirado pelo GHC-pacote (com algumas peças copiada verbatim). O código original foi licenciada sob uma licença BSD, eu acho que isso pode ser distribuído sob a cc-wiki licenciar todos os conteúdos Stackoverflow é baixo, mas eu não tenho certeza. Enfim, como qualquer outra coisa, eu fiz alguns testes iniciais e parece trabalho, mas usá-lo em seu próprio risco.

Outras dicas

O formato do banco de dados de pacotes instalados é 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])

Esta não obedecer a configuração do pacote do usuário, mas deve ser um começo.

Pergunte Duncan Coutts na listas de discussão cabal haskell-cafe @ ou. (Estou falando sério. Isso é um melhor fórum para perguntas Cabal que estouro de pilha).

Às vezes você apenas tem que ponto as pessoas em um fórum diferente.

Se você estiver usando cabal para configurar e construir o seu programa / biblioteca você pode utilizar o Paths_ * módulo gerada automaticamente.

Por exemplo, se você tem um arquivo foo.cabal, cabala irá gerar um módulo Paths_foo (ver sua fonte sob dist/build/autogen), que você pode importar. Este exportações módulo A getLibDir :: IO FilePath função que tem o valor que você está procurando.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top