11{-# LANGUAGE TupleSections, LambdaCase, RecordWildCards, OverloadedStrings #-}
2- module Stg.Program where
2+ module Stg.Program
3+ ( getGhcStgAppModules
4+ , StgAppLinkerInfo (.. )
5+ , StgLibLinkerInfo (.. )
6+ , getAppLinkerInfo
7+ , StgModuleInfo (.. )
8+ , getFullpakModules
9+ , getJSONModules
10+ , StgAppLicenseInfo (.. )
11+ , StgAppForeignSourceInfo (.. )
12+ , collectProgramModules
13+ , getAppLicenseInfo
14+ , getAppForeignFiles
15+ , printSection
16+ --
17+ , getAppModuleMapping
18+ ) where
319
420import Control.Monad.IO.Class
521import Control.Monad
@@ -63,6 +79,7 @@ data UnitLinkerInfo =
6379 , unitLdOptions :: [String ]
6480 , unitExposedModules :: [String ]
6581 , unitHiddenModules :: [String ]
82+ , unitArtifactsDir :: Maybe FilePath
6683 } deriving (Eq , Show )
6784
6885instance FromJSON UnitLinkerInfo where
@@ -78,6 +95,7 @@ instance FromJSON UnitLinkerInfo where
7895 <*> v .:? " ld-options" .!= []
7996 <*> v .:? " exposed-modules" .!= []
8097 <*> v .:? " hidden-modules" .!= []
98+ <*> pure Nothing
8199 parseJSON _ = fail " Expected Object for UnitLinkerInfo value"
82100
83101data GhcStgApp
@@ -87,6 +105,7 @@ data GhcStgApp
87105 , appNoHsMain :: Bool
88106 , appGhcName :: String
89107 , appGhcVersion :: String
108+ , appTargetPlatform :: String
90109 , appPlatformOS :: String
91110 , appUnitDbPaths :: [FilePath ]
92111 , appObjectDir :: FilePath
@@ -109,6 +128,7 @@ instance FromJSON GhcStgApp where
109128 <*> v .: " no-hs-main"
110129 <*> v .: " ghc-name"
111130 <*> v .: " ghc-version"
131+ <*> v .: " target-platform"
112132 <*> v .: " platform-os"
113133 <*> v .:? " unit-db-paths" .!= []
114134 <*> v .: " object-dir"
@@ -130,9 +150,6 @@ wpcCapiStubsPath = "extra-compilation-artifacts" </> "wpc-plugin" </> "capi-stu
130150wpcWrapperStubsPath = " extra-compilation-artifacts" </> " wpc-plugin" </> " wrapper-stubs"
131151wpcCbitsSourcePath = " extra-compilation-artifacts" </> " wpc-plugin" </> " cbits-source"
132152
133- readGhcStgApp :: FilePath -> IO GhcStgApp
134- readGhcStgApp = Y. decodeFileThrow
135-
136153getAppModuleMapping :: FilePath -> IO [StgModuleInfo ]
137154getAppModuleMapping ghcStgAppFname = do
138155 let showLog = False -- TODO: use RIO ???
@@ -155,7 +172,7 @@ getAppModuleMapping ghcStgAppFname = do
155172 , modUnitId = unitId
156173 }
157174 | UnitLinkerInfo {.. } <- appLibDeps
158- , dir <- unitImportDirs
175+ , Just dir <- [unitArtifactsDir]
159176 , mod <- unitExposedModules ++ unitHiddenModules
160177
161178 -- TODO: make this better somehow
@@ -295,10 +312,10 @@ getAppLinkerInfo ghcStgAppFname = do
295312 -}
296313 libInfoList <- forM appLibDeps $ \ UnitLinkerInfo {.. } -> do
297314
298- cbitsPathList <- forM unitLibDirs $ \ path -> do
315+ cbitsPathList <- forM (maybeToList unitArtifactsDir) $ \ path -> do
299316 findIfExists always (extension ==? " .dyn_o" ) $ path </> wpcCbitsPath
300317
301- capiStubsPathList <- forM unitLibDirs $ \ path -> do
318+ capiStubsPathList <- forM (maybeToList unitArtifactsDir) $ \ path -> do
302319 findIfExists always (extension ==? " .dyn_o" ) $ path </> wpcCapiStubsPath
303320
304321 pure $ StgLibLinkerInfo
@@ -380,7 +397,7 @@ getAppForeignFiles ghcStgAppFname = do
380397 | p <- appCbitsSources
381398 ]
382399 libsCbitsInfos <- forM appLibDeps $ \ UnitLinkerInfo {.. } -> do
383- forM unitLibDirs $ \ path -> do
400+ forM (maybeToList unitArtifactsDir) $ \ path -> do
384401 let libSrcDir = path </> wpcCbitsSourcePath
385402 libCbitsSources <- findIfExists always (fileType ==? RegularFile ) libSrcDir
386403 pure
@@ -393,3 +410,105 @@ getAppForeignFiles ghcStgAppFname = do
393410 ]
394411
395412 pure $ appCbitsInfos ++ (concat $ concat libsCbitsInfos)
413+
414+ readGhcStgApp :: FilePath -> IO GhcStgApp
415+ readGhcStgApp fname = do
416+ ghcStgApp <- Y. decodeFileThrow fname
417+ PakYaml {.. } <- getFoundationPakForGhcStgApp fname
418+ let foundationUnitMap = Map. fromList
419+ [ (pakUnitId, pakUnitDir)
420+ | PakUnitInfo {.. } <- pakyamlPackages
421+ ]
422+
423+ wiredInUnitIds = Set. fromList
424+ [ " base"
425+ , " ghc"
426+ , " ghc-bignum"
427+ , " ghc-prim"
428+ , " rts"
429+ , " template-haskell"
430+ ]
431+
432+ -- HINT: create versioned unit-id
433+ calculateUnitId UnitLinkerInfo {.. }
434+ -- handle wired-in units
435+ | Set. member unitId wiredInUnitIds
436+ = unitName ++ " -" ++ unitVersion
437+
438+ | otherwise
439+ = unitId
440+
441+ pure $ ghcStgApp
442+ { appLibDeps =
443+ [ uli {unitArtifactsDir = Just $ Map. findWithDefault (head unitImportDirs) (calculateUnitId uli) foundationUnitMap}
444+ | uli@ UnitLinkerInfo {.. } <- appLibDeps ghcStgApp
445+ ]
446+ }
447+
448+ -- foundation-pak handling
449+
450+ foundationPakCachePath :: IO FilePath
451+ foundationPakCachePath = do
452+ home <- getHomeDirectory
453+ pure $ home </> " .estg/foundation-pak"
454+
455+ -- example URL: https://github.com/haskell/haskell-language-server/releases/download/2.0.0.0/haskell-language-server-2.0.0.0-aarch64-apple-darwin.tar.xz
456+
457+ foundationPakURL :: String -> String
458+ foundationPakURL ghcVersion = " https://github.com/grin-compiler/foundation-pak/releases/download/" ++ ghcVersion
459+
460+ getFoundationPakForGhcStgApp :: FilePath -> IO PakYaml
461+ getFoundationPakForGhcStgApp ghcstgapp = do
462+ GhcStgApp {.. } <- Y. decodeFileThrow ghcstgapp
463+ root <- foundationPakCachePath
464+ -- foundation-pak name schema: `ghc-name`-`ghc-version`-`target-platform`.pak.zip
465+ let foundationPakName = printf " %s-%s-%s" appGhcName appGhcVersion appTargetPlatform
466+ foundationPakPath = root </> foundationPakName
467+ {-
468+ TODO:
469+ check foundationPakPath locally
470+ if not present, create URL and download it to foundationPakPath
471+ load the content from foundationPakPath
472+ -}
473+ let prefixPakUnitDirs :: FilePath -> PakYaml -> PakYaml
474+ prefixPakUnitDirs dir p@ PakYaml {.. } = p
475+ { pakyamlPackages =
476+ [ u {pakUnitDir = dir </> pakUnitDir}
477+ | u@ PakUnitInfo {.. } <- pakyamlPackages
478+ ]
479+ }
480+
481+ pakYaml <- Y. decodeFileThrow (foundationPakPath </> " pak.yaml" )
482+ pure $ prefixPakUnitDirs foundationPakPath pakYaml
483+
484+ data PakUnitInfo
485+ = PakUnitInfo
486+ { pakUnitName :: String
487+ , pakUnitVersion :: String
488+ , pakUnitId :: String
489+ , pakUnitDir :: FilePath
490+ }
491+ deriving (Eq , Ord , Show )
492+
493+ instance FromJSON PakUnitInfo where
494+ parseJSON (Y. Object v) =
495+ PakUnitInfo
496+ <$> v .: " name"
497+ <*> v .: " version"
498+ <*> v .: " id"
499+ <*> v .: " dir"
500+ parseJSON _ = fail " Expected Object for PakUnitInfo value"
501+
502+ data PakYaml
503+ = PakYaml
504+ { pakyamlPathPrefix :: FilePath
505+ , pakyamlPackages :: [PakUnitInfo ]
506+ }
507+ deriving (Eq , Ord , Show )
508+
509+ instance FromJSON PakYaml where
510+ parseJSON (Y. Object v) =
511+ PakYaml
512+ <$> v .: " path-prefix"
513+ <*> v .: " packages"
514+ parseJSON _ = fail " Expected Object for PakYaml value"
0 commit comments