2009-10-05 10 views

답변

3

다음은 소스 코드 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 스타일의 라이센스하에 라이센스를 받았으며,이 모든 것은 Stackoverflow 컨텐츠가 아래에있는 cc-wiki 라이센스하에 배포 될 수 있다고 생각하지만 실제로는 잘 모르겠습니다. 어쨌든, 다른 어떤 것으로서, 나는 초기 테스트를했는데 제대로 작동하는 것으로 보인다.

+0

그래, 그게 기본적으로 내가 쓴 것보다 포괄적 인 버전이야. 단 하나의 하드 코딩 된'% GHC_ROOT %/package.conf'를 사용하는 대신에, 당신은 정규적으로 사용되는 것들 모두를 찾은 것 같아요. – ephemient

+0

ghc-pkg가 그 동작을 모방하기 위해 찾은 모든 것을 찾으려고했습니다. –

0

cabal을 사용하여 프로그램/라이브러리를 구성하고 빌드하는 경우 자동 생성 된 Paths_ * 모듈을 사용할 수 있습니다.

예를 들어 파일이 foo.cabal 인 경우 cabal은 모듈 (해당 소스는 dist/build/autogen 참조)을 가져올 수 있습니다. 이 모듈은 찾고있는 값을 가진 getLibDir :: IO FilePath 함수를 내 보냅니다.

+0

답변 주셔서 감사합니다.하지만 그건 내가 찾고있는 것이 아닙니다. 내 설치 패키지가 아닌 다른 lib 디렉토리를 가져와야합니다. –

1

설치된 패키지 데이터베이스의 형식은 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]) 

이것은 사용자의 패키지 구성을 따르지는 않지만 시작이어야합니다.

1

haskell-cafe @ 또는 cabal 메일 링리스트에서 Duncan Coutts에게 질문하십시오. (나는 진지해. 스택 오버플로보다 카발 질문에 더 좋은 포럼이다.)

간혹 다른 포럼에 사람들을 안내해야 할 때가 있습니다.