GHC 패키지 정보를 프로그래밍 방식으로 검색하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/1522104

  •  19-09-2019
  •  | 
  •  

문제

보다 구체적으로, arbritary 패키지 이름을 감안할 때 나는 동일하게 검색해야합니다. library-dirs TH에서 얻을 수있는 필드 ghc-pkg describe 실행중인 Haskell 프로그램 내부에서 명령.

도움이 되었습니까?

해결책

다음은 ghc-pkg 소스 코드.

그만큼 getPkgInfos 함수는 설치된 모든 패키지 (사용자 설치 패키지 포함)에 대한 패키지 정의를 반환합니다. 이것으로 당신의 손에 도서관 디렉토리 및 기타 패키지 정보를 검색 할 수 있습니다. 보다 문서 자세한 내용은.

그만큼 GHC_PKGCONF 변수는 일반적인 장소에 있지 않은 시스템의 글로벌 패키지 구성 파일을 가리켜 야합니다. ghc-pkg 예를 들어 우분투의 래퍼 스크립트를 통해 명령 줄 플래그를 수신 하여이 문제를 해결합니다.

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 컨텐츠가 아래에있는 CC-Wiki 라이센스에 따라 배포 될 수 있다고 생각합니다. 어쨌든, 다른 어떤 것과 같이, 나는 초기 테스트를했는데 효과가있는 것처럼 보이지만 자신의 위험에 따라 사용합니다.

다른 팁

설치된 패키지 데이터베이스의 형식은 다음과 같습니다 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을 사용하여 프로그램/라이브러리를 구성하고 빌드하는 경우 자동 생성 경로 _* 모듈을 사용할 수 있습니다.

예를 들어, 당신이있는 경우 foo.cabal 파일, Cabal은 a를 생성합니다 Paths_foo 모듈 (아래의 소스 참조) dist/build/autogen) 가져올 수 있습니다. 이 모듈은 함수를 내 보냅니다 getLibDir :: IO FilePath 당신이 찾고있는 가치가 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top