GHC 패키지 정보를 프로그래밍 방식으로 검색하는 방법은 무엇입니까?
문제
보다 구체적으로, 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
당신이 찾고있는 가치가 있습니다.