-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconvert.hs
executable file
·107 lines (101 loc) · 3.7 KB
/
convert.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/usr/bin/env nix-shell
#! nix-shell -i runghc -p "haskell.packages.ghc982.ghcWithPackages (ps: with ps; [cabal-install-parsers pathwalk pretty-show])"
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedRecordUpdate #-}
{-# LANGUAGE PackageImports #-}
{-# LANGUAGE PolyKinds #-}
import Cabal.Package (readPackage)
import Data.Foldable
import Data.List (intercalate)
import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map
import System.Directory.PathWalk
import System.FilePath
import Text.Show.Pretty (pPrint)
import "Cabal-syntax" Distribution.Compiler
import "Cabal-syntax" Distribution.Pretty (prettyShow)
import "Cabal-syntax" Distribution.Types.BuildInfo
import "Cabal-syntax" Distribution.Types.CondTree
import "Cabal-syntax" Distribution.Types.Dependency
import "Cabal-syntax" Distribution.Types.GenericPackageDescription
import "Cabal-syntax" Distribution.Types.Library
import "Cabal-syntax" Distribution.Types.LibraryName
import "Cabal-syntax" Distribution.Types.PackageDescription
import "Cabal-syntax" Distribution.Types.PackageId
import "Cabal-syntax" Distribution.Types.PackageName
data Buck2PackageDesc = Buck2PackageDesc
{ directory :: String,
sources :: [String],
extensions :: [String],
options :: [String],
dependencies :: [String]
}
deriving (Show)
parseCabal :: FilePath -> IO (Map String Buck2PackageDesc)
parseCabal filepath = do
genPkgDesc <- readPackage filepath
let name = unPackageName genPkgDesc.packageDescription.package.pkgName
let (srcs, extensions, options, dependencies) = flip foldMap (genPkgDesc.condLibrary) $ \case
CondNode {condTreeData = library@Library {libName = LMainLibName}} ->
( map prettyShow library.libBuildInfo.hsSourceDirs,
map prettyShow library.libBuildInfo.defaultExtensions,
fold library.libBuildInfo.options,
map (unPackageName . depPkgName) library.libBuildInfo.targetBuildDepends
)
_ -> mempty
pure $
Map.singleton name $
Buck2PackageDesc
{ directory = takeDirectory filepath,
sources = srcs,
extensions = extensions,
options = options,
dependencies = dependencies
}
collectCabals :: FilePath -> IO (Map String Buck2PackageDesc)
collectCabals = flip pathWalkAccumulate $ \dir _ files ->
case find isCabal files of
Nothing -> mempty
Just cabal -> parseCabal $ dir </> cabal
where
isCabal filepath = takeExtension filepath == ".cabal"
genTarget :: String -> Buck2PackageDesc -> Map String Buck2PackageDesc -> String
genTarget name desc pkgMap =
"extensions = [\n"
++ concat [" \"" ++ ext ++ "\",\n" | ext <- desc.extensions]
++ "]\n\n"
++ "ghc_flags = [\"-X\" + ext for ext in extensions] + [\n"
++ concat [" \"" ++ flag ++ "\",\n" | flag <- desc.options]
++ "]\n\n"
++ "haskell_library(\n"
++ " name = \""
++ name
++ "\",\n"
++ " srcs = glob(["
++ intercalate
", "
[ "\"" ++ src ++ "/**/*" ++ ext ++ "\""
| src <- desc.sources,
ext <- [".hs", ".hs-boot"]
]
++ "]),\n"
++ " compiler_flags = ghc_flags,\n"
++ " visibility = [\"//amazonka/...\"],\n"
++ " deps = [\n"
++ concat
[ " \""
++ case Map.lookup dep pkgMap of
Just depPkg -> "//" ++ depPkg.directory ++ ":" ++ dep
Nothing -> "//haskell:" ++ dep
++ "\",\n"
| dep <- desc.dependencies
]
++ " ],\n"
++ ")\n"
main :: IO ()
main = do
pkgMap <- collectCabals "amazonka/lib"
forM_ (Map.toList pkgMap) $ \(name, pkg) -> do
writeFile (pkg.directory </> "BUCK") (genTarget name pkg pkgMap)