Skip to content

Commit 06f6397

Browse files
Add hpack configuration option.
1 parent 7b07c46 commit 06f6397

10 files changed

Lines changed: 87 additions & 22 deletions

File tree

ChangeLog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ Behavior changes:
5151

5252
Other enhancements:
5353

54+
* The `with-hpack` configuration option specifies an Hpack executable to use
55+
instead of the Hpack bundled with Stack. Please
56+
see [#3179](https://github.com/commercialhaskell/stack/issues/3179).
5457
* It's now possible to skip tests and benchmarks using `--skip`
5558
flag
5659
* `GitSHA1` is now `StaticSHA256` and is implemented using the `StaticSize 64 ByteString` for improved performance.

doc/faq.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,3 +528,4 @@ Yes:
528528
529529
* If a package directory contains an Hpack `package.yaml` file, then Stack will use it to generate a `.cabal` file when building the package.
530530
* You can run `stack init` to initialize a `stack.yaml` file regardless of whether your packages are declared with `.cabal` files or with Hpack `package.yaml` files.
531+
* You can use the `with-hpack` configuration option to specify an Hpack executable to use instead of the Hpack bundled with Stack.

doc/yaml_configuration.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,14 @@ Specify a path to gcc explicitly, rather than relying on the normal path resolut
460460
with-gcc: /usr/local/bin/gcc-5
461461
```
462462

463+
### with-hpack
464+
465+
Use an Hpack executable, rather than using the bundled Hpack.
466+
467+
```yaml
468+
with-hpack: /usr/local/bin/hpack
469+
```
470+
463471
### compiler-check
464472

465473
(Since 0.1.4)

src/Stack/Config.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ configFromConfigMonoid
283283
configExtraIncludeDirs = configMonoidExtraIncludeDirs
284284
configExtraLibDirs = configMonoidExtraLibDirs
285285
configOverrideGccPath = getFirst configMonoidOverrideGccPath
286-
286+
configOverrideHpack = maybe HpackBundled HpackCommand $ getFirst configMonoidOverrideHpack
287+
287288
-- Only place in the codebase where platform is hard-coded. In theory
288289
-- in the future, allow it to be configured.
289290
(Platform defArch defOS) = buildPlatform

src/Stack/Options/ConfigParser.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import qualified System.FilePath as FilePath
2020
-- | Command-line arguments parser for configuration.
2121
configOptsParser :: FilePath -> GlobalOptsContext -> Parser ConfigMonoid
2222
configOptsParser currentDir hide0 =
23-
(\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch ghcVariant ghcBuild jobs includes libs overrideGccPath skipGHCCheck skipMsys localBin modifyCodePage allowDifferentUser dumpLogs -> mempty
23+
(\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch ghcVariant ghcBuild jobs includes libs overrideGccPath overrideHpack skipGHCCheck skipMsys localBin modifyCodePage allowDifferentUser dumpLogs -> mempty
2424
{ configMonoidStackRoot = stackRoot
2525
, configMonoidWorkDir = workDir
2626
, configMonoidBuildOpts = buildOpts
@@ -36,6 +36,7 @@ configOptsParser currentDir hide0 =
3636
, configMonoidExtraIncludeDirs = includes
3737
, configMonoidExtraLibDirs = libs
3838
, configMonoidOverrideGccPath = overrideGccPath
39+
, configMonoidOverrideHpack = overrideHpack
3940
, configMonoidSkipMsys = skipMsys
4041
, configMonoidLocalBinPath = localBin
4142
, configMonoidModifyCodePage = modifyCodePage
@@ -103,6 +104,12 @@ configOptsParser currentDir hide0 =
103104
<> help "Use gcc found at PATH-TO-GCC"
104105
<> hide
105106
))
107+
<*> optionalFirst (strOption
108+
( long "with-hpack"
109+
<> metavar "HPACK"
110+
<> help "Use HPACK executable (overrides bundled Hpack)"
111+
<> hide
112+
))
106113
<*> firstBoolFlags
107114
"skip-ghc-check"
108115
"skipping the GHC version and architecture check"

src/Stack/Package.hs

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ import qualified System.Directory as D
9999
import System.FilePath (splitExtensions, replaceExtension)
100100
import qualified System.FilePath as FilePath
101101
import System.IO.Error
102+
import System.Process.Run (runCmd, Cmd(..))
102103

103104
data Ctx = Ctx { ctxFile :: !(Path Abs File)
104105
, ctxDir :: !(Path Abs Dir)
@@ -171,7 +172,7 @@ readPackageBS packageConfig loc bs =
171172
-- | Get 'GenericPackageDescription' and 'PackageDescription' reading info
172173
-- from given directory.
173174
readPackageDescriptionDir
174-
:: (MonadLogger m, MonadIO m, MonadThrow m, HasRunner env,
175+
:: (MonadLogger m, MonadIO m, MonadUnliftIO m, MonadThrow m, HasRunner env, HasConfig env,
175176
MonadReader env m)
176177
=> PackageConfig
177178
-> Path Abs Dir
@@ -1280,7 +1281,7 @@ logPossibilities dirs mn = do
12801281
-- generate a .cabal file from it.
12811282
findOrGenerateCabalFile
12821283
:: forall m env.
1283-
(MonadIO m, MonadLogger m, HasRunner env, MonadReader env m)
1284+
(MonadIO m, MonadUnliftIO m, MonadLogger m, HasRunner env, HasConfig env, MonadReader env m)
12841285
=> Path Abs Dir -- ^ package directory
12851286
-> m (Path Abs File)
12861287
findOrGenerateCabalFile pkgDir = do
@@ -1309,30 +1310,38 @@ findOrGenerateCabalFile pkgDir = do
13091310
where hasExtension fp x = FilePath.takeExtension fp == "." ++ x
13101311

13111312
-- | Generate .cabal file from package.yaml, if necessary.
1312-
hpack :: (MonadIO m, MonadLogger m, HasRunner env, MonadReader env m)
1313+
hpack :: (MonadIO m, MonadUnliftIO m, MonadLogger m, HasRunner env, HasConfig env, MonadReader env m)
13131314
=> Path Abs Dir -> m ()
13141315
hpack pkgDir = do
13151316
let hpackFile = pkgDir </> $(mkRelFile Hpack.packageConfig)
13161317
exists <- liftIO $ doesFileExist hpackFile
13171318
when exists $ do
13181319
prettyDebugL [flow "Running hpack on", display hpackFile]
1320+
1321+
config <- view configL
1322+
case configOverrideHpack config of
1323+
HpackBundled -> do
13191324
#if MIN_VERSION_hpack(0,18,0)
1320-
r <- liftIO $ Hpack.hpackResult (Just $ toFilePath pkgDir)
1325+
r <- liftIO $ Hpack.hpackResult (Just $ toFilePath pkgDir)
13211326
#else
1322-
r <- liftIO $ Hpack.hpackResult (toFilePath pkgDir)
1327+
r <- liftIO $ Hpack.hpackResult (toFilePath pkgDir)
13231328
#endif
1324-
forM_ (Hpack.resultWarnings r) prettyWarnS
1325-
let cabalFile = styleFile . fromString . Hpack.resultCabalFile $ r
1326-
case Hpack.resultStatus r of
1327-
Hpack.Generated -> prettyDebugL
1328-
[flow "hpack generated a modified version of", cabalFile]
1329-
Hpack.OutputUnchanged -> prettyDebugL
1330-
[flow "hpack output unchanged in", cabalFile]
1331-
Hpack.AlreadyGeneratedByNewerHpack -> prettyWarnL
1332-
[ cabalFile
1333-
, flow "was generated with a newer version of hpack,"
1334-
, flow "please upgrade and try again."
1335-
]
1329+
forM_ (Hpack.resultWarnings r) prettyWarnS
1330+
let cabalFile = styleFile . fromString . Hpack.resultCabalFile $ r
1331+
case Hpack.resultStatus r of
1332+
Hpack.Generated -> prettyDebugL
1333+
[flow "hpack generated a modified version of", cabalFile]
1334+
Hpack.OutputUnchanged -> prettyDebugL
1335+
[flow "hpack output unchanged in", cabalFile]
1336+
Hpack.AlreadyGeneratedByNewerHpack -> prettyWarnL
1337+
[ cabalFile
1338+
, flow "was generated with a newer version of hpack,"
1339+
, flow "please upgrade and try again."
1340+
]
1341+
HpackCommand command -> do
1342+
envOverride <- getMinimalEnvOverride
1343+
let cmd = Cmd (Just pkgDir) command envOverride []
1344+
runCmd cmd Nothing
13361345

13371346
-- | Path for the package's build log.
13381347
buildLogPath :: (MonadReader env m, HasBuildConfig env, MonadThrow m)

src/Stack/Solver.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ getResolverConstraints menv mcompilerVersion stackYaml sd = do
490490
-- file.
491491
-- Subdirectories can be included depending on the @recurse@ parameter.
492492
findCabalFiles
493-
:: (MonadIO m, MonadLogger m, HasRunner env, MonadReader env m)
493+
:: (MonadIO m, MonadUnliftIO m, MonadLogger m, HasRunner env, MonadReader env m, HasConfig env)
494494
=> Bool -> Path Abs Dir -> m [Path Abs File]
495495
findCabalFiles recurse dir = do
496496
liftIO (findFiles dir isHpack subdirFilter) >>= mapM_ (hpack . parent)
@@ -586,8 +586,8 @@ formatGroup :: [String] -> String
586586
formatGroup = concatMap (\path -> "- " <> path <> "\n")
587587

588588
reportMissingCabalFiles
589-
:: (MonadIO m, MonadThrow m, MonadLogger m,
590-
HasRunner env, MonadReader env m)
589+
:: (MonadIO m, MonadUnliftIO m, MonadThrow m, MonadLogger m,
590+
HasRunner env, MonadReader env m, HasConfig env)
591591
=> [Path Abs File] -- ^ Directories to scan
592592
-> Bool -- ^ Whether to scan sub-directories
593593
-> m ()

src/Stack/Types/Build.hs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ configureOptsNoDir econfig bco deps isLocal package = concat
565565
, map ("--extra-include-dirs=" ++) (Set.toList (configExtraIncludeDirs config))
566566
, map ("--extra-lib-dirs=" ++) (Set.toList (configExtraLibDirs config))
567567
, maybe [] (\customGcc -> ["--with-gcc=" ++ toFilePath customGcc]) (configOverrideGccPath config)
568+
, hpackOptions (configOverrideHpack config)
568569
, ["--ghcjs" | wc == Ghcjs]
569570
, ["--exact-configuration" | useExactConf]
570571
]
@@ -589,6 +590,9 @@ configureOptsNoDir econfig bco deps isLocal package = concat
589590
where
590591
toDepOption = if newerCabal then toDepOption1_22 else toDepOption1_18
591592

593+
hpackOptions HpackBundled = []
594+
hpackOptions (HpackCommand cmd) = ["--with-hpack=" ++ cmd]
595+
592596
toDepOption1_22 ident gid = concat
593597
[ "--dependency="
594598
, packageNameString $ packageIdentifierName ident

src/Stack/Types/Config.hs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ module Stack.Types.Config
5858
-- ** ApplyGhcOptions
5959
,ApplyGhcOptions(..)
6060
-- ** ConfigException
61+
,HpackExecutable(..)
6162
,ConfigException(..)
6263
-- ** WhichSolverCmd
6364
,WhichSolverCmd(..)
@@ -306,6 +307,8 @@ data Config =
306307
-- ^ How many concurrent jobs to run, defaults to number of capabilities
307308
,configOverrideGccPath :: !(Maybe (Path Abs File))
308309
-- ^ Optional gcc override path
310+
,configOverrideHpack :: !HpackExecutable
311+
-- ^ Use Hpack executable (overrides bundled Hpack)
309312
,configExtraIncludeDirs :: !(Set FilePath)
310313
-- ^ --extra-include-dirs arguments
311314
,configExtraLibDirs :: !(Set FilePath)
@@ -357,6 +360,11 @@ data Config =
357360
,configRunner :: !Runner
358361
}
359362

363+
data HpackExecutable
364+
= HpackBundled
365+
| HpackCommand String
366+
deriving (Show, Read, Eq, Ord)
367+
360368
-- | Which packages do ghc-options on the command line apply to?
361369
data ApplyGhcOptions = AGOTargets -- ^ all local targets
362370
| AGOLocals -- ^ all local packages, even non-targets
@@ -705,6 +713,8 @@ data ConfigMonoid =
705713
-- ^ See: 'configExtraLibDirs'
706714
, configMonoidOverrideGccPath :: !(First (Path Abs File))
707715
-- ^ Allow users to override the path to gcc
716+
,configMonoidOverrideHpack :: !(First FilePath)
717+
-- ^ Use Hpack executable (overrides bundled Hpack)
708718
,configMonoidConcurrentTests :: !(First Bool)
709719
-- ^ See: 'configConcurrentTests'
710720
,configMonoidLocalBinPath :: !(First FilePath)
@@ -789,6 +799,7 @@ parseConfigMonoidObject rootDir obj = do
789799
configMonoidExtraLibDirs <- fmap (Set.map (toFilePath rootDir FilePath.</>)) $
790800
obj ..:? configMonoidExtraLibDirsName ..!= Set.empty
791801
configMonoidOverrideGccPath <- First <$> obj ..:? configMonoidOverrideGccPathName
802+
configMonoidOverrideHpack <- First <$> obj ..:? configMonoidOverrideHpackName
792803
configMonoidConcurrentTests <- First <$> obj ..:? configMonoidConcurrentTestsName
793804
configMonoidLocalBinPath <- First <$> obj ..:? configMonoidLocalBinPathName
794805
configMonoidImageOpts <- jsonSubWarnings (obj ..:? configMonoidImageOptsName ..!= mempty)
@@ -914,6 +925,9 @@ configMonoidExtraLibDirsName = "extra-lib-dirs"
914925
configMonoidOverrideGccPathName :: Text
915926
configMonoidOverrideGccPathName = "with-gcc"
916927

928+
configMonoidOverrideHpackName :: Text
929+
configMonoidOverrideHpackName = "with-hpack"
930+
917931
configMonoidConcurrentTestsName :: Text
918932
configMonoidConcurrentTestsName = "concurrent-tests"
919933

src/test/Stack/ConfigSpec.hs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ buildOptsConfig =
4848
" reconfigure: true\n" ++
4949
" cabal-verbose: true\n"
5050

51+
hpackConfig :: String
52+
hpackConfig =
53+
"resolver: lts-2.10\n" ++
54+
"with-hpack: /usr/local/bin/hpack\n" ++
55+
"packages: ['.']\n"
56+
5157
stackDotYaml :: Path Rel File
5258
stackDotYaml = $(mkRelFile "stack.yaml")
5359

@@ -88,6 +94,18 @@ spec = beforeAll setup $ do
8894
-- TODO(danburton): more specific test for exception
8995
loadConfig' (const (return ())) `shouldThrow` anyException
9096

97+
it "parses config option with-hpack" $ inTempDir $ do
98+
writeFile (toFilePath stackDotYaml) hpackConfig
99+
loadConfig' $ \lc -> do
100+
let Config{..} = lcConfig lc
101+
configOverrideHpack `shouldBe` HpackCommand "/usr/local/bin/hpack"
102+
103+
it "parses config bundled hpack" $ inTempDir $ do
104+
writeFile (toFilePath stackDotYaml) sampleConfig
105+
loadConfig' $ \lc -> do
106+
let Config{..} = lcConfig lc
107+
configOverrideHpack `shouldBe` HpackBundled
108+
91109
it "parses build config options" $ inTempDir $ do
92110
writeFile (toFilePath stackDotYaml) buildOptsConfig
93111
loadConfig' $ \lc -> do

0 commit comments

Comments
 (0)