سؤال

وبشكل أكثر تحديدا، بالنظر إلى اسم الحزمة الشبرية أحتاج إلى استرداد نفسه library-dirs الحقل الذي يمكن الحصول عليه مع ghc-pkg describe أمر من داخل برنامج تشغيل Haskell.

هل كانت مفيدة؟

المحلول

إليك ما يمكنني التوصل إليه من خلال تطل ghc-pkg مصدر الرمز.

ال getPkgInfos تقوم الدالة بإرجاع تعريفات الحزمة لجميع الحزم المثبتة (نأمل بما في ذلك الحزم المثبتة على المستخدم). مع هذا في يديك، يمكنك استرداد أدلة المكتبة ومعلومات الحزمة الأخرى. يرى وثائق للتفاصيل.

ال 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، لكنني لست متأكدا حقا. على أي حال، كشيء آخر، فعلت بعض الاختبارات الأولية ويبدو أن العمل، ولكن استخدامها على مسؤوليتك الخاصة.

نصائح أخرى

تنسيق قاعدة بيانات الحزم المثبتة 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])

هذا لا يطيع تكوين حزمة المستخدم، ولكن يجب أن يكون بداية.

اسأل Duncan Coutts على القوائم البريدية في Haskell-Cafe أو Cabal. (أنا جاد. هذا هو منتدى أفضل لأسئلة CABAL من تجاوز مكدس).

في بعض الأحيان عليك فقط توجيه الناس في منتدى مختلف.

إذا كنت تستخدم Cabal لتكوين وإنشاء برنامجك / المكتبة، فيمكنك استخدام الوحدة النمطية للمسارات الحسية.

على سبيل المثال، إذا كان لديك foo.cabal ملف، cabal سوف تولد Paths_foo الوحدة النمطية (انظر مصدرها تحت dist/build/autogen) ما يمكنك استيراده. هذه الوحدة تصدر وظيفة getLibDir :: IO FilePath التي لديها القيمة التي تبحث عنها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top