Skip to content

Commit 99be0b1

Browse files
committed
add local foundation-pak handling
1 parent 440b6e3 commit 99be0b1

File tree

1 file changed

+127
-8
lines changed

1 file changed

+127
-8
lines changed

external-stg/lib/Stg/Program.hs

Lines changed: 127 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
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

420
import Control.Monad.IO.Class
521
import 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

6885
instance 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

83101
data 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
130150
wpcWrapperStubsPath = "extra-compilation-artifacts" </> "wpc-plugin" </> "wrapper-stubs"
131151
wpcCbitsSourcePath = "extra-compilation-artifacts" </> "wpc-plugin" </> "cbits-source"
132152

133-
readGhcStgApp :: FilePath -> IO GhcStgApp
134-
readGhcStgApp = Y.decodeFileThrow
135-
136153
getAppModuleMapping :: FilePath -> IO [StgModuleInfo]
137154
getAppModuleMapping 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

Comments
 (0)