GHC issueshttps://gitlab.haskell.org/ghc/ghc/-/issues2021-11-29T09:15:21Zhttps://gitlab.haskell.org/ghc/ghc/-/issues/14092hs-boot unfolding visibility not consistent between --make and -c2021-11-29T09:15:21ZEdward Z. Yanghs-boot unfolding visibility not consistent between --make and -cduog's comment in https://phabricator.haskell.org/D3815#107812 pointed out an inconsistency between hs-boot handling in --make and -c that I have been dimly aware of for some time now.
Here is how to trigger the situation:
```
-- A.hs-...duog's comment in https://phabricator.haskell.org/D3815#107812 pointed out an inconsistency between hs-boot handling in --make and -c that I have been dimly aware of for some time now.
Here is how to trigger the situation:
```
-- A.hs-boot
module A where
f :: Int -> Int
-- B.hs
module B where
import {-# SOURCE #-} A
-- A.hs
module A where
import B
f :: Int -> Int
f x = x + 1
-- C.hs
module C where
import {-# SOURCE #-} A
g = f 2
```
When we run `ghc-head C.hs --make -O -ddump-simpl -fforce-recomp`, we see that f has been successfully inlined:
```
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
g :: Int
[GblId,
Caf=NoCafRefs,
Str=m,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]
g = GHC.Types.I# 3#
```
However, if we then one-shot compile C.hs, as in `ghc-head -c C.hs -O -ddump-simpl -fforce-recomp`, the unfolding is not seen:
```
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
C.g1 :: Int
[GblId,
Caf=NoCafRefs,
Str=m,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]
C.g1 = GHC.Types.I# 2#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
g :: Int
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False,
WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}]
g = f C.g1
```
The crux of the matter is that `--make` and `-c` have different rules about when to make use of the unfolded definition.
The `--make` rule is: compile the modules in some topological order. Any module that comes after `A.hs` sees the improved unfoldings. And as it turns out, the current topological order GHC picks is this:
```
[1 of 4] Compiling A[boot] ( A.hs-boot, A.o-boot )
[2 of 4] Compiling B ( B.hs, B.o )
[3 of 4] Compiling A ( A.hs, A.o )
[4 of 4] Compiling C ( C.hs, C.o )
```
The `-c` rule is more complicated. Every module records a list of transitive module dependencies, and whether or not a boot or non-boot was used. We load an hi-boot file if NONE of the modules we imported "saw" the full hi module, AND we only did direct SOURCE imports. If anyone has transitively imported A.hs, we load the hi file.
In the example above, C.hs ONLY imports A.hs-boot, so hs-boot is obliged to load A.hi-boot, and thus it does not see the unfolding.
The `-c` behavior is the correct behavior, because with the `--make` behavior it is easy to get into a situation where the build is dependent on the topological order chosen. Consider:
- `A.hs-boot`
- `B.hs-boot`
- `A.hs` imports `A.hs-boot`, `B.hs-boot`
- `B.hs` imports `A.hs-boot`, `B.hs-boot`
(Ignore the fact that in GHC today you can't actually directly import your hs-boot file; you can fix this by importing dummy modules.)
Now you can see that depending on the order you compile, e.g., A.hs-boot, B.hs-boot, A.hs, B.hs versus B.hs, A.hs, either A.hs or B.hs will be compiled with the unfoldings for its partner, but not vice versa. This doesn't sound good!
Unfortunately, fixing things properly in `--make` mode is quite troublesome. To understand why, we have to first remind ourself about loop retypechecking in make mode. Remember that GHC knot-ties all of the typechecker data structures together (https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/TyingTheKnot). This means that at the point we typecheck an hs-boot file, we are building an (immutable) graph on top of the impoverished, type signature only declarations from the hs-boot file. When we finish typechecking the loop closer, the only way to "update" all of the old references to the hs-boot file is to throw out the entire graph and rebuild it from scratch (the loop retypecheck!)
So let's think about the A.hs-boot B.hs A.hs C.hs case. At the point we're typechecking A.hs, we throw out the graph referencing A.hs-boot and rebuild it referencing A.hs so that everything gets knot-tied to A.hs. But THEN, C.hs comes around, and it's like, "Oy, I don't want the A.hs version of the graph, I want the A.hs-boot version of the graph." In `-c` mode, this is not a problem, since we have to rebuild the graph from scratch anyway, but in `--make` this is a big deal, since we have to throw everything out and rebuild it AGAIN.
One implementation strategy that doesn't involve mucking about with HPT retypechecking is to somehow make the typechecker aware of what unfoldings it should "see" and which it should not. The idea is that if it can ignore unfoldings that it doesn't have legitimate access to, that should be "just as good" as having typechecked against the hs-boot graph itself. But this sounds very tricky and difficult to get right... so here we are.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | duog |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"hs-boot unfolding visibility not consistent between --make and -c","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["hs-boot."],"differentials":[],"test_case":"","architecture":"","cc":["duog"],"type":"Bug","description":"duog's comment in https://phabricator.haskell.org/D3815#107812 pointed out an inconsistency between hs-boot handling in --make and -c that I have been dimly aware of for some time now.\r\n\r\nHere is how to trigger the situation:\r\n\r\n{{{\r\n-- A.hs-boot\r\nmodule A where\r\nf :: Int -> Int\r\n\r\n-- B.hs\r\nmodule B where\r\nimport {-# SOURCE #-} A\r\n\r\n-- A.hs\r\nmodule A where\r\nimport B\r\nf :: Int -> Int\r\nf x = x + 1\r\n\r\n-- C.hs\r\nmodule C where\r\nimport {-# SOURCE #-} A\r\ng = f 2\r\n}}}\r\n\r\nWhen we run `ghc-head C.hs --make -O -ddump-simpl -fforce-recomp`, we see that f has been successfully inlined:\r\n\r\n{{{\r\n-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}\r\ng :: Int\r\n[GblId,\r\n Caf=NoCafRefs,\r\n Str=m,\r\n Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,\r\n WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]\r\ng = GHC.Types.I# 3#\r\n}}}\r\n\r\nHowever, if we then one-shot compile C.hs, as in `ghc-head -c C.hs -O -ddump-simpl -fforce-recomp`, the unfolding is not seen:\r\n\r\n{{{\r\n-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}\r\nC.g1 :: Int\r\n[GblId,\r\n Caf=NoCafRefs,\r\n Str=m,\r\n Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,\r\n WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]\r\nC.g1 = GHC.Types.I# 2#\r\n\r\n-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}\r\ng :: Int\r\n[GblId,\r\n Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False,\r\n WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}]\r\ng = f C.g1\r\n}}}\r\n\r\nThe crux of the matter is that `--make` and `-c` have different rules about when to make use of the unfolded definition.\r\n\r\nThe `--make` rule is: compile the modules in some topological order. Any module that comes after `A.hs` sees the improved unfoldings. And as it turns out, the current topological order GHC picks is this:\r\n\r\n{{{\r\n[1 of 4] Compiling A[boot] ( A.hs-boot, A.o-boot )\r\n[2 of 4] Compiling B ( B.hs, B.o )\r\n[3 of 4] Compiling A ( A.hs, A.o )\r\n[4 of 4] Compiling C ( C.hs, C.o )\r\n}}}\r\n\r\nThe `-c` rule is more complicated. Every module records a list of transitive module dependencies, and whether or not a boot or non-boot was used. We load an hi-boot file if NONE of the modules we imported \"saw\" the full hi module, AND we only did direct SOURCE imports. If anyone has transitively imported A.hs, we load the hi file.\r\n\r\nIn the example above, C.hs ONLY imports A.hs-boot, so hs-boot is obliged to load A.hi-boot, and thus it does not see the unfolding.\r\n\r\nThe `-c` behavior is the correct behavior, because with the `--make` behavior it is easy to get into a situation where the build is dependent on the topological order chosen. Consider:\r\n\r\n* `A.hs-boot`\r\n* `B.hs-boot`\r\n* `A.hs` imports `A.hs-boot`, `B.hs-boot`\r\n* `B.hs` imports `A.hs-boot`, `B.hs-boot`\r\n\r\n(Ignore the fact that in GHC today you can't actually directly import your hs-boot file; you can fix this by importing dummy modules.)\r\n\r\nNow you can see that depending on the order you compile, e.g., A.hs-boot, B.hs-boot, A.hs, B.hs versus B.hs, A.hs, either A.hs or B.hs will be compiled with the unfoldings for its partner, but not vice versa. This doesn't sound good!\r\n\r\nUnfortunately, fixing things properly in `--make` mode is quite troublesome. To understand why, we have to first remind ourself about loop retypechecking in make mode. Remember that GHC knot-ties all of the typechecker data structures together (https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/TyingTheKnot). This means that at the point we typecheck an hs-boot file, we are building an (immutable) graph on top of the impoverished, type signature only declarations from the hs-boot file. When we finish typechecking the loop closer, the only way to \"update\" all of the old references to the hs-boot file is to throw out the entire graph and rebuild it from scratch (the loop retypecheck!)\r\n\r\nSo let's think about the A.hs-boot B.hs A.hs C.hs case. At the point we're typechecking A.hs, we throw out the graph referencing A.hs-boot and rebuild it referencing A.hs so that everything gets knot-tied to A.hs. But THEN, C.hs comes around, and it's like, \"Oy, I don't want the A.hs version of the graph, I want the A.hs-boot version of the graph.\" In `-c` mode, this is not a problem, since we have to rebuild the graph from scratch anyway, but in `--make` this is a big deal, since we have to throw everything out and rebuild it AGAIN.\r\n\r\nOne implementation strategy that doesn't involve mucking about with HPT retypechecking is to somehow make the typechecker aware of what unfoldings it should \"see\" and which it should not. The idea is that if it can ignore unfoldings that it doesn't have legitimate access to, that should be \"just as good\" as having typechecked against the hs-boot graph itself. But this sounds very tricky and difficult to get right... so here we are.","type_of_failure":"OtherFailure","blocking":[]} -->Divam NarulaDivam Narulahttps://gitlab.haskell.org/ghc/ghc/-/issues/14090Static pointers are not being registered under certain conditions2019-07-07T18:18:30ZmnislaihStatic pointers are not being registered under certain conditionsIt seems that only the static pointers in the module export list survive the Simplifier. This is a regression which doesn't seem to affect ghci/runghc only compiled code.
```
{-# LANGUAGE StaticPointers #-}
import GHC.StaticPtr
static...It seems that only the static pointers in the module export list survive the Simplifier. This is a regression which doesn't seem to affect ghci/runghc only compiled code.
```
{-# LANGUAGE StaticPointers #-}
import GHC.StaticPtr
staticHello :: StaticPtr String
staticHello = static "hello"
main = do
keys <- staticPtrKeys
if null keys
then error "static ptrs are not being registered"
else putStrLn "Everything is fine"
```
```
pepe:~/scratch$ stack --resolver ghc-8.2.1 script --optimize bug-spt.hs
Using resolver: ghc-8.2.1 specified on command line
bug-spt: static ptrs are not being registered
CallStack (from HasCallStack):
error, called at bug-spt.hs:11:10 in main:Main
pepe:~/scratch$ stack --resolver ghc-8.0.2 script --optimize bug-spt.hs
Using resolver: ghc-8.0.2 specified on command line
Everything is fine
```https://gitlab.haskell.org/ghc/ghc/-/issues/14074fdReadBuf001 fails non-deterministically on FreeBSD2019-07-07T18:18:35ZBen GamarifdReadBuf001 fails non-deterministically on FreeBSDWith this patch to `libraries/unix`,
```patch
diff --git a/tests/fdReadBuf001.hs b/tests/fdReadBuf001.hs
index 4c121a2..f987c94 100644
--- a/tests/fdReadBuf001.hs
+++ b/tests/fdReadBuf001.hs
@@ -21,7 +21,7 @@ main = do
r <- ...With this patch to `libraries/unix`,
```patch
diff --git a/tests/fdReadBuf001.hs b/tests/fdReadBuf001.hs
index 4c121a2..f987c94 100644
--- a/tests/fdReadBuf001.hs
+++ b/tests/fdReadBuf001.hs
@@ -21,7 +21,7 @@ main = do
r <- fdReadBuf rd p block
let (chunk,rest) = splitAt (fromIntegral r) text
chars <- peekArray (fromIntegral r) p
- when (chars /= chunk) $ error "mismatch"
+ when (chars /= chunk) $ error $ "mismatch: expected="++show chunk++", found="++show chars
when (null rest) $ exitWith ExitSuccess
loop rest
loop bytes
```
`fdReadBuf001` sometimes fails under the ghci way on FreeBSD 11.0 with something like,
```
=====> fdReadBuf001(ghci) 1 of 1 [0, 0, 0]
cd "../../libraries/unix/tests/fdReadBuf001.run" && "/home/ben/ghc-8.2.1/bin/ghc" fdReadBuf001.hs -dcore-lint -dcmm-lint -no-user-package-db -rtsopts -fno-warn-missed-specialisations -fshow-warning-groups -fdiagnostics-color=never -fno-diagnostics-show-caret -dno-debug-output --interactive -v0 -ignore-dot-ghci -fno-ghci-history +RTS -I0.1 -RTS -package unix< fdReadBuf001.genscript
Wrong exit code for fdReadBuf001(ghci) (expected 0 , actual 1 )
Stderr ( fdReadBuf001 ):
fdReadBuf001: mismatch: expected=[101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112], found=[168,149,144,14,8,0,0,0,58,1,0,0,0,0,0,0,32,228,123,10,8,0,0,0,200,149,144,14,8,0,0,0,0,150,144,14,8,0,0,0,96,127,174,10,8,0,0,0,33,152,144,14,8,0,0,0,0,150,144,14,8,0,0,0,42,0,0,0,0,0,0,0,96,127,174,10,8,0,0,0,162,21,74,13,8,0,0,0,56,150,144,14,8,0,0,0,96,127,174,10,8,0,0,0,10,152,144,14,8,0,0,0,56,150,144,14,8,0,0,0,32,228,123,10,8,0,0,0,200,149,144,14,8,0,0,0,112,150,144,14,8,0,0,0,112,209,123,10,8,0,0,0,138,150,144,14,8,0,0,0,88,150,144,14,8,0,0,0,96,127,174,10,8,0,0,0,249,150,144,14,8,0,0,0,48,187,247,9,8,0,0,0,129,223,208,10,8,0,0,0,96,127,174,10,8,0,0,0,9,151,144,14,8,0,0,0,16,46,250,9,8,0,0,0,184,150,144,14,8,0,0,0,224,227,123,10,8,0,0,0,111,0,0,0,0,0,0,0,8,246,255,9,8,0,0,0,111,0,0,0,0,0,0,0,224,0,194,9,8,0,0,0]
CallStack (from HasCallStack):
error, called at fdReadBuf001.hs:24:36 in main:Main
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"fdReadBuf001 fails non-deterministically on FreeBSD","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"With this patch to `libraries/unix`,\r\n{{{#!patch\r\ndiff --git a/tests/fdReadBuf001.hs b/tests/fdReadBuf001.hs\r\nindex 4c121a2..f987c94 100644\r\n--- a/tests/fdReadBuf001.hs\r\n+++ b/tests/fdReadBuf001.hs\r\n@@ -21,7 +21,7 @@ main = do\r\n r <- fdReadBuf rd p block\r\n let (chunk,rest) = splitAt (fromIntegral r) text\r\n chars <- peekArray (fromIntegral r) p\r\n- when (chars /= chunk) $ error \"mismatch\"\r\n+ when (chars /= chunk) $ error $ \"mismatch: expected=\"++show chunk++\", found=\"++show chars\r\n when (null rest) $ exitWith ExitSuccess\r\n loop rest\r\n loop bytes\r\n}}}\r\n\r\n`fdReadBuf001` sometimes fails under the ghci way on FreeBSD 11.0 with something like,\r\n{{{\r\n=====> fdReadBuf001(ghci) 1 of 1 [0, 0, 0]\r\ncd \"../../libraries/unix/tests/fdReadBuf001.run\" && \"/home/ben/ghc-8.2.1/bin/ghc\" fdReadBuf001.hs -dcore-lint -dcmm-lint -no-user-package-db -rtsopts -fno-warn-missed-specialisations -fshow-warning-groups -fdiagnostics-color=never -fno-diagnostics-show-caret -dno-debug-output --interactive -v0 -ignore-dot-ghci -fno-ghci-history +RTS -I0.1 -RTS -package unix< fdReadBuf001.genscript\r\nWrong exit code for fdReadBuf001(ghci) (expected 0 , actual 1 )\r\nStderr ( fdReadBuf001 ):\r\nfdReadBuf001: mismatch: expected=[101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112], found=[168,149,144,14,8,0,0,0,58,1,0,0,0,0,0,0,32,228,123,10,8,0,0,0,200,149,144,14,8,0,0,0,0,150,144,14,8,0,0,0,96,127,174,10,8,0,0,0,33,152,144,14,8,0,0,0,0,150,144,14,8,0,0,0,42,0,0,0,0,0,0,0,96,127,174,10,8,0,0,0,162,21,74,13,8,0,0,0,56,150,144,14,8,0,0,0,96,127,174,10,8,0,0,0,10,152,144,14,8,0,0,0,56,150,144,14,8,0,0,0,32,228,123,10,8,0,0,0,200,149,144,14,8,0,0,0,112,150,144,14,8,0,0,0,112,209,123,10,8,0,0,0,138,150,144,14,8,0,0,0,88,150,144,14,8,0,0,0,96,127,174,10,8,0,0,0,249,150,144,14,8,0,0,0,48,187,247,9,8,0,0,0,129,223,208,10,8,0,0,0,96,127,174,10,8,0,0,0,9,151,144,14,8,0,0,0,16,46,250,9,8,0,0,0,184,150,144,14,8,0,0,0,224,227,123,10,8,0,0,0,111,0,0,0,0,0,0,0,8,246,255,9,8,0,0,0,111,0,0,0,0,0,0,0,224,0,194,9,8,0,0,0]\r\nCallStack (from HasCallStack):\r\n error, called at fdReadBuf001.hs:24:36 in main:Main\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14073Testsuite should pass even with LANG=C2019-07-07T18:18:35ZBen GamariTestsuite should pass even with LANG=CIt seems that our testsuite has some sensitivity to the setting of the `LANG` environment variable. Namely the driver seems to encounter encoding issues in a few cases,
```
Framework failures:
ghci/scripts/T5975a.run T59...It seems that our testsuite has some sensitivity to the setting of the `LANG` environment variable. Namely the driver seems to encounter encoding issues in a few cases,
```
Framework failures:
ghci/scripts/T5975a.run T5975a [ghci] ('ascii' codec can't encode characters in position 41-42: ordinal not in range(128))
ghci/scripts/T5975b.run T5975b [ghci] ('ascii' codec can't encode characters in position 41-42: ordinal not in range(128))
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Test Suite |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Testsuite should pass even with LANG=C","status":"New","operating_system":"","component":"Test Suite","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"It seems that our testsuite has some sensitivity to the setting of the `LANG` environment variable. Namely the driver seems to encounter encoding issues in a few cases,\r\n{{{\r\n\r\nFramework failures:\r\n ghci/scripts/T5975a.run T5975a [ghci] ('ascii' codec can't encode characters in position 41-42: ordinal not in range(128))\r\n ghci/scripts/T5975b.run T5975b [ghci] ('ascii' codec can't encode characters in position 41-42: ordinal not in range(128))\r\n\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14068Loopification using join points2024-03-04T22:34:57ZJoachim Breitnermail@joachim-breitner.deLoopification using join pointsThis is the master ticket for doing **loopification in Core**. See also:
* `Note [Self-recursive tail calls]` in GHC.StgToCmm.Expr
* See wiki page: https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/loopification#new-idea-u...This is the master ticket for doing **loopification in Core**. See also:
* `Note [Self-recursive tail calls]` in GHC.StgToCmm.Expr
* See wiki page: https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/loopification#new-idea-use-join-points
* #22227 has several examples of the value of loopification in Core
* #13966
* #14287
* See https://gitlab.haskell.org/ghc/ghc/issues/14068#note_140494 for a wrinkle.
* See https://gitlab.haskell.org/ghc/ghc/issues/22227#note_457985 for another wrinkle
## The idea
The function
```
let f x y = case y of
A -> f x' y'
B -> e2
C -> e3
in g f
```
is not turned into a recursive join point, because the call to `f` is not in tail call position. But the recursive calls are, and these matter performance-wise! Hence, it would be beneficial to turn this into
```
let f x y = joinrec $j x y = case x y of
A -> $j x' y'
B -> e2
C -> e3
in $j x y
in g f
```
This has the additional effect that now `f` is no longer recursive and may get inlined.
The idea is described under "New idea: use join points" in [Commentary/Compiler/Loopification](commentary/compiler/loopification).
Some notes:
- We should to this both at top level and for nested definitions.
- We can remove the "loopification" code from the code generator when this is done.
- It came up in #13966, and might go well with #14067.
- It might work well with #13051, which Thomas Jakway is still thinking about.
- Should fix #14287 too.
- See also [ticket:14068\#comment:140494](https://gitlab.haskell.org//ghc/ghc/issues/14068#note_140494) of #14620, for a wrinkle.Joachim Breitnermail@joachim-breitner.deJoachim Breitnermail@joachim-breitner.dehttps://gitlab.haskell.org/ghc/ghc/-/issues/14067Static Argument Transformation for tail-recursive functions2022-10-17T12:40:37ZJoachim Breitnermail@joachim-breitner.deStatic Argument Transformation for tail-recursive functionsIn #13966 it was determined that having a variant of the Static Argument Transformation (StaticArgumentTransformation) pass that would specifically work on recursive join points, would be beneficial. This ticket tracks this task.
Consid...In #13966 it was determined that having a variant of the Static Argument Transformation (StaticArgumentTransformation) pass that would specifically work on recursive join points, would be beneficial. This ticket tracks this task.
Consider
```
joinrec $j x y = case y of
A -> $j x y'
B -> e2 x
C -> e3
in $j foo bar
```
Here the first argument to `$j` is "static"; that is, the same in every call. So we can transform like this
```
joinrec $j y = case y of
A -> $j y'
B -> e2 foo
C -> e3
in $j bar
```
Note that `x` isn't passed around in every iteration any more.https://gitlab.haskell.org/ghc/ghc/-/issues/14063Compiling with --backpack with undefined dependency results in "the 'impossib...2023-05-05T12:59:10ZrcookCompiling with --backpack with undefined dependency results in "the 'impossible' happened"Using GHC 8.2.1:
```
> ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.2.1
```
And compiling with `--backpack` as follows:
```
> ghc --backpack foo.bkp
[1 of 4] Processing foo-indef
[1 of 2] Compiling Str[si...Using GHC 8.2.1:
```
> ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.2.1
```
And compiling with `--backpack` as follows:
```
> ghc --backpack foo.bkp
[1 of 4] Processing foo-indef
[1 of 2] Compiling Str[sig] ( foo-indef\Str.hsig, nothing )
[2 of 2] Compiling Foo ( foo-indef\Foo.hs, nothing )
[2 of 4] Processing foo-string
Instantiating foo-string
[1 of 1] Compiling Str ( foo-string\Str.hs, foo-string\Str.o )
[3 of 4] Processing foo-int
Instantiating foo-int
[1 of 1] Compiling Str ( foo-int\Str.hs, foo-int\Str.o )
[4 of 4] Processing main
ghc.EXE: panic! (the 'impossible' happened)
(GHC version 8.2.1 for x86_64-unknown-mingw32):
no package name
CallStack (from HasCallStack):
error, called at compiler\backpack\DriverBkp.hs:573:32 in ghc:DriverBkp
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
make: *** [foo-indef/Foo.hi] Error 1
```
See attached `foo.bkp` file. While the Backpack file *is* invalid, in that the `main` unit mentions the `foo` dependency, which does not exist, this shouldn't lead to a GHC panic.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Compiling with --backpack with undefined dependency results in \"the 'impossible' happened\"","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":["Backpack"],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Using GHC 8.2.1:\r\n\r\n{{{\r\n> ghc --version\r\nThe Glorious Glasgow Haskell Compilation System, version 8.2.1\r\n}}}\r\n\r\nAnd compiling with `--backpack` as follows:\r\n\r\n{{{\r\n> ghc --backpack foo.bkp\r\n[1 of 4] Processing foo-indef\r\n [1 of 2] Compiling Str[sig] ( foo-indef\\Str.hsig, nothing )\r\n [2 of 2] Compiling Foo ( foo-indef\\Foo.hs, nothing )\r\n[2 of 4] Processing foo-string\r\n Instantiating foo-string\r\n [1 of 1] Compiling Str ( foo-string\\Str.hs, foo-string\\Str.o )\r\n[3 of 4] Processing foo-int\r\n Instantiating foo-int\r\n [1 of 1] Compiling Str ( foo-int\\Str.hs, foo-int\\Str.o )\r\n[4 of 4] Processing main\r\nghc.EXE: panic! (the 'impossible' happened)\r\n (GHC version 8.2.1 for x86_64-unknown-mingw32):\r\n no package name\r\nCallStack (from HasCallStack):\r\n error, called at compiler\\backpack\\DriverBkp.hs:573:32 in ghc:DriverBkp\r\n\r\nPlease report this as a GHC bug: http://www.haskell.org/ghc/reportabug\r\n\r\nmake: *** [foo-indef/Foo.hi] Error 1\r\n}}}\r\n\r\nSee attached `foo.bkp` file. While the Backpack file ''is'' invalid, in that the `main` unit mentions the `foo` dependency, which does not exist, this shouldn't lead to a GHC panic.\r\n","type_of_failure":"OtherFailure","blocking":[]} -->Edward Z. YangEdward Z. Yanghttps://gitlab.haskell.org/ghc/ghc/-/issues/14061reflection2019-07-07T18:18:39Zzaoqireflection```hs
{-# LANGUAGE KindSignatures, GADTs #-}
data Dyn :: * where
Dyn :: a -> Dyn
```
How to write the correct `instance Eq Dyn`, do not change `data Dyn`?
```hs
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
class GEq a...```hs
{-# LANGUAGE KindSignatures, GADTs #-}
data Dyn :: * where
Dyn :: a -> Dyn
```
How to write the correct `instance Eq Dyn`, do not change `data Dyn`?
```hs
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
class GEq a b where
geq :: a -> b -> Bool
instance {-# OVERLAPPABLE #-} (Eq a) => GEq a a where
geq = (==)
instance {-# OVERLAPPING #-} GEq a b where
geq _ _ = False
```
```hs
instance Eq Dyn where
Dyn a == Dyn b = geq a b
```
```
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Prelude> :load Dyn.hs
[1 of 1] Compiling Main ( Dyn.hs, interpreted )
Ok, modules loaded: Main.
*Main> Dyn () == Dyn ()
False
```
If Haskell supports reflections like Java,https://gitlab.haskell.org/ghc/ghc/-/issues/14057Upstream Alpine Linux distribution patches2019-07-07T18:18:40ZBen GamariUpstream Alpine Linux distribution patchesAlpine Linux has a variety of [patches](https://git.alpinelinux.org/cgit/aports/tree/community/ghc?h=3.6-stable) to allow GHC to build against the musl libc implementation. Let's get these upstream.
Here is my take on the patches:
- `0...Alpine Linux has a variety of [patches](https://git.alpinelinux.org/cgit/aports/tree/community/ghc?h=3.6-stable) to allow GHC to build against the musl libc implementation. Let's get these upstream.
Here is my take on the patches:
- `0000-alpine.patch`: This is a no-brainer. Merged as 9ae24bb615416b3e8d972d45ebe3dd281242d213.
- `0000-bootstrap.patch`: I really don't know about this one. The motivation is quite unclear. Needs discussion.
- `0001-rm-ghc-pwd.patch`: Already merged in 4c56ad36ee0d1f8b6f1b2bc0d8fff1c9acd1a389.
- `0002-Correct-issue-with-libffi-and-glibc.patch`: This is, unfortunately, a `libffi` fix, not a GHC fix. I'm not enthusiastic about patching libffi like this. However, `libffi`'s upstream is quite unresponsive and we are waiting for them to act on a number of issues, so perhaps we'll need to reconsider this. I've created #14056 to track this.
- `0003-do-not-use-SHELL.patch`: Looks reasonable to me. Merged as a10c2e6e9e9af3addbf91c0bb374257fb6c72553.
- `0004-reproducible-tmp-names.patch`: Seems plausible.
- `0005-buildpath-abi-stability.patch`: There's some discussion in #10424.
- `0006-fix-madvise.patch`: Merged in 6576bf83cdf4eac05eb88a24aa934a736c91e3da. See #12865
- `0007-build-hp2ps-twice.patch`, `0008-build-unlit-twice.patch`: Why?8.2.3https://gitlab.haskell.org/ghc/ghc/-/issues/14049relax -Wmissing-import-lists to allow one module with implicit imports when u...2020-02-21T13:12:39Zcdepillaboutrelax -Wmissing-import-lists to allow one module with implicit imports when using NoImplicitPreludeIt would be nice to modify the `-Wmissing-import-lists` warning flag to allow one module with implicit imports when using the `NoImplicitPrelude` pragma.
For example, imagine the following program:
```hs
{-# LANGUAGE NoImplicitPrelude ...It would be nice to modify the `-Wmissing-import-lists` warning flag to allow one module with implicit imports when using the `NoImplicitPrelude` pragma.
For example, imagine the following program:
```hs
{-# LANGUAGE NoImplicitPrelude #-}
module Main where
import MyCustomPrelude
import Control.Monad.Trans.Reader (Reader, runReader)
what :: Reader Int String -> String
what x = runReader x 3
main :: IO ()
main = print "hello"
```
If this program is compiled with the `-Wmissing-import-lists` flag, the following warning will be produced:
```
example.hs:5:1: warning: [-Wmissing-import-lists]
The module ‘MyCustomPrelude’ does not have an explicit import list
```
I think it would be nice if this warning did not appear.
Ideally, when using `NoImplicitPrelude` and `-Wmissing-import-lists` together, I would want one import per module to be permitted not to be explicit. This would make it possible to use an alternative Prelude and `-Wmissing-import-lists` at the same time.
Alternatively, a new warning flag could be created with the above behavior. Maybe it could be called something like `-Wmulti-implicit-imports` or `-Wmulti-open-imports`. I would appreciate feedback/suggestions for the name.
----
PureScript currently works like I have described above. By default the `Prelude` module is not imported (so you must explicitly import it), and the compiler will warn you if you have more than one implicit import. I really like this combination and it would be nice to be able to get the same thing in Haskell.
In case anyone is interested, [here](https://github.com/purescript/purescript/issues/1869) is the issue for PureScript where they talked about making this change.
----
If it seems like this is a good idea and other people are onboard, I'd be willing to implement it. I think it would be a relatively easy change, so it would be good for a first-time contributor.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"relax -Wmissing-import-lists to allow one module without implicit imports when using NoImplicitPrelude","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"It would be nice to modify the `-Wmissing-import-lists` warning flag to allow one module with implicit imports when using the `NoImplicitPrelude` pragma.\r\n\r\nFor example, imagine the following program:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE NoImplicitPrelude #-}\r\n\r\nmodule Main where\r\n\r\nimport MyCustomPrelude\r\n\r\nimport Control.Monad.Trans.Reader (Reader, runReader)\r\n\r\nwhat :: Reader Int String -> String\r\nwhat x = runReader x 3\r\n\r\nmain :: IO ()\r\nmain = print \"hello\"\r\n}}}\r\n\r\nIf this program is compiled with the `-Wmissing-import-lists` flag, the following warning will be produced:\r\n\r\n{{{\r\nexample.hs:5:1: warning: [-Wmissing-import-lists]\r\n The module ‘MyCustomPrelude’ does not have an explicit import list\r\n}}}\r\n\r\nI think it would be nice if this warning did not appear.\r\n\r\nIdeally, when using `NoImplicitPrelude` and `-Wmissing-import-lists` together, I would want one import per module to be permitted not to be explicit. This would make it possible to use an alternative Prelude and `-Wmissing-import-lists` at the same time.\r\n\r\nAlternatively, a new warning flag could be created with the above behavior. Maybe it could be called something like `-Wmulti-implicit-imports` or `-Wmulti-open-imports`. I would appreciate feedback/suggestions for the name.\r\n\r\n----\r\n\r\nPureScript currently works like I have described above. By default the `Prelude` module is not imported (so you must explicitly import it), and the compiler will warn you if you have more than one implicit import. I really like this combination and it would be nice to be able to get the same thing in Haskell.\r\n\r\nIn case anyone is interested, [https://github.com/purescript/purescript/issues/1869 here] is the issue for PureScript where they talked about making this change.\r\n\r\n----\r\n\r\nIf it seems like this is a good idea and other people are onboard, I'd be willing to implement it. I think it would be a relatively easy change, so it would be good for a first-time contributor.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14044ghc-8.2.1 installation fails on OpenBSD 6.02019-07-07T18:18:44Zromanzolotarevghc-8.2.1 installation fails on OpenBSD 6.0I have tried to install ghc-8.2.1 directly and via stack. Getting the same error:
```
ghc-cabal: can't load library 'libc.so.89.3'
```
ghc requires 'libc.so.89.3', while OpenBSD 6.0 has 'libc.so.88.0' by default.
```
# find / -name li...I have tried to install ghc-8.2.1 directly and via stack. Getting the same error:
```
ghc-cabal: can't load library 'libc.so.89.3'
```
ghc requires 'libc.so.89.3', while OpenBSD 6.0 has 'libc.so.88.0' by default.
```
# find / -name libc.so*
/usr/lib/libc.so.88.0
/usr/lib/libc.so.88.0.a
```
----
Full log
```
# /root/.cabal/bin/stack setup
Preparing to install GHC to an isolated location.
This will not interfere with any system-level installation.
Already downloaded.
Running /usr/local/bin/gmake install in directory /root/.stack/programs/x86_64-openbsd/ghc-8.2.1.temp/ghc-8.2.1/ exited with ExitFailure 2
/usr/local/bin/gmake --no-print-directory -f ghc.mk install BINDIST=YES NO_INCLUDE_DEPS=YES
"rm" -f utils/ghc-pkg/dist-install/build/Version.hs
echo "module Version where" >> utils/ghc-pkg/dist-install/build/Version.hs
echo "version, targetOS, targetARCH :: String" >> utils/ghc-pkg/dist-install/build/Version.hs
echo "version = \"8.2.1\"" >> utils/ghc-pkg/dist-install/build/Version.hs
echo "targetOS = \"openbsd\"" >> utils/ghc-pkg/dist-install/build/Version.hs
echo "targetARCH = \"x86_64\"" >> utils/ghc-pkg/dist-install/build/Version.hs
"rm" -f utils/ghc-pkg/dist/build/Version.hs
echo "module Version where" >> utils/ghc-pkg/dist/build/Version.hs
echo "version, targetOS, targetARCH :: String" >> utils/ghc-pkg/dist/build/Version.hs
echo "version = \"8.2.1\"" >> utils/ghc-pkg/dist/build/Version.hs
echo "targetOS = \"openbsd\"" >> utils/ghc-pkg/dist/build/Version.hs
echo "targetARCH = \"x86_64\"" >> utils/ghc-pkg/dist/build/Version.hs
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo 'exeprog="hp2ps"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
cat utils/hp2ps/hp2ps.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1"
echo 'exec "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1" --interactive "$@"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci"
ln -s ghci-8.2.1 "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/." && /usr/bin/install -c -m 644 includes/./*.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/./" && /usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts" && /usr/bin/install -c -m 644 includes/rts/*.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/" && /usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/prof" && /usr/bin/install -c -m 644 includes/rts/prof/*.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/prof/" && /usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/storage" && /usr/bin/install -c -m 644 includes/rts/storage/*.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/storage/" && /usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/stg" && /usr/bin/install -c -m 644 includes/stg/*.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/stg/" && true
/usr/bin/install -c -m 644 includes/ghcautoconf.h includes/ghcplatform.h includes/ghcversion.h includes/dist-derivedconstants/header/DerivedConstants.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo 'exeprog="haddock"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
cat utils/haddock/haddock.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/latex/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/haddock-util.js "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/haskell_icon.gif "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/minus.gif "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/plus.gif "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/xhaddock.css "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/hslogo-16.png "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/minus.gif "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/ocean.css "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/plus.gif "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/synopsis.png "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/solarized.css "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/highlight.js "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/"
/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/latex/haddock.sty "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/latex/"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock"
ln -s haddock-ghc-8.2.1 "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'exeprog="hsc2hs"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
echo 'HSC2HS_EXTRA="--cflag=-std=gnu99 --cflag=-fno-stack-protector --lflag=-Wl,-z,wxneeded"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
cat utils/hsc2hs/hsc2hs.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs"
/usr/bin/install -c -m 644 utils/hsc2hs/template-hsc.h "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo 'exeprog="ghc-pkg"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
cat utils/ghc-pkg/ghc-pkg.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg"
ln -s ghc-pkg-8.2.1 "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo 'exeprog="hpc"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
cat utils/hpc/hpc.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'exeprog="runghc"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
echo 'ghcprog="ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
cat utils/runghc/runghc.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runhaskell"
ln -s runghc "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runhaskell"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc"
ln -s runghc-8.2.1 "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
create () { touch "$1" && chmod 755 "$1" ; } && create "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo '#!/bin/sh' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'exedir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'exeprog="ghc-stage2"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'executablename="$exedir/$exeprog"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'datadir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'bindir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'topdir="/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
echo 'executablename="$exedir/ghc"' >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
cat ghc/ghc.wrapper >> "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
chmod +x "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1"
"rm" -f "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc"
ln -s ghc-8.2.1 "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/man"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/man/man1"
/usr/bin/install -c -m 644 docs/users_guide/build-man/ghc.1 "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/man/man1"
# driver/ghc-usage.txt driver/ghci-usage.txt includes/dist-derivedconstants/header/platformConstants settings = libraries to install
# "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1" = directory to install to
#
# The .dll case calls STRIP_CMD explicitly, instead of `install -s`, because
# on Win64, "install -s" calls a strip that doesn't understand 64bit binaries.
# For some reason, this means the DLLs end up non-executable, which means
# executables that use them just segfault.
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"
for i in driver/ghc-usage.txt driver/ghci-usage.txt includes/dist-derivedconstants/header/platformConstants settings; do case $i in *.a) /usr/bin/install -c -m 644 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"; true "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"/`basename $i` ;; *.dll) /usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1" ; strip "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"/`basename $i` ;; *.so) /usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1" ;; *.dylib) /usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1";; *) /usr/bin/install -c -m 644 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"; esac; done
gcc -E -undef -traditional -P -DINSTALLING -DLIB_DIR='"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"' -DINCLUDE_DIR='"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include"' -DFFI_INCLUDE_DIR=/usr/local/include -DFFI_LIB_DIR=/usr/local/lib '-DFFI_LIB=' -x c -Iincludes -Iincludes/dist -Iincludes/dist-derivedconstants/header -Iincludes/dist-ghcconstants/header rts/package.conf.in -o rts/dist/package.conf.install.raw
grep -v '^#pragma GCC' rts/dist/package.conf.install.raw | sed -e 's/""//g' -e 's/:[ ]*,/: /g' >rts/dist/package.conf.install
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"
for i in utils/unlit/dist/build/tmp/unlit utils/hp2ps/dist/build/tmp/hp2ps utils/hp2ps/dist/build/tmp/hp2ps utils/haddock/dist/build/tmp/haddock utils/haddock/dist/build/tmp/haddock utils/hsc2hs/dist-install/build/tmp/hsc2hs utils/hsc2hs/dist-install/build/tmp/hsc2hs utils/ghc-pkg/dist-install/build/tmp/ghc-pkg utils/ghc-pkg/dist-install/build/tmp/ghc-pkg utils/hpc/dist-install/build/tmp/hpc utils/hpc/dist-install/build/tmp/hpc utils/runghc/dist-install/build/tmp/runghc utils/runghc/dist-install/build/tmp/runghc ghc/stage2/build/tmp/ghc-stage2 ghc/stage2/build/tmp/ghc-stage2 iserv/stage2/build/tmp/ghc-iserv iserv/stage2_p/build/tmp/ghc-iserv-prof iserv/stage2_dyn/build/tmp/ghc-iserv-dyn; do \
/usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin"; \
done
"mv" "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin/ghc-stage2" "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin/ghc"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1"
"rm" -rf "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/package.conf.d"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/package.conf.d"
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts"
# rts/dist/build/libHSrts.a rts/dist/build/libHSrts_p.a rts/dist/build/libHSrts-ghc8.2.1.so rts/dist/build/libHSrts_l.a rts/dist/build/libHSrts_debug.a rts/dist/build/libHSrts_thr.a rts/dist/build/libHSrts_thr_debug.a rts/dist/build/libHSrts_thr_l.a rts/dist/build/libHSrts_thr_p.a rts/dist/build/libHSrts_debug-ghc8.2.1.so rts/dist/build/libHSrts_thr-ghc8.2.1.so rts/dist/build/libHSrts_thr_debug-ghc8.2.1.so rts/dist/build/libHSrts_l-ghc8.2.1.so rts/dist/build/libHSrts_thr_l-ghc8.2.1.so = libraries to install
# "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts" = directory to install to
#
# The .dll case calls STRIP_CMD explicitly, instead of `install -s`, because
# on Win64, "install -s" calls a strip that doesn't understand 64bit binaries.
# For some reason, this means the DLLs end up non-executable, which means
# executables that use them just segfault.
/usr/bin/install -c -m 755 -d "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts"
for i in rts/dist/build/libHSrts.a rts/dist/build/libHSrts_p.a rts/dist/build/libHSrts-ghc8.2.1.so rts/dist/build/libHSrts_l.a rts/dist/build/libHSrts_debug.a rts/dist/build/libHSrts_thr.a rts/dist/build/libHSrts_thr_debug.a rts/dist/build/libHSrts_thr_l.a rts/dist/build/libHSrts_thr_p.a rts/dist/build/libHSrts_debug-ghc8.2.1.so rts/dist/build/libHSrts_thr-ghc8.2.1.so rts/dist/build/libHSrts_thr_debug-ghc8.2.1.so rts/dist/build/libHSrts_l-ghc8.2.1.so rts/dist/build/libHSrts_thr_l-ghc8.2.1.so; do case $i in *.a) /usr/bin/install -c -m 644 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts"; true "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts"/`basename $i` ;; *.dll) /usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts" ; strip "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts"/`basename $i` ;; *.so) /usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts" ;; *.dylib) /usr/bin/install -c -m 755 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts";; *) /usr/bin/install -c -m 644 $i "/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts"; esac; done
"utils/ghc-cabal/dist-install/build/tmp/ghc-cabal-bindist" copy libraries/ghc-prim dist-install "strip" '' '/root/.stack/programs/x86_64-openbsd/ghc-8.2.1' '/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1' '/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/doc/ghc-8.2.1/html/libraries' 'v p dyn'
ghc-cabal: can't load library 'libc.so.89.3'
gmake[1]: *** [ghc.mk:991: install_packages] Error 4
gmake: *** [Makefile:51: install] Error 2
Error: Error encountered while installing GHC with
gmake install
run in /root/.stack/programs/x86_64-openbsd/ghc-8.2.1.temp/ghc-8.2.1/
The following directories may now contain files, but won't be used by stack:
- /root/.stack/programs/x86_64-openbsd/ghc-8.2.1.temp/
- /root/.stack/programs/x86_64-openbsd/ghc-8.2.1/
Installing GHC ...
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.2.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | None |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"ghc-8.2.1 installation fails on OpenBSD 6.0","status":"New","operating_system":"","component":"None","related":[],"milestone":"Research needed","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"I have tried to install ghc-8.2.1 directly and via stack. Getting the same error:\r\n\r\n{{{\r\nghc-cabal: can't load library 'libc.so.89.3'\r\n}}}\r\n\r\nghc requires 'libc.so.89.3', while OpenBSD 6.0 has 'libc.so.88.0' by default.\r\n\r\n{{{\r\n# find / -name libc.so*\r\n/usr/lib/libc.so.88.0\r\n/usr/lib/libc.so.88.0.a\r\n}}}\r\n\r\n\r\n----\r\n\r\nFull log\r\n\r\n{{{\r\n# /root/.cabal/bin/stack setup\r\nPreparing to install GHC to an isolated location.\r\nThis will not interfere with any system-level installation.\r\nAlready downloaded.\r\nRunning /usr/local/bin/gmake install in directory /root/.stack/programs/x86_64-openbsd/ghc-8.2.1.temp/ghc-8.2.1/ exited with ExitFailure 2\r\n\r\n/usr/local/bin/gmake --no-print-directory -f ghc.mk install BINDIST=YES NO_INCLUDE_DEPS=YES\r\n\"rm\" -f utils/ghc-pkg/dist-install/build/Version.hs\r\necho \"module Version where\" >> utils/ghc-pkg/dist-install/build/Version.hs\r\necho \"version, targetOS, targetARCH :: String\" >> utils/ghc-pkg/dist-install/build/Version.hs\r\necho \"version = \\\"8.2.1\\\"\" >> utils/ghc-pkg/dist-install/build/Version.hs\r\necho \"targetOS = \\\"openbsd\\\"\" >> utils/ghc-pkg/dist-install/build/Version.hs\r\necho \"targetARCH = \\\"x86_64\\\"\" >> utils/ghc-pkg/dist-install/build/Version.hs\r\n\"rm\" -f utils/ghc-pkg/dist/build/Version.hs\r\necho \"module Version where\" >> utils/ghc-pkg/dist/build/Version.hs\r\necho \"version, targetOS, targetARCH :: String\" >> utils/ghc-pkg/dist/build/Version.hs\r\necho \"version = \\\"8.2.1\\\"\" >> utils/ghc-pkg/dist/build/Version.hs\r\necho \"targetOS = \\\"openbsd\\\"\" >> utils/ghc-pkg/dist/build/Version.hs\r\necho \"targetARCH = \\\"x86_64\\\"\" >> utils/ghc-pkg/dist/build/Version.hs\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho 'exeprog=\"hp2ps\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\ncat utils/hp2ps/hp2ps.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hp2ps\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1\"\r\necho 'exec \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\" --interactive \"$@\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci-8.2.1\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci\"\r\nln -s ghci-8.2.1 \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghci\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/.\" && /usr/bin/install -c -m 644 includes/./*.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/./\" && /usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts\" && /usr/bin/install -c -m 644 includes/rts/*.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/\" && /usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/prof\" && /usr/bin/install -c -m 644 includes/rts/prof/*.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/prof/\" && /usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/storage\" && /usr/bin/install -c -m 644 includes/rts/storage/*.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/rts/storage/\" && /usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/stg\" && /usr/bin/install -c -m 644 includes/stg/*.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/stg/\" && true\r\n/usr/bin/install -c -m 644 includes/ghcautoconf.h includes/ghcplatform.h includes/ghcversion.h includes/dist-derivedconstants/header/DerivedConstants.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include/\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho 'exeprog=\"haddock\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\ncat utils/haddock/haddock.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock-ghc-8.2.1\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/latex/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/haddock-util.js \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/haskell_icon.gif \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/minus.gif \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/plus.gif \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Classic.theme/xhaddock.css \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Classic.theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/hslogo-16.png \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/minus.gif \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/ocean.css \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/plus.gif \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/Ocean.std-theme/synopsis.png \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/Ocean.std-theme/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/solarized.css \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/html/highlight.js \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/html/\"\r\n/usr/bin/install -c -m 644 utils/haddock/haddock-api/resources/latex/haddock.sty \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/latex/\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock\"\r\nln -s haddock-ghc-8.2.1 \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/haddock\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'exeprog=\"hsc2hs\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\necho 'HSC2HS_EXTRA=\"--cflag=-std=gnu99 --cflag=-fno-stack-protector --lflag=-Wl,-z,wxneeded\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\ncat utils/hsc2hs/hsc2hs.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hsc2hs\"\r\n/usr/bin/install -c -m 644 utils/hsc2hs/template-hsc.h \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho 'exeprog=\"ghc-pkg\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\ncat utils/ghc-pkg/ghc-pkg.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg-8.2.1\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg\"\r\nln -s ghc-pkg-8.2.1 \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-pkg\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho 'exeprog=\"hpc\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\ncat utils/hpc/hpc.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/hpc\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'exeprog=\"runghc\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\necho 'ghcprog=\"ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\ncat utils/runghc/runghc.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc-8.2.1\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runhaskell\"\r\nln -s runghc \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runhaskell\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc\"\r\nln -s runghc-8.2.1 \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/runghc\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\ncreate () { touch \"$1\" && chmod 755 \"$1\" ; } && create \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho '#!/bin/sh' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'exedir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'exeprog=\"ghc-stage2\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'executablename=\"$exedir/$exeprog\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'datadir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'bindir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'topdir=\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\necho 'executablename=\"$exedir/ghc\"' >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\ncat ghc/ghc.wrapper >> \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\nchmod +x \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc-8.2.1\"\r\n\"rm\" -f \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc\"\r\nln -s ghc-8.2.1 \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/bin/ghc\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/man\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/man/man1\"\r\n/usr/bin/install -c -m 644 docs/users_guide/build-man/ghc.1 \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/man/man1\"\r\n# driver/ghc-usage.txt driver/ghci-usage.txt includes/dist-derivedconstants/header/platformConstants settings = libraries to install\r\n# \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\" = directory to install to\r\n#\r\n# The .dll case calls STRIP_CMD explicitly, instead of `install -s`, because\r\n# on Win64, \"install -s\" calls a strip that doesn't understand 64bit binaries.\r\n# For some reason, this means the DLLs end up non-executable, which means\r\n# executables that use them just segfault.\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"\r\nfor i in driver/ghc-usage.txt driver/ghci-usage.txt includes/dist-derivedconstants/header/platformConstants settings; do case $i in *.a) /usr/bin/install -c -m 644 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"; true \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"/`basename $i` ;; *.dll) /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\" ; strip \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"/`basename $i` ;; *.so) /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\" ;; *.dylib) /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\";; *) /usr/bin/install -c -m 644 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"; esac; done\r\ngcc -E -undef -traditional -P -DINSTALLING -DLIB_DIR='\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"' -DINCLUDE_DIR='\"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/include\"' -DFFI_INCLUDE_DIR=/usr/local/include -DFFI_LIB_DIR=/usr/local/lib '-DFFI_LIB=' -x c -Iincludes -Iincludes/dist -Iincludes/dist-derivedconstants/header -Iincludes/dist-ghcconstants/header rts/package.conf.in -o rts/dist/package.conf.install.raw\r\ngrep -v '^#pragma GCC' rts/dist/package.conf.install.raw | sed -e 's/\"\"//g' -e 's/:[ ]*,/: /g' >rts/dist/package.conf.install\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"\r\nfor i in utils/unlit/dist/build/tmp/unlit utils/hp2ps/dist/build/tmp/hp2ps utils/hp2ps/dist/build/tmp/hp2ps utils/haddock/dist/build/tmp/haddock utils/haddock/dist/build/tmp/haddock utils/hsc2hs/dist-install/build/tmp/hsc2hs utils/hsc2hs/dist-install/build/tmp/hsc2hs utils/ghc-pkg/dist-install/build/tmp/ghc-pkg utils/ghc-pkg/dist-install/build/tmp/ghc-pkg utils/hpc/dist-install/build/tmp/hpc utils/hpc/dist-install/build/tmp/hpc utils/runghc/dist-install/build/tmp/runghc utils/runghc/dist-install/build/tmp/runghc ghc/stage2/build/tmp/ghc-stage2 ghc/stage2/build/tmp/ghc-stage2 iserv/stage2/build/tmp/ghc-iserv iserv/stage2_p/build/tmp/ghc-iserv-prof iserv/stage2_dyn/build/tmp/ghc-iserv-dyn; do \\\r\n /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin\"; \\\r\ndone\r\n\"mv\" \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin/ghc-stage2\" \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/bin/ghc\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1\"\r\n\"rm\" -rf \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/package.conf.d\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/package.conf.d\"\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\"\r\n# rts/dist/build/libHSrts.a rts/dist/build/libHSrts_p.a rts/dist/build/libHSrts-ghc8.2.1.so rts/dist/build/libHSrts_l.a rts/dist/build/libHSrts_debug.a rts/dist/build/libHSrts_thr.a rts/dist/build/libHSrts_thr_debug.a rts/dist/build/libHSrts_thr_l.a rts/dist/build/libHSrts_thr_p.a rts/dist/build/libHSrts_debug-ghc8.2.1.so rts/dist/build/libHSrts_thr-ghc8.2.1.so rts/dist/build/libHSrts_thr_debug-ghc8.2.1.so rts/dist/build/libHSrts_l-ghc8.2.1.so rts/dist/build/libHSrts_thr_l-ghc8.2.1.so = libraries to install\r\n# \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\" = directory to install to\r\n#\r\n# The .dll case calls STRIP_CMD explicitly, instead of `install -s`, because\r\n# on Win64, \"install -s\" calls a strip that doesn't understand 64bit binaries.\r\n# For some reason, this means the DLLs end up non-executable, which means\r\n# executables that use them just segfault.\r\n/usr/bin/install -c -m 755 -d \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\"\r\nfor i in rts/dist/build/libHSrts.a rts/dist/build/libHSrts_p.a rts/dist/build/libHSrts-ghc8.2.1.so rts/dist/build/libHSrts_l.a rts/dist/build/libHSrts_debug.a rts/dist/build/libHSrts_thr.a rts/dist/build/libHSrts_thr_debug.a rts/dist/build/libHSrts_thr_l.a rts/dist/build/libHSrts_thr_p.a rts/dist/build/libHSrts_debug-ghc8.2.1.so rts/dist/build/libHSrts_thr-ghc8.2.1.so rts/dist/build/libHSrts_thr_debug-ghc8.2.1.so rts/dist/build/libHSrts_l-ghc8.2.1.so rts/dist/build/libHSrts_thr_l-ghc8.2.1.so; do case $i in *.a) /usr/bin/install -c -m 644 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\"; true \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\"/`basename $i` ;; *.dll) /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\" ; strip \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\"/`basename $i` ;; *.so) /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\" ;; *.dylib) /usr/bin/install -c -m 755 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\";; *) /usr/bin/install -c -m 644 $i \"/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1/rts\"; esac; done\r\n\"utils/ghc-cabal/dist-install/build/tmp/ghc-cabal-bindist\" copy libraries/ghc-prim dist-install \"strip\" '' '/root/.stack/programs/x86_64-openbsd/ghc-8.2.1' '/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/lib/ghc-8.2.1' '/root/.stack/programs/x86_64-openbsd/ghc-8.2.1/share/doc/ghc-8.2.1/html/libraries' 'v p dyn'\r\n\r\nghc-cabal: can't load library 'libc.so.89.3'\r\ngmake[1]: *** [ghc.mk:991: install_packages] Error 4\r\ngmake: *** [Makefile:51: install] Error 2\r\n\r\n\r\nError: Error encountered while installing GHC with\r\n gmake install\r\n run in /root/.stack/programs/x86_64-openbsd/ghc-8.2.1.temp/ghc-8.2.1/\r\n\r\nThe following directories may now contain files, but won't be used by stack:\r\n - /root/.stack/programs/x86_64-openbsd/ghc-8.2.1.temp/\r\n - /root/.stack/programs/x86_64-openbsd/ghc-8.2.1/\r\n\r\nInstalling GHC ...\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->Research neededhttps://gitlab.haskell.org/ghc/ghc/-/issues/14039Add ability to install libraries bundled with ghc into separate prefixes2019-07-07T18:18:45ZShea Levyshea@shealevy.comAdd ability to install libraries bundled with ghc into separate prefixesCurrently, if I build an executable dynamically linked to 'base' and 'rts' with nix, I am forced to bring the ghc binary and, say, 'hoopl' along at runtime because these are all installed into the same prefix. Having options to indpenden...Currently, if I build an executable dynamically linked to 'base' and 'rts' with nix, I am forced to bring the ghc binary and, say, 'hoopl' along at runtime because these are all installed into the same prefix. Having options to indpendently specify output prefixes for each of the libraries would allow us to significantly decrease closure sizes.
Ben Gamari suggests this may be doable in the new Hadrian build.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Build System |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Add ability to install libraries bundled with ghc into separate prefixes","status":"New","operating_system":"","component":"Build System","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"Currently, if I build an executable dynamically linked to 'base' and 'rts' with nix, I am forced to bring the ghc binary and, say, 'hoopl' along at runtime because these are all installed into the same prefix. Having options to indpendently specify output prefixes for each of the libraries would allow us to significantly decrease closure sizes.\r\n\r\nBen Gamari suggests this may be doable in the new Hadrian build.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14035Weird performance results.2019-07-07T18:18:46Zdanilo2Weird performance results.Hi! I was recently testing performance of a critical code in a product we are shipping and I'm getting really weird results.
- \*The code is compiled with `-XStrict` enabled globally. The full source code for this ticket is attached, wh...Hi! I was recently testing performance of a critical code in a product we are shipping and I'm getting really weird results.
- \*The code is compiled with `-XStrict` enabled globally. The full source code for this ticket is attached, while the exposed code below uses `...` to hide some non-important implementations.\*\*
To get desired results, we use following GHC flags: `-O2 -funfolding-use-threshold=10000`.
Let's consider the following program. It is just a pseudo-parser implementation. It consumes 'a' chars in a loop and fails on empty input in the end:
```hs
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-- | WARNING: -XStrict enabled in this file !!!
-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
module Main where
imports ... (full source attached to this ticket)
------------------------
-- === Primitives === --
------------------------
-- === Strict Either === --
data Either e a = Left e | Right a deriving (Eq, Generic, Ord, Read, Show, Functor)
newtype EitherT e m a = EitherT { runEitherT :: m (Either e a) }
instance Monad m => Functor (EitherT e m) where ...
instance Monad m => Applicative (EitherT e m) where ...
instance Monad m => Monad (EitherT e m) where ...
-- === Strict Bool === --
data XBool = XTrue | XFalse deriving (Show, Generic)
(|||) :: XBool -> XBool -> XBool
(|||) !a !b = case a of
XTrue -> a
XFalse -> b
{-# INLINE (|||) #-}
-- === Strict Tuple === --
data T a b = T !a !b deriving (Generic, Show, Functor)
------------------------
-- === FailParser === --
------------------------
-- === Definition === --
-- | It is just like EitherT, but also contains progress indicator - a field of type XBool
-- which tells us if we've already parsed a char or not yet. In this snippet code however,
-- it does not do anything valuable - it just stores the value.
newtype FailParser m a = FailParser { fromFailParser :: EitherT () m (T XBool a) } deriving (Functor)
instance Monad m => Applicative (FailParser m) where
pure = undefined
(<*>) = undefined
instance Monad m => Monad (FailParser m) where
return a = FailParser $ return $ (T XFalse a) ; {-# INLINE return #-}
FailParser ma >>= f = FailParser $ do
T !b !a <- ma
T !b' !a' <- fromFailParser $ f a
return $ T (b ||| b') a'
{-# INLINE (>>=) #-}
_ >> _ = undefined ; {-# INLINE (>>) #-}
-- === Running === --
failParser :: m (Either () (T XBool a)) -> FailParser m a
failParser a = FailParser $ EitherT a ; {-# INLINE failParser #-}
runFailParser :: forall m a. FailParser m a -> m (Either () (T XBool a))
runFailParser f = runEitherT $ fromFailParser f ; {-# INLINE runFailParser #-}
-- === MonadFailedParser === --
-- | Behaves just like "left" - lifts until it hits MonadFailedParser
class Monad m => MonadFailedParser m where
failed :: m a
instance {-# OVERLAPPABLE #-} (MonadFailedParser m, MonadTrans t, Monad (t m))
=> MonadFailedParser (t m) where
failed = lift failed ; {-# INLINE failed #-}
instance Monad m => MonadFailedParser (FailParser m) where
failed = failParser $ return $ Left () ; {-# INLINE failed #-}
-----------------------
-- === Main loop === --
-----------------------
parserLoop :: StateT Text (FailParser Identity) Bool
parserLoop = parserStep >> parserLoop
parserStep :: StateT Text (FailParser Identity) Char
parserStep = get >>= \s -> case Text.uncons s of
Just (!t, !s') -> if t == 'a' then put s' >> return t else failed
Nothing -> failed
{-# INLINE parserStep #-}
-- === Criterion === --
instance NFData XBool
instance (NFData l, NFData r) => NFData (Either l r)
instance (NFData a, NFData b) => NFData (T a b)
genText :: Int -> Text
genText i = fromString $ replicate i 'a' ; {-# INLINE genText #-}
a_parsing_main :: IO ()
a_parsing_main = do
defaultMain
[ env (return $ genText $ 10^6) $ bench "a*" . nf (runIdentity . runFailParser . evalStateT parserLoop)
]
main = a_parsing_main
```
The most important part is the `bind` implementation of `FailParser`:
```hs
FailParser ma >>= f = FailParser $ do
T b a <- ma
T b' a' <- fromFailParser $ f a
return $ T (b ||| b') a'
```
There are several performance related observations and problems:
1. \*\*INFO:\*\* Everything is compiled with `-XStrict` and every field in this code is fully evaluated, in particular `b` and `b'` are fully evaluated, strict values of type `XBool`.
1. \*\*INFO:\*\* Neither `b` nor `b'` are used anywhere else in the code. They are just fields in `FailParser` which should be used to store information if we did consume a letter or we did not.
1. \*\*PROBLEM:\*\* When provided with `10^6` characters this code works in 1ms. If we replace `(b ||| b')` with `(b' ||| b)` or with `(b')` the time do NOT change. However, if we replace it with `(b)`, we've got \*\*15 times\*\* slowdown. Moreover, the resulting core is changed drastically in some places.
1. \*\*PROBLEM:\*\* Another interesting observation is that the value of `XBool` is created only in one place in the code, namely in: `FailParser`'s `Monad` implementation, in `return` function: `return a = FailParser $ return $ (T XFalse a) ; {-# INLINE return #-}`. We never change the XFalse, so this is the only value that could appear in this code. If we change it to `XTrue` in this implementation however, we again get \*\*15 times\*\* slowdown.
1. \*\*INFO:\*\* The order of `case` expressions in definition of `(|||)` or the order of constructor defintions of any datatype does not affect the above results.https://gitlab.haskell.org/ghc/ghc/-/issues/14032Can't splice TH quote with infix declaration for name in two different namesp...2024-02-21T10:01:03ZRyan ScottCan't splice TH quote with infix declaration for name in two different namespacesSpun off from #13799 (and #13054\##14032). This code compiles:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
infix 5 :*:
data a :*: b = a :*: b
```
But this code does not:
```hs
{-# LANGUAGE TemplateHaskell #-...Spun off from #13799 (and #13054\##14032). This code compiles:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
infix 5 :*:
data a :*: b = a :*: b
```
But this code does not:
```hs
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
$([d| infix 5 :*:
data a :*: b = a :*: b
|])
```
```
$ /opt/ghc/8.2.1/bin/ghc -ddump-splices Bug.hs
[1 of 1] Compiling Main ( Bug.hs, Bug.o )
Bug.hs:(4,3)-(6,6): Splicing declarations
[d| infix 5 :*:_anM, :*:_anL
data a_anN :*:_anL b_anO = a_anN :*:_anM b_anO |]
======>
infix 5 :*:_a3IL
infix 5 :*:_a3IK
data (:*:_a3IK) a_a3IM b_a3IN = a_a3IM :*:_a3IL b_a3IN
Bug.hs:4:3: error:
Multiple fixity declarations for ‘:*:_a3IL’
also at Bug.hs:(4,3)-(6,6)
|
4 | $([d| infix 5 :*:
| ^^^^^^^^^^^^^^^...
```
Inspecting the `-ddump-splices` output reveals why: when `infix 5 :*:` is renamed, because `:*:` refers to two different names in both the value and type namespaces, it actually gets renamed to `infix 5 :*:_anM, :*:_anL`, where `:*:_anM` and `:*:_anL` are the same name with different uniques.
Normally, this isn't a problem, since feeding `infix 5 :*:_anM, :*:_anL` to the typechecker works fine. However, when it's spliced in via Template Haskell, it gets fed back into the renamer, where it believes that `:*:_anM` and `:*:_anL` are duplicate names, causing the error.
Really, this is just a symptom of the fact that infix declarations are insufficiently powerful to encode information for identical names in different namespaces. But until GHC gains this ability, we need to find some workaround for this problem. My hunch is that we'll need to give GHC the power to recognize these sorts of duplicate fixity declarations in `Convert` and only emit one actual fixity declaration per set of duplicates. (Disclaimer: I haven't worked out all the fiddly details yet.)
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Can't splice TH quote with infix declaration for name in two different namespaces","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Spun off from #13799 (and https://ghc.haskell.org/trac/ghc/ticket/13054#comment:2). This code compiles:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE TypeOperators #-}\r\n\r\ninfix 5 :*:\r\ndata a :*: b = a :*: b\r\n}}}\r\n\r\nBut this code does not:\r\n\r\n{{{#!hs\r\n{-# LANGUAGE TemplateHaskell #-}\r\n{-# LANGUAGE TypeOperators #-}\r\n\r\n$([d| infix 5 :*:\r\n data a :*: b = a :*: b\r\n |])\r\n}}}\r\n{{{\r\n$ /opt/ghc/8.2.1/bin/ghc -ddump-splices Bug.hs\r\n[1 of 1] Compiling Main ( Bug.hs, Bug.o )\r\nBug.hs:(4,3)-(6,6): Splicing declarations\r\n [d| infix 5 :*:_anM, :*:_anL\r\n \r\n data a_anN :*:_anL b_anO = a_anN :*:_anM b_anO |]\r\n ======>\r\n infix 5 :*:_a3IL\r\n infix 5 :*:_a3IK\r\n data (:*:_a3IK) a_a3IM b_a3IN = a_a3IM :*:_a3IL b_a3IN\r\n\r\nBug.hs:4:3: error:\r\n Multiple fixity declarations for ‘:*:_a3IL’\r\n also at Bug.hs:(4,3)-(6,6)\r\n |\r\n4 | $([d| infix 5 :*:\r\n | ^^^^^^^^^^^^^^^...\r\n}}}\r\n\r\nInspecting the `-ddump-splices` output reveals why: when `infix 5 :*:` is renamed, because `:*:` refers to two different names in both the value and type namespaces, it actually gets renamed to `infix 5 :*:_anM, :*:_anL`, where `:*:_anM` and `:*:_anL` are the same name with different uniques.\r\n\r\nNormally, this isn't a problem, since feeding `infix 5 :*:_anM, :*:_anL` to the typechecker works fine. However, when it's spliced in via Template Haskell, it gets fed back into the renamer, where it believes that `:*:_anM` and `:*:_anL` are duplicate names, causing the error.\r\n\r\nReally, this is just a symptom of the fact that infix declarations are insufficiently powerful to encode information for identical names in different namespaces. But until GHC gains this ability, we need to find some workaround for this problem. My hunch is that we'll need to give GHC the power to recognize these sorts of duplicate fixity declarations in `Convert` and only emit one actual fixity declaration per set of duplicates. (Disclaimer: I haven't worked out all the fiddly details yet.)","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14031Linker paths carry substantial N*M overhead when many libaries are used2019-07-07T18:18:48ZNiklas Hambüchenmail@nh2.meLinker paths carry substantial N*M overhead when many libaries are used- \*"The linker search path problem"\*\*
It's common these days to have 400 (transitive) Hackage dependencies (even my hobby projects have that many).
When linking, statically or dynamically, GHC passes `-L /path/to/foo/dir` and `-L HS...- \*"The linker search path problem"\*\*
It's common these days to have 400 (transitive) Hackage dependencies (even my hobby projects have that many).
When linking, statically or dynamically, GHC passes `-L /path/to/foo/dir` and `-L HSfoo...` to the linker for each Haskell package `foo`.
That results in `N` many linker search paths (`-L`) and `M` many library names. That will translate in `N * M` many `stat()` syscalls (file existence checks) in the linker to check where each file is.
For 400 package dependencies, that translates to 160k `stat()` syscalls. On my machine (on SSD and hot file system cache in RAM), that takes `0.7 seconds` (measured with `strace -c -w`).
That is a substantial overhead for linking (for example, the executable with 400 dependencies with which I found this problem can be linked with `ld.gold` in just 1.5 seconds).
If there is tooling in between GHC and the linker that also parses linker flags and checks for file existence (for example Nix's `cc-wrapper` and `ld-wrapper` scripts, or other instrumentation or build system tooling, which are often not written in compiled languages and thus [much slower](https://github.com/NixOS/nixpkgs/issues/27609) at stat()ing than the linker is), then the problem can be easily blown up another 10x.
As a result, you may be waiting a lot longer for your link to finish than necessary.
For static linking, this could be resolved by passing the archive files (`libHSfoo....a`) directly to the linker instead of the `-L`/`-l` combination.
For this we would need to check that passing files directly really have the same semantics as `-L` and `-l`, but the man pages suggest so (and I'll check it with the binutils authors).
For dynamic linking, it cannot be fixed this way. It can be fixed at compile time, but with dynamic linking the same problem exists at run-time (startup): Here all the `-L`s become `RPATH`s if not installed in a global location (for example, nix has an `RPATH` for each package), and thus program startup can take up to those 0.7 seconds I mentioned.
To solve the runtime problem, the only solution seems to be to place the libraries into the same directory (i.e. to have `M = 1` essentially).
This approach (putting all libs into 1 directory) would also solve it for the static linking case, with the drawback of this being not compatible with how cabal sandboxes, stack build and snapshot dirs, nix, Debian and other distributions deliver and build libraries. And for some of them this approach goes straight against their nature.
- \*Detail discussion:\*\*
See below the relevant discussion on \#ghc:
```
nh2: bgamari-: do you know why ghc uses -L and -l for linking libHS... things instead of passing the .a file directly?
hvr: nh2: btw, fun fact: on IBM AIX, both static and DSOs are stored in .a archives
bgamari-: nh2, I suspect just since it makes the dynamic and static linking codepaths consistent
hvr: nh2: and if you use .a for linking, you end up hardwiring the DSO path into your executable
nh2: bgamari-: I'm looking into whether it would make sense to change it, at least for the platforms that would support it, because the (-L * -l) searching that it does currently seems to dominate link times here
nh2: cc hvr
hvr: nh2: sounds reasonable; but then you end up with longer CLI arguments
hvr: nh2: it could be a problem for when the tools don't support @
bgamari-: nh2, seriously?
bgamari-: the search is really that long?
bgamari-: nh2, it seems like that's a linker bug
hvr: bgamari-: I guess it depends on how many -L there are
bgamari-: nh2, how many libraries are you linking against?
hvr: bgamari-: as each -L and -l multiply w/ each other requiring several stat() calls iirc
bgamari-: hvr, yes
hvr: but otoh, I wouldn't expect this to *dominate* linker times
bgamari-: right
bgamari-: hvr, this is the compile-time equivalent to #11587
bgamari-: which I still think we should do
hvr: right
bgamari-: hmm
bgamari-: although comment:9 sort of suggests that this is already the case for user-installed libraries
***bgamari- forgot about that
hvr: I mean, if you have really *many* -L-paths
hvr: then the quadratic effect becomes probably significant
bgamari-: right
bgamari-: nh2, how many libraries are you linking against?
nh2: bgamari-: I have approximately L=450 and l=350. There is some notoriously slow tooling "in between" that I'm currently investigating, namely nix's ld-wrapper, which does does the stat'ing in bash, where statting that many files easily takes 1 second, but I did a quick test with `xargs ls -1` on the "$DIR/lib${name}.a" expansion, an that too takes 1 second, so it might not be entirely its fault
hvr: ok, ~400 is quite a bit
bgamari-: sheesh
bgamari-: yes, that is... impressive
geekosaur: next they'll want this to work on macOS >..
geekosaur: >.>
hvr: and then windows!
nh2: even my hobby projects have 300 recursive deps by now
nh2: bgamari-: my strace says that `ls` did the 160k stat()s in 0.7 seconds, which is half of the time that `gold` needs to link my binary
nh2: bgamari-: I have now strace'd `ld` itself, that does it slightly faster, 0.5 seconds, but this is just because it's my hobby project and has "only" that many deps; for a real project that'd be 2 seconds just stat()ing
bgamari-: nh2, sheesh
nh2: bgamari-: of course nix's ld wrapper, being written in bash, does the same thing but at least 5x slower
bgamari-: nh2, do you just add all of Hackage to your build-depends? ;)
bgamari-: nh2, Instead of passing explicit paths I think I would rather just put all of the archives in LIBDIR
nh2: bgamari-: I blame it on my dependees ;) also, "Haskell has high-quality libraries and encourages code reuse" comes back at us here
bgamari-: although, admittedly, I haven't really thought through the consequences of this yet
bgamari-: this does sound like a worthwhile thing to fix though
bgamari-: that is a significant amount of time
nh2: bgamari-: personally I'd WAY prefer explicit args vs env vars because then I can see them in ps, I can easily replay the specific command myself to debug it etc
hvr: nh2: not every library on Hackage is "high-quality" ;-)
bgamari-: I had always assumed that our large linking times we due to, well, the "linking"
bgamari-: not just the stating
bgamari-: nh2, fair enough, but I'd rather not have to add even more platform-dependent behavior to our interaction with the system toolchain
bgamari-: oh, wait
bgamari-: nh2, I didn't mean to pass via env var
bgamari-: nh2, I just meant pass one -L
bgamari-: nh2, where the static and dynamic libraries can both be
bgamari-: found
nh2: bgamari-: I don't know that, where can I read about that? Is it a flag?
bgamari-: nh2, -L?
bgamari-: it's just the usual --library-path flag
nh2: bgamari-: I got confused by LIBDIR in caps
bgamari-: ah
bgamari-: right, I should have been more specific
nh2: bgamari-: so what do you mean by that, somehow put all the libraries into a single dir?
bgamari-: nh2, treat static archives the same way we treat dynamic libraries
bgamari-: which is to place them in, e.g., $HOME/.cabal/lib/$ghc_version/
bgamari-: instead of where they are currently, $HOME/.cabal/lib/$ghc_version/$library_abi_name
bgamari-: then you can just pass -L$HOME/.cabal/lib/$ghc_version to ld
bgamari-: and a -l for each library
bgamari-: I think this is probably as much a Cabal change as it is a GHC change
nh2: bgamari-: that doesn't seem to go well with approaches that package separately, like debian, nix, cabal sandboxes and stack work dirs
hvr: which includes new-build
bgamari-: I'm not sure it's fundamentally incompatible
hvr: yeah, but it's a lot of work to change everyone :-)
bgamari-: to take the case of new-build, all that matters AFAIK is that the packages are registered in separate package dbs
bgamari-: there's nothing stopping you from throwing all of the libraries into one directory
hvr: bgamari-: well, I kinda exploit that new-build has nicely self-contained folders
hvr: this makes it easier to atomically move around artifacts
nh2: bgamari-: do you have a dislike for passing them explicitly as files beyond cross-platform worries? Because I really find explicit arguments the cleanest, easiest and most debuggable approach
hvr: as I can stage the new artifact, and then move it into place
hvr: atomically
hvr: by simply renaming/moving the folder which contains everyting
bgamari-: nh2, I'm just currently really not sure that passing libraries by path is really equivalent to passing via -l
hvr: unfortauntely filesytems don't offer many other facilities for atomic transactions
bgamari-: I would need to run some experiments
nh2: bgamari-: gcc's and ld's man pages suggest that to me, looking at their respective `-l`; we certainly should double check (or maybe simpler, ask the linker authors)
bgamari-: if we can really show that the linker treats explicit paths no differently then I'd be okay with it
nh2: suggests that they are equivalent)
bgamari-: but I'm rather weary
bgamari-: nh2, are you only suggesting this for static libraries?
geekosaur: it's supposed to be equivalent. but shared objects have the added issue of runtime discoverability (i.e. passing by full path at link time does not install a full path for runtime access)
geekosaur: except on macos or older aix where it's always a full path)
nh2: bgamari-: no, at least the stat()-taking-time problem is the same problem for .so's (though I'm using static linking in many places and would be appreciate an improvement even if limited to static linking)
bgamari-: nh2, the problem is that your approach doesn't help dynamic linkage at all
bgamari-: since the runtime linker still needs to search N paths
bgamari-: so I would argue that new-build, stack, etc. really should be putting libraries in the same directory regardless
bgamari-: more work or not
bgamari-: it's the only way to truly solve the problem
mpickering: Wonders if David saw this issue https://github.com/haskell/cabal/issues/4550
alanz: mpickering: what are you planning to use the source plugins for?
nh2: bgamari-: yeah you're right, the start-up cost of the executable will always be there for dynamic linking, I was purely talking from the compiler's perspective
bgamari-: nh2, my point was that I would prefer to solve the problem once and for all
bgamari-: rather than have another sharp edge that we then still need to solve
bgamari-: given that moving the libraries solves both problems, it feels like the right solution
mpickering: alanz: haskell-indexer was the plan
nh2: bgamari-: I agree that for dynamic linking that is the only solution. But I'm not sure there exist a fits-it-all solution across static and dynamic. At least for my work, I'd prefer to have static libs that can be anywhere, in nix-style immutable locations, and give up on dynamic linking (of Haskell libs) to get that. It seems that hvr's thoughts are going in the same direction on the cabal side, and lots of build system and OS movements these days seem to converge away from global shared dirs to dir-prefixes.
nh2: I also suspect that static linking will be even more attractive now that sensible -split-sections is in place, which can give smaller code sizes, which .so's can't deliver.
nh2: So I'm not sure that a big shift to the fits-it-all solution that satisfies dynamic linking needs would be the most practical or used; it'd certainly be nice to have it for dynamic linking, but I'm not sure all the downstreams can be forced to do it that way for non-static if it quite fundamentally dictates how they have to work. If they can, it would probably take pretty long.
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 8.0.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | bgamari, hvr, nh2 |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Linker paths carry substantial N*M overhead when many libaries are used","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":["bgamari","hvr","nh2"],"type":"Bug","description":"**\"The linker search path problem\"**\r\n\r\nIt's common these days to have 400 (transitive) Hackage dependencies (even my hobby projects have that many).\r\n\r\nWhen linking, statically or dynamically, GHC passes `-L /path/to/foo/dir` and `-L HSfoo...` to the linker for each Haskell package `foo`.\r\n\r\nThat results in `N` many linker search paths (`-L`) and `M` many library names. That will translate in `N * M` many `stat()` syscalls (file existence checks) in the linker to check where each file is.\r\n\r\nFor 400 package dependencies, that translates to 160k `stat()` syscalls. On my machine (on SSD and hot file system cache in RAM), that takes `0.7 seconds` (measured with `strace -c -w`).\r\n\r\nThat is a substantial overhead for linking (for example, the executable with 400 dependencies with which I found this problem can be linked with `ld.gold` in just 1.5 seconds).\r\n\r\nIf there is tooling in between GHC and the linker that also parses linker flags and checks for file existence (for example Nix's `cc-wrapper` and `ld-wrapper` scripts, or other instrumentation or build system tooling, which are often not written in compiled languages and thus [https://github.com/NixOS/nixpkgs/issues/27609 much slower] at stat()ing than the linker is), then the problem can be easily blown up another 10x.\r\n\r\nAs a result, you may be waiting a lot longer for your link to finish than necessary.\r\n\r\nFor static linking, this could be resolved by passing the archive files (`libHSfoo....a`) directly to the linker instead of the `-L`/`-l` combination.\r\n\r\nFor this we would need to check that passing files directly really have the same semantics as `-L` and `-l`, but the man pages suggest so (and I'll check it with the binutils authors).\r\n\r\nFor dynamic linking, it cannot be fixed this way. It can be fixed at compile time, but with dynamic linking the same problem exists at run-time (startup): Here all the `-L`s become `RPATH`s if not installed in a global location (for example, nix has an `RPATH` for each package), and thus program startup can take up to those 0.7 seconds I mentioned.\r\n\r\nTo solve the runtime problem, the only solution seems to be to place the libraries into the same directory (i.e. to have `M = 1` essentially).\r\n\r\nThis approach (putting all libs into 1 directory) would also solve it for the static linking case, with the drawback of this being not compatible with how cabal sandboxes, stack build and snapshot dirs, nix, Debian and other distributions deliver and build libraries. And for some of them this approach goes straight against their nature.\r\n\r\n**Detail discussion:**\r\n\r\nSee below the relevant discussion on #ghc:\r\n\r\n{{{\r\nnh2: bgamari-: do you know why ghc uses -L and -l for linking libHS... things instead of passing the .a file directly?\r\nhvr: nh2: btw, fun fact: on IBM AIX, both static and DSOs are stored in .a archives\r\nbgamari-: nh2, I suspect just since it makes the dynamic and static linking codepaths consistent\r\nhvr: nh2: and if you use .a for linking, you end up hardwiring the DSO path into your executable\r\nnh2: bgamari-: I'm looking into whether it would make sense to change it, at least for the platforms that would support it, because the (-L * -l) searching that it does currently seems to dominate link times here\r\nnh2: cc hvr\r\nhvr: nh2: sounds reasonable; but then you end up with longer CLI arguments\r\nhvr: nh2: it could be a problem for when the tools don't support @\r\nbgamari-: nh2, seriously?\r\nbgamari-: the search is really that long?\r\nbgamari-: nh2, it seems like that's a linker bug\r\nhvr: bgamari-: I guess it depends on how many -L there are\r\nbgamari-: nh2, how many libraries are you linking against?\r\nhvr: bgamari-: as each -L and -l multiply w/ each other requiring several stat() calls iirc\r\nbgamari-: hvr, yes\r\nhvr: but otoh, I wouldn't expect this to *dominate* linker times\r\nbgamari-: right\r\nbgamari-: hvr, this is the compile-time equivalent to #11587\r\nbgamari-: which I still think we should do\r\nhvr: right\r\nbgamari-: hmm\r\nbgamari-: although comment:9 sort of suggests that this is already the case for user-installed libraries\r\n***bgamari- forgot about that\r\nhvr: I mean, if you have really *many* -L-paths\r\nhvr: then the quadratic effect becomes probably significant\r\nbgamari-: right\r\nbgamari-: nh2, how many libraries are you linking against?\r\nnh2: bgamari-: I have approximately L=450 and l=350. There is some notoriously slow tooling \"in between\" that I'm currently investigating, namely nix's ld-wrapper, which does does the stat'ing in bash, where statting that many files easily takes 1 second, but I did a quick test with `xargs ls -1` on the \"$DIR/lib${name}.a\" expansion, an that too takes 1 second, so it might not be entirely its fault\r\nhvr: ok, ~400 is quite a bit\r\nbgamari-: sheesh\r\nbgamari-: yes, that is... impressive\r\ngeekosaur: next they'll want this to work on macOS >..\r\ngeekosaur: >.>\r\nhvr: and then windows!\r\nnh2: even my hobby projects have 300 recursive deps by now\r\nnh2: bgamari-: my strace says that `ls` did the 160k stat()s in 0.7 seconds, which is half of the time that `gold` needs to link my binary\r\nnh2: bgamari-: I have now strace'd `ld` itself, that does it slightly faster, 0.5 seconds, but this is just because it's my hobby project and has \"only\" that many deps; for a real project that'd be 2 seconds just stat()ing\r\nbgamari-: nh2, sheesh\r\nnh2: bgamari-: of course nix's ld wrapper, being written in bash, does the same thing but at least 5x slower\r\nbgamari-: nh2, do you just add all of Hackage to your build-depends? ;)\r\nbgamari-: nh2, Instead of passing explicit paths I think I would rather just put all of the archives in LIBDIR\r\nnh2: bgamari-: I blame it on my dependees ;) also, \"Haskell has high-quality libraries and encourages code reuse\" comes back at us here\r\nbgamari-: although, admittedly, I haven't really thought through the consequences of this yet\r\nbgamari-: this does sound like a worthwhile thing to fix though\r\nbgamari-: that is a significant amount of time\r\nnh2: bgamari-: personally I'd WAY prefer explicit args vs env vars because then I can see them in ps, I can easily replay the specific command myself to debug it etc\r\nhvr: nh2: not every library on Hackage is \"high-quality\" ;-)\r\nbgamari-: I had always assumed that our large linking times we due to, well, the \"linking\"\r\nbgamari-: not just the stating\r\nbgamari-: nh2, fair enough, but I'd rather not have to add even more platform-dependent behavior to our interaction with the system toolchain\r\nbgamari-: oh, wait\r\nbgamari-: nh2, I didn't mean to pass via env var\r\nbgamari-: nh2, I just meant pass one -L\r\nbgamari-: nh2, where the static and dynamic libraries can both be\r\nbgamari-: found\r\nnh2: bgamari-: I don't know that, where can I read about that? Is it a flag?\r\nbgamari-: nh2, -L?\r\nbgamari-: it's just the usual --library-path flag\r\nnh2: bgamari-: I got confused by LIBDIR in caps\r\nbgamari-: ah\r\nbgamari-: right, I should have been more specific\r\nnh2: bgamari-: so what do you mean by that, somehow put all the libraries into a single dir?\r\nbgamari-: nh2, treat static archives the same way we treat dynamic libraries\r\nbgamari-: which is to place them in, e.g., $HOME/.cabal/lib/$ghc_version/\r\nbgamari-: instead of where they are currently, $HOME/.cabal/lib/$ghc_version/$library_abi_name\r\nbgamari-: then you can just pass -L$HOME/.cabal/lib/$ghc_version to ld\r\nbgamari-: and a -l for each library\r\nbgamari-: I think this is probably as much a Cabal change as it is a GHC change\r\nnh2: bgamari-: that doesn't seem to go well with approaches that package separately, like debian, nix, cabal sandboxes and stack work dirs\r\nhvr: which includes new-build\r\nbgamari-: I'm not sure it's fundamentally incompatible\r\nhvr: yeah, but it's a lot of work to change everyone :-)\r\nbgamari-: to take the case of new-build, all that matters AFAIK is that the packages are registered in separate package dbs\r\nbgamari-: there's nothing stopping you from throwing all of the libraries into one directory\r\nhvr: bgamari-: well, I kinda exploit that new-build has nicely self-contained folders\r\nhvr: this makes it easier to atomically move around artifacts\r\nnh2: bgamari-: do you have a dislike for passing them explicitly as files beyond cross-platform worries? Because I really find explicit arguments the cleanest, easiest and most debuggable approach\r\nhvr: as I can stage the new artifact, and then move it into place\r\nhvr: atomically\r\nhvr: by simply renaming/moving the folder which contains everyting\r\nbgamari-: nh2, I'm just currently really not sure that passing libraries by path is really equivalent to passing via -l\r\nhvr: unfortauntely filesytems don't offer many other facilities for atomic transactions\r\nbgamari-: I would need to run some experiments\r\nnh2: bgamari-: gcc's and ld's man pages suggest that to me, looking at their respective `-l`; we certainly should double check (or maybe simpler, ask the linker authors)\r\nbgamari-: if we can really show that the linker treats explicit paths no differently then I'd be okay with it\r\nnh2: suggests that they are equivalent)\r\nbgamari-: but I'm rather weary\r\nbgamari-: nh2, are you only suggesting this for static libraries?\r\ngeekosaur: it's supposed to be equivalent. but shared objects have the added issue of runtime discoverability (i.e. passing by full path at link time does not install a full path for runtime access)\r\ngeekosaur: except on macos or older aix where it's always a full path)\r\nnh2: bgamari-: no, at least the stat()-taking-time problem is the same problem for .so's (though I'm using static linking in many places and would be appreciate an improvement even if limited to static linking)\r\nbgamari-: nh2, the problem is that your approach doesn't help dynamic linkage at all\r\nbgamari-: since the runtime linker still needs to search N paths\r\nbgamari-: so I would argue that new-build, stack, etc. really should be putting libraries in the same directory regardless\r\nbgamari-: more work or not\r\nbgamari-: it's the only way to truly solve the problem\r\nmpickering: Wonders if David saw this issue https://github.com/haskell/cabal/issues/4550\r\nalanz: mpickering: what are you planning to use the source plugins for?\r\nnh2: bgamari-: yeah you're right, the start-up cost of the executable will always be there for dynamic linking, I was purely talking from the compiler's perspective\r\nbgamari-: nh2, my point was that I would prefer to solve the problem once and for all\r\nbgamari-: rather than have another sharp edge that we then still need to solve\r\nbgamari-: given that moving the libraries solves both problems, it feels like the right solution\r\nmpickering: alanz: haskell-indexer was the plan\r\nnh2: bgamari-: I agree that for dynamic linking that is the only solution. But I'm not sure there exist a fits-it-all solution across static and dynamic. At least for my work, I'd prefer to have static libs that can be anywhere, in nix-style immutable locations, and give up on dynamic linking (of Haskell libs) to get that. It seems that hvr's thoughts are going in the same direction on the cabal side, and lots of build system and OS movements these days seem to converge away from global shared dirs to dir-prefixes.\r\nnh2: I also suspect that static linking will be even more attractive now that sensible -split-sections is in place, which can give smaller code sizes, which .so's can't deliver.\r\nnh2: So I'm not sure that a big shift to the fits-it-all solution that satisfies dynamic linking needs would be the most practical or used; it'd certainly be nice to have it for dynamic linking, but I'm not sure all the downstreams can be forced to do it that way for non-static if it quite fundamentally dictates how they have to work. If they can, it would probably take pretty long.\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14030Implement the "Derive Lift instances for data types in template-haskell" prop...2024-03-18T14:36:50ZRyan ScottImplement the "Derive Lift instances for data types in template-haskell" proposalBack in September 2015, I [proposed](https://mail.haskell.org/pipermail/libraries/2015-September/026117.html) using the `DeriveLift` extension to, well, derive `Lift` instance for data types in the `template-haskell` library. The proposa...Back in September 2015, I [proposed](https://mail.haskell.org/pipermail/libraries/2015-September/026117.html) using the `DeriveLift` extension to, well, derive `Lift` instance for data types in the `template-haskell` library. The proposal was well received, but I was unable to implement it at the time due to `DeriveLift`'s newness (having only been introduced in GHC 8.0). Now that GHC 8.0 is the oldest version of GHC that we support bootstrapping with, this is no longer an obstacle.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ---------------- |
| Version | 8.3 |
| Type | Task |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Implement the \"Derive Lift instances for data types in template-haskell\" proposal","status":"New","operating_system":"","component":"Template Haskell","related":[],"milestone":"8.4.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Task","description":"Back in September 2015, I [https://mail.haskell.org/pipermail/libraries/2015-September/026117.html proposed] using the `DeriveLift` extension to, well, derive `Lift` instance for data types in the `template-haskell` library. The proposal was well received, but I was unable to implement it at the time due to `DeriveLift`'s newness (having only been introduced in GHC 8.0). Now that GHC 8.0 is the oldest version of GHC that we support bootstrapping with, this is no longer an obstacle.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14026hs_init is not idempotent2019-07-07T18:18:49ZFeuerbachhs_init is not idempotenths_init tries to be idempotent by ignoring all calls but the first one. However, subsequent calls to hs_init do not set argc and argv correctly.
Here's a test case:
```
#include "HsFFI.h"
#include "stdio.h"
void try_init() {
char *a...hs_init tries to be idempotent by ignoring all calls but the first one. However, subsequent calls to hs_init do not set argc and argv correctly.
Here's a test case:
```
#include "HsFFI.h"
#include "stdio.h"
void try_init() {
char *argv[] = { "./test", "+RTS", "-s", "-RTS", "arg", 0 };
char **argv_ptr = argv;
int argc = sizeof(argv)/sizeof(argv[0]) - 1;
hs_init(&argc, &argv_ptr);
printf("%d\n", argc);
}
int main() {
try_init();
try_init();
}
```
Result:
```
2
5
```
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"hs_init is not idempotent","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"hs_init tries to be idempotent by ignoring all calls but the first one. However, subsequent calls to hs_init do not set argc and argv correctly.\r\n\r\nHere's a test case:\r\n\r\n{{{\r\n#include \"HsFFI.h\"\r\n#include \"stdio.h\"\r\n\r\nvoid try_init() {\r\n char *argv[] = { \"./test\", \"+RTS\", \"-s\", \"-RTS\", \"arg\", 0 };\r\n char **argv_ptr = argv;\r\n int argc = sizeof(argv)/sizeof(argv[0]) - 1;\r\n hs_init(&argc, &argv_ptr);\r\n printf(\"%d\\n\", argc);\r\n}\r\n\r\nint main() {\r\n try_init();\r\n try_init();\r\n}\r\n}}}\r\n\r\nResult:\r\n\r\n{{{\r\n2\r\n5\r\n}}}","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14025Object file is put in wrong directory when any source has absolute path2019-07-07T18:18:49ZliteronObject file is put in wrong directory when any source has absolute pathFiles: `/tmp/e/A.hs`, `/tmp/e/dep.c`. Current dir: `/tmp/e`.
`ghc -odir /tmp/xyzzy A.hs dep.c`: works as expected, puts `dep.o` in `/tmp/xyzzy`.
But try to prefix either `A.hs` or `dep.c` (or both) with `/tmp/e/`, and suddenly `dep.o` ...Files: `/tmp/e/A.hs`, `/tmp/e/dep.c`. Current dir: `/tmp/e`.
`ghc -odir /tmp/xyzzy A.hs dep.c`: works as expected, puts `dep.o` in `/tmp/xyzzy`.
But try to prefix either `A.hs` or `dep.c` (or both) with `/tmp/e/`, and suddenly `dep.o` is put in `/tmp/e`, not in `/tmp/xyzzy`.
Couldn't check with 8.2.1 yet.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ------------ |
| Version | 8.0.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Object file is put in wrong directory when any source has absolute path","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.0.1","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"Files: `/tmp/e/A.hs`, `/tmp/e/dep.c`. Current dir: `/tmp/e`.\r\n\r\n`ghc -odir /tmp/xyzzy A.hs dep.c`: works as expected, puts `dep.o` in `/tmp/xyzzy`.\r\n\r\nBut try to prefix either `A.hs` or `dep.c` (or both) with `/tmp/e/`, and suddenly `dep.o` is put in `/tmp/e`, not in `/tmp/xyzzy`.\r\n\r\nCouldn't check with 8.2.1 yet.","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14018Highlight differences of Frontend Plugin vs GHC API2019-07-07T18:18:51ZliteronHighlight differences of Frontend Plugin vs GHC APIThere's many useful functionality in non-exposed modules. For example, `ghc/Main.hs` contains `doMake` \[0\], which is a one-shop stop for compiling all (non-Haskell + Haskell) source files. Now a GHC API client has to replicate much of ...There's many useful functionality in non-exposed modules. For example, `ghc/Main.hs` contains `doMake` \[0\], which is a one-shop stop for compiling all (non-Haskell + Haskell) source files. Now a GHC API client has to replicate much of this logic to get GHC-alike behavior.
Similarly for `parseModeFlags`. Or is the intent here to encourage using of Frontend plugins instead of relying on these internals?
\[0\]: http://stuff.codereview.me/\#ghc/ghc/Main.hs?corpus=ghc-8.2.1-rc2&signature&line=696
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | -------------- |
| Version | 8.2.1-rc2 |
| Type | FeatureRequest |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"Expose more pipeline functionality to GHC API","status":"New","operating_system":"","component":"Compiler","related":[],"milestone":"","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.2.1-rc2","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"FeatureRequest","description":"There's many useful functionality in non-exposed modules. For example, `ghc/Main.hs` contains `doMake` [0], which is a one-shop stop for compiling all (non-Haskell + Haskell) source files. Now a GHC API client has to replicate much of this logic to get GHC-alike behavior.\r\n\r\nSimilarly for `parseModeFlags`. Or is the intent here to encourage using of Frontend plugins instead of relying on these internals?\r\n\r\n[0]: http://stuff.codereview.me/#ghc/ghc/Main.hs?corpus=ghc-8.2.1-rc2&signature&line=696","type_of_failure":"OtherFailure","blocking":[]} -->https://gitlab.haskell.org/ghc/ghc/-/issues/14013Bad monads performance2022-07-18T08:52:05Zdanilo2Bad monads performanceHi! We've been struggling with a very strange GHC behavior on IRC today. Let's consider the following code (needs mtl and criterion to be compiled):
```hs
module Main where
import Prelude
import Criterion.Main
import qualified Control....Hi! We've been struggling with a very strange GHC behavior on IRC today. Let's consider the following code (needs mtl and criterion to be compiled):
```hs
module Main where
import Prelude
import Criterion.Main
import qualified Control.Monad.State.Strict as Strict
import qualified Control.Monad.State.Class as State
import Control.DeepSeq (NFData, rnf, force)
import GHC.IO (evaluate)
import Data.Monoid
-----------------------------
-- === Criterion utils === --
-----------------------------
eval :: NFData a => a -> IO a
eval = evaluate . force ; {-# INLINE eval #-}
liftExp :: (Int -> a) -> (Int -> a)
liftExp f = f . (10^) ; {-# INLINE liftExp #-}
expCodeGen :: NFData a => (Int -> a) -> (Int -> IO a)
expCodeGen f i = do
putStrLn $ "generating input code (10e" <> show i <> " chars)"
out <- eval $ liftExp f i
putStrLn "code generated sucessfully"
return out
{-# INLINE expCodeGen #-}
expCodeGenBench :: (NFData a, NFData b) => (Int -> a) -> (a -> b) -> Int -> Benchmark
expCodeGenBench f p i = env (expCodeGen f i) $ bench ("10e" <> show i) . nf p ; {-# INLINE expCodeGenBench #-}
-------------------------------
-- === (a*) list parsing === --
-------------------------------
genList_a :: Int -> [Char]
genList_a i = replicate i 'a' ; {-# INLINE genList_a #-}
pureListParser_a :: [Char] -> Bool
pureListParser_a = \case
'a':s -> pureListParser_a s
[] -> True
_ -> False
{-# INLINE pureListParser_a #-}
mtlStateListParser_a :: State.MonadState [Char] m => m Bool
mtlStateListParser_a = State.get >>= \case
'a':s -> State.put s >> mtlStateListParser_a
[] -> return True
_ -> return False
{-# INLINE mtlStateListParser_a #-}
mtlStateListParser_a_typed :: Strict.State [Char] Bool
mtlStateListParser_a_typed = State.get >>= \case
'a':s -> State.put s >> mtlStateListParser_a_typed
[] -> return True
_ -> return False
{-# INLINE mtlStateListParser_a_typed #-}
mtlStateListParser_a_let :: Strict.MonadState [Char] m => m Bool
mtlStateListParser_a_let = go where
go = Strict.get >>= \case
'a':s -> Strict.put s >> go
[] -> return True
_ -> return False
{-# INLINE mtlStateListParser_a_let #-}
{-# SPECIALIZE mtlStateListParser_a :: Strict.State [Char] Bool #-}
{-# SPECIALIZE mtlStateListParser_a_typed :: Strict.State [Char] Bool #-}
main = do
defaultMain
[ bgroup "a*" $
[ bgroup "pure" $ expCodeGenBench genList_a pureListParser_a <$> [6..6]
, bgroup "mtl.State.Strict" $ expCodeGenBench genList_a (Strict.evalState mtlStateListParser_a) <$> [6..6]
, bgroup "mtl.State.Strict typed" $ expCodeGenBench genList_a (Strict.evalState mtlStateListParser_a_typed) <$> [6..6]
, bgroup "mtl.State.Strict let" $ expCodeGenBench genList_a (Strict.evalState mtlStateListParser_a_let) <$> [6..6]
]
]
```
The code was compiled with following options (and many other variations): `-threaded -funbox-strict-fields -O2 -fconstraint-solver-iterations=100 -funfolding-use-threshold=10000 -fexpose-all-unfoldings -fsimpl-tick-factor=1000 -flate-dmd-anal`
Everything in this code has `INLINE` pragma. The important part we should focus on are these two functions:
```hs
pureListParser_a :: [Char] -> Bool
pureListParser_a = \case
'a':s -> pureListParser_a s
[] -> True
_ -> False
{-# INLINE pureListParser_a #-}
mtlStateListParser_a :: State.MonadState [Char] m => m Bool
mtlStateListParser_a = State.get >>= \case
'a':s -> State.put s >> mtlStateListParser_a
[] -> return True
_ -> return False
{-# INLINE mtlStateListParser_a #-}
```
Which are just "parsers" accepting strings containing only 'a' characters. The former is pure one, while the later uses `State` to keep the remaining input. The following list contains performance related observations:
1. For the rest of the points, let's call the performance of `pureListParser_a` a "good" one and everything worse a "bad" one.
1. The performance of `mtlStateListParser_a` is bad, it runs 10 times slower than `pureListParser_a`. Inspecting CORE we can observe that GHC jumps between `(# a,b #)` and `(a,b)` representations all the time.
1. If we add a specialize pragma `{-# SPECIALIZE mtlStateListParser_a :: Strict.State [Char] Bool #-}`, the performance of `mtlStateListParser_a` is good (exactly the same as `pureListParser_a`).
1. If we do NOT use specialize pragma, but we use explicite, non-polymorphic type signature `mtlStateListParser_a_typed :: Strict.State [Char] Bool`, the performance is bad (!), identical to the polymorphic version without specialization.
1. If we use SPECIALIZE pragma together with explicite, non-polymorphic type, so we use BOTH `mtlStateListParser_a_typed :: Strict.State [Char] Bool` AND `{-# SPECIALIZE mtlStateListParser_a_typed :: Strict.State [Char] Bool #-}` we get the good performance.
1. If we transform `pureListParser_a` to
```hs
mtlStateListParser_a_let :: Strict.MonadState [Char] m => m Bool
mtlStateListParser_a_let = go where
go = Strict.get >>= \case
'a':s -> Strict.put s >> go
[] -> return True
_ -> return False
{-# INLINE mtlStateListParser_a_let #-}
```
we again get the good performance without the need to use `SPECIALIZE` pragmas.
1. The performance of all the functions that are not optimized as good as `pureListParser_a` is a lot worse in GHC 8.2.1-rc3 than in 8.0.2.
1. The not-yet documented flag `-fspecialise-aggressively` does NOT affect the results (https://ghc.haskell.org/trac/ghc/ticket/12463).
1. If you do NOT use `INLINE` pragma on functions `mtlStateListParser_a` and `mtlStateListParser_a_typed` their performance is good (so `INLINE` pragma makes it bad until we provide explicit specialization). Moreover, if we use `INLINABLE` pragma instead of `INLINE` on these functions (which logically makes more sense, because they are recursive), performance of the polymorphic one `mtlStateListParser_a` is good, while performance of the explicitly typed `mtlStateListParser_a_typed` is bad until we provide explicite specialization.
The above points raise the following questions:
1. Why GHC does not optimize `mtlStateListParser_a` the same way as `pureListParser_a` and where the jumping between `(# a,b #)` and `(a,b)` comes from?
1. Is there any way to tell GHC to automatically insert `SPECIALIZE` pragmas, especially in performance critical code?
1. Why providing very-explicite type signature `mtlStateListParser_a_typed :: Strict.State [Char] Bool` does not solve the problem unless we use `SPECIALIZE` pragma that tells the same as the signature? (GHC even warns: `SPECIALISE pragma for non-overloaded function ‘mtlStateListParser_a_typed’` but it affects performance.)
1. Why the trick to alias the body of recursive function to a local variable `go` affects the performance in any way, especially when it does NOT bring any variable to the local let scope?
We've been testing this behavior in GHC 8.0.2 and 8.2.1-rc3 and several people reported exactly the same observations.⊥Simon Peyton JonesSimon Peyton Jones