Closed bitemyapp closed 7 years ago
https://github.com/Homebrew/homebrew-core/blob/master/Formula/haskell-stack.rb#L45
You need to pass --stack-yaml=stack-8.0.yaml
Thank you for the quick reply! Unfortunately that didn't work and I'm still seeing the same error message...
@jasonstolaruk stack upgrade
in older versions of Stack are going to try to use the preferred LTS version to build stack-1.4.0, which is lts-6, regardless of your global project's default resolver. Newer versions of stack upgrade
will just download a binary instead. Your best bet is to do a manual download from https://github.com/commercialhaskell/stack/releases. Future upgrades should be easier.
@borsboom Ah, that would explain it! Yeah, I think my current version of stack is fairly old. I'll try that, thanks!
@borsboom @jasonstolaruk I just got this with Stack 1.4.1
, LTS 8.4, and Sierra. Not sure where to report, so chiming in here again.
[ 2 of 16] Compiling Settings.StaticFiles ( src/Settings/StaticFiles.hs, .stack-work/dist/x86_64-osx/Cabal-1.24.2.0/build/Settings/StaticFiles.o )
ghc: panic! (the 'impossible' happened)
(GHC version 8.0.2 for x86_64-apple-darwin):
Loading temp shared object failed: dlopen(/var/folders/gq/rh0h8yns2p1bb5d31mdx69b40000gn/T/ghc37966_0/libghc_33.dylib, 5): no suitable image found. Did find:
/var/folders/gq/rh0h8yns2p1bb5d31mdx69b40000gn/T/ghc37966_0/libghc_33.dylib: malformed mach-o: load commands size (33560) > 32768
Jason, are you sorted now?
It's one project of several at work that is tripping over this. Everything else builds.
Should I file a new ticket? Should it be with Stack?
Just to confirm, still getting this with a Stack binary provisioned by the website via curl
or manual download.
$ stack --version
Version 1.4.0, Git revision e714f1dd3fade19496d91bd6a017e435a96a6bcd (4640 commits) x86_64 hpack-0.17.0
@bitemyapp Not sure where that should be filed. Feel free to open a ticket, but it'll take a minimal repro for us to investigate it. Seems more likely to be a ghc issue.
@bitemyapp Yep, I was able to build just now. Looks like I'm good.
macOS Sierra 10.12.3 Stack Version 1.4.0, Git revision e714f1dd3fade19496d91bd6a017e435a96a6bcd (4640 commits) x86_64 hpack-0.17.0 resolver: nightly-2017-04-02
This isn't and never was a GHC issue, it's a new limit added by Apple, for which a workaround was added to Cabal, which required a new feature in GHC.
If your project has enough dependencies it's possible to hit the limit again even with the workaround in place. The output of otool -l
on the temporary shared object (invoke GHC with -keep-tmp-files
) will clarify what is happening.
I don't think it's possible for Stack to do anything about this. Even if it is possible to add a workaround to Stack, it's properly fixed in Cabal and/or GHC. It's annoying when Apple does this sort of thing, but unfortunately we're stuck with it (it's not a macOS bug; they intentionally added that limit, and we will just have to adapt).
@chrisdone I can confirm that this still comes up for me on ghc-8.0.2 and lts-8.5 while building a yesod-based application:
ghc: panic! (the 'impossible' happened)
(GHC version 8.0.2 for x86_64-apple-darwin):
Loading temp shared object failed: dlopen(/var/folders/l2/zpkx9mks1n12dbj0cy16nfn40000gn/T/ghc34456_0/libghc_10.dylib, 5): no suitable image found. Did find:
/var/folders/l2/zpkx9mks1n12dbj0cy16nfn40000gn/T/ghc34456_0/libghc_10.dylib: malformed mach-o: load commands size (33280) > 32768
Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug
As @rwbarton points out, you can still hit the limit even with the workaround added to Cabal.
In my case, I may be able to shorted the length of some paths because I currently soft link ~/.stack to elsewhere (in my dotfiles
repo) so that it picks up my .stack/config.yaml
.
I wonder if there might be any benefit in soft linking ~/.stack
to say /s
to shorten paths further?
A quick follow-up. For this app, I wasn't able to get it to build when I moved .stack to the usual location (ie. /Users/steshaw/.stack
). However, when I soft linked /s
to ~/.stack
, I managed to get a successful build.
The tail end of the output from otool -l
shows that the difference is made when addressing packages that come with ghc. Also, there is only a couple of hundred bytes to spare for sizeofcmds
.
$ otool -l <file>.dylib | grep /s/programs
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/process-1.4.3.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/directory-1.3.0.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/filepath-1.4.1.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/template-haskell-2.11.1.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/pretty-1.1.3.3 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/ghc-boot-th-8.0.2 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/unix-2.7.2.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/time-1.6.0.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/transformers-0.5.2.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/binary-0.8.3.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/containers-0.5.7.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/bytestring-0.10.8.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/deepseq-1.4.2.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/array-0.5.1.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/base-4.9.1.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/integer-gmp-1.0.0.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/ghc-prim-0.5.0.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/rts (offset 12)
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/directory-1.3.0.0 (offset 12)
Load command 125
cmd LC_RPATH
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/filepath-1.4.1.1 (offset 12)
Load command 126
cmd LC_RPATH
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/ghc-boot-th-8.0.2 (offset 12)
Load command 127
cmd LC_RPATH
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/ghc-prim-0.5.0.0 (offset 12)
Load command 128
cmd LC_RPATH
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/integer-gmp-1.0.0.1 (offset 12)
Load command 129
cmd LC_RPATH
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/pretty-1.1.3.3 (offset 12)
Load command 130
cmd LC_RPATH
cmdsize 80
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/process-1.4.3.0 (offset 12)
...
$ otool -l .stack-work/install/x86_64-osx/lts-8.4/8.0.2/lib/x86_64-osx-ghc-8.0.2/libHSyesod-core-1.4.32-G0tj9L3iIRq7jY7gWqui14-ghc8.0.2.dylib | grep /s/programs
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/array-0.5.1.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/base-4.9.1.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/binary-0.8.3.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/bytestring-0.10.8.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/containers-0.5.7.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/deepseq-1.4.2.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/directory-1.3.0.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/filepath-1.4.1.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/ghc-boot-th-8.0.2 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/ghc-prim-0.5.0.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/integer-gmp-1.0.0.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/pretty-1.1.3.3 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/process-1.4.3.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/rts (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/template-haskell-2.11.1.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/time-1.6.0.1 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/transformers-0.5.2.0 (offset 12)
path /s/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/unix-2.7.2.1 (offset 12)
Thank you for sharing this tactic @steshaw, still not quite enough in my case:
(GHC version 8.0.2 for x86_64-apple-darwin):
Loading temp shared object failed: dlopen(/var/folders/gq/rh0h8yns2p1bb5d31mdx69b40000gn/T/ghc76548_0/libghc_33.dylib, 5): no suitable image found. Did find:
/var/folders/gq/rh0h8yns2p1bb5d31mdx69b40000gn/T/ghc76548_0/libghc_33.dylib: malformed mach-o: load commands size (33288) > 32768
Other than the irritation of getting dyld
to compile (you have to start vendoring the darwin userland into a build env), is there a reason people haven't made a fork that disables the byte limit? /cc @borsboom
It's the loader itself that has the limit: https://github.com/commercialhaskell/stack/issues/2577#issuecomment-262725233
@ilovezfs any idea as to why Apple did this?
@bitemyapp I believe it's purely an optimization measure to improve load times, but there may also be undisclosed security issues with the prior versions for all we know. (Also, no one should run into the limit in the first place when libraries are arranged as intended.)
The LC_LOAD_DYLIB
load command for one library is typically 72 bytes long (depending on the library's file name length), so even with no other load commands at all (in particular, not counting any LC_RPATH
entries) that puts a limit of around 500 on the number of dependencies. My understanding is that many Yesod-based projects already comfortably exceed half this number so it's a limit that does not seem very far off.
@rwbarton: would it help to shorten the library paths within ~/.stack
? On Windows replace some of the deeper paths with a short hash to work around path length limits, and we could do something like that on macOS too (although I'd much rather not, since it makes it harder for a human to navigate ~/.stack).
@borsboom My load commands typically look something like this:
cmd LC_LOAD_DYLIB
cmdsize 72
name @rpath/libHSghc-boot-th-8.0.2-ghc8.0.2.dylib (offset 24)
time stamp 2 Wed Dec 31 19:00:02 1969
It's using @rpath
to handle the path prefix. I don't know how the bytes are calculated by the runtime loader, but I'm not sure what more you can do.
This is a touch frustrating as the project that won't build is a pretty young Yesod project with not many extra dependencies beyond Yesod + lens.
Stack could create a library in intermediate steps, while the tree of dynamic libraries would be bigger, the limit could be mitigated.
I'm looking into possible solutions, for Nix one would be just to patch Apple source.
Can anyone confirm that this is fixed in macOS High Sierra? I was previously on Sierra but had to wipe my machine and downgrade to El Capitan to get work done. I'm wondering if it's safe to upgrade to High Sierra for a yesod project with lots of dependencies (342 ?!?).
As far as I can tell, the GHC bug is fixed ... but it does look like someone had a similar problem on Sierra with it 7 weeks ago. Probably not fixed?
@steshaw it's not fixed, as the GHC fix only makes it harder to hit the limit in linker.
In Nix, we have a hack to reexport symbols to never reach the limit in one executable, so that should work with Stack.
I suggest you try out your project on Sierra (High Sierra doesn't change anything) and try to use Nix to provide the linker hack.
Long term solution is for haskell libraries not to use such long paths, now that stack/nix use separate folders and naming doesn't have to account for namespacing.
It’s still broken for me on High Sierra. I use docker container with ubuntu and some rsync-ing to get the job done.
On Sun, Dec 10, 2017 at 06:58 Domen Kožar notifications@github.com wrote:
@steshaw https://github.com/steshaw it's not fixed, as the GHC fix only makes it harder to hit the limit in linker.
In Nix, we have a hack to reexport symbols to never reach the limit in one executable, so that should work with Stack.
I suggest you try out your project on Sierra (High Sierra doesn't change anything) and try to use Nix to provide the linker hack.
Long term solution is for haskell libraries not to use such long paths, now that stack/nix use separate folders and naming doesn't have to account for namespacing.
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/commercialhaskell/stack/issues/2577#issuecomment-350543254, or mute the thread https://github.com/notifications/unsubscribe-auth/ABNscrZrcjU1uAvSLzIUBgwHMorxpRPFks5s-8dhgaJpZM4J546w .
I am running into this as well. Would it be reasonable to use Nix's workaround inside Stack? I am not familiar with Stack's internals, but if anyone thinks that would be a good approach I can investigate it.
Also, perhaps this issue should be reopened?
@asivitz Stack had already done the rpath shortening trick, I think this is what remains as a more permanent fix.
Yikes, I think that's a little more involved than I hoped.
Btw, I tried to make a controlled reproduction case by generating a giant stack project with a bunch of sub-packages, but I couldn't cause the panic. I wonder what I'm missing? https://gist.github.com/asivitz/f4b983b2374a6155ac4faaf9b61aca59
@asivitz I think they need to be dependencies rather than modules? Make a Stack project that depends on acme-everything
and see if that trips it.
They are dependencies actually. It's a top-level library that depends on 400 sub-packages. It's pretty weird because when I looked at the output for my failure it was around 300 deps, and this one has 400 (and longer filenames also) and it doesn't trip it.
@asivitz Oh my bad, I only glanced at the script. I've found reproducing the failure with Stack to be inconsistent in this way too, FWIW.
Did you try executing it or using some Template Haskell in it? I think you can force a linker failure during compile-time if you use TH.
@bitemyapp Nope! Didn't try that. I'll give it a shot, thanks!
@asivitz AIUI this is the runtime linker in the Darwin kernel that is imposing the kilobyte limit on the paths. macOS doesn't actually permit static linking at all. Given that, the only way to trip it that I'm aware of is for TH to force runtime linking at compile time or to run the program.
Ah, ok that's super helpful, thanks. I added some TH and am now able to reproduce it reliably. I updated the gist.
We have worked around this issue by following in the Nix folks' footsteps and using a wrapper script around ld
to recursively subdivide the dependencies into a tree of re-exporting delegate libraries.
The script, an example using @asivitz's repro, and more info about this issue is available here: https://github.com/Simspace/ld-wrapper-macos
Hope this helps!
I wonder: would it be possible to modify the GHC settings
file to use this wrapper for all builds (rather than having to add the flag to every project)? If so, it would be possible to have Stack use patched GHC bindists on macOS that includes this fix.
Sure, but you have to add -fuse-ld=ld-wrapper-macos.sh
to the C compiler flags
section of the settings
file, you can't simply set the ld command
option.
edit: for stack, the path for the settings
file looks like ~/.stack/programs/x86_64-osx/ghc-8.2.2/lib/ghc-8.2.2/settings
So we could, in theory, fix this for macOS users by providing patched bindists that include the wrapper script and a modified configure
to update settings
to use it on macOS >= 10.12. I'm always hesitant about this sort of thing, because it's one more thing we have to support going forward and would be best fixed by the GHC team themselves, but in this case there are enough macOS users and this causes enough pain that it might be worth doing.
I've changed my settings
to have the following flags and it built my project on High Sierra. Thank you!
("C compiler link flags", " -m64 -fuse-ld=ld-wrapper-macos.sh")
:sparkles: This is an old work account. Please reference @brandonchinn178 for all future communication :sparkles:
@steshaw I'm getting
clang: error: argument unused during compilation: '-fuse-ld=ld-wrapper-macos.sh' [-Werror,-Wunused-command-line-argument]
I'm on stack 1.6.5. Have you seen this problem?
Just ignore that warning instead of making it fail with -Werror
; the warning comes from clang, who noticed that you gave it linking flags in a clang invocation which doesn't perform any linking. This in turn occurs because adding -fuse-ld=ld-wrapper-macos.sh
to C compiler link flags
causes ghc to add this flag to all of its invocations of clang, both those which perform linking and those which don't.
@brandon-leapyear @gelisam I don't see that error. Perhaps it's because I updated C compiler link flags
rather than C compiler flags
in ~/.stack/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/settings
.
I do get some warnings during the linking stage like this:
/Users/steshaw/.stack/programs/x86_64-osx/ghc-8.0.2/lib/ghc-8.0.2/include/rts/storage/ClosureMacros.h:552:32: error:
warning: macro expansion producing 'defined' has undefined behavior [-Wexpansion-to-defined]
#if ZERO_SLOP_FOR_LDV_PROF && !ZERO_SLOP_FOR_SANITY_CHECK
^
...
9 warnings generated.
Seems those can be safely ignored.
GHC 7.10.3
Xcode 8.0 GM, macOS Sierra