Change:
fails to build on with the following errors: Recent hydra builds also fail: Steps to reproduce the behavior: should install and be available. Please run and paste the result. Maintainer information:
See also for the same issue. Seems like haskell packages with separate outputs just don't work on for some reason, likely codesigning?!
please can someone look into this issue? I literally have no way of debugging this.
I attempted to build niv with and still get the same error. I haven't touched before and I'm extremely unfamiliar as to how the outputs are created and how the relate to eachother in a way that creates a loop.
Setting ( not ) worked for me, but I'm also quite unfamiliar with how things work so it was a bit of a guess.
Well, that's an obvious workaround, what I'm more interested in is why do outputs in haskell packages create cyclical dependencies between outputs only on .
Which references are causing the cycles? Is it something like an extra codesigning binary in bin which is also used from out?
I'm seeing this issue in a Nix shell with and . I'll look into this a little more in the evening but at least to me it seems like this affects more than just a single package
Yes, every haskell package with a separate output is broken at the moment. Would be great to find out what actually causes the reference cycle.
I think we should change the title of the issue to reflect the broader scope. I tried bisecting on my M1 machine earlier but build times are brutal for all the Haskell machinery. I might have to try a different approach later on. I did check if references anything from the lib output but it did not. Which is strange because then what's responsible for the circular reference? Anyhow, will look into this more later.
I can upload the failed build directory of ormolu (a failing haskell package) being built on aarch64-darwin if that helps?
This is of limited use because it doesn't really tell you what is wrong in the installed outputs. I'd expect that the references get introduced in which is after installation… I guess you could grep for the value of and in the build directory and see if it turns up something interesting. would be useful right about now…
If I do: I can see the output directories in the store: Those directories do have the built binaries in libs in there. Would that be of more use? i.e, would the have occurred at that point?
I've been doing a bit more digging on this and after running , I found the following: I'm not too sure how these references are found, but I presume that it's doing something similar to running across the binary and looking for a valid nix store hash. If that's the case. The reference from to : The reference from to : Having a reference from -makes sense, the more curious case is the reference from -. Strangely, it looks as though it's only referencing the folder, not the actual executable.
Actually the -reference is probably the anomaly since the executable should be statically linked (against the haskell libraries, system deps are linked dynamically) and thus contain no reference to the library. I wonder how the reference comes into existence…
Indeed, you are correct. I've just checked on my x86darwin system and there is a reference from -but no reference from -, so it looks as though the binary is the problem. I've uploaded it here for other people to take a look at, but I'll see if I can figure out where the reference is coming from. The bad references can be seen with . Update: After throwing the binary into ghidra to see where the referencies are coming from , it looks as though they are values of the haskell functions: : <img width="994" alt="Screenshot 2021-12-04 at 08 32 40" src="https://user-"These symbols don't exist in the binary.
Maybe we can just make bin output a no-op on aarch64-darwin until it's fixed?
I'm against this for the simple reason it eliminates any incentive to fix the bug. Separate outputs are quite important as they significantly reduce the closure size: Haskell binaries are statically linked, so the download of the libraries plus the entire dependency closure is unnecessary if you only want to execute a tool. Given Rosetta, there is a decent enough workaround for the failing builds.
That's the incentive :)
cc is this a bug in GHC dead tree elimination for arm/darwin?
Note: does include the paths module: , It looks like most packages use to get the version of the package. Same for : Update: I've confirmed that the module is the issue. I've successfully built after applying the following patch:
I just wanted to start debugging this using and using this flake I'm now getting on my M1 machine. Notice that the error is talking about the output. more specifically from the file in question: I get the same behavior when building the package directly from Nixpkgs at
Is there any workaround?
Thank you,
did you reconsider fixing this with a workaround? Many basic packages like niv are failing for aarch64-darwin users and having a big closure is a lot better than just plain build failure.
My point still stands, but I suppose I could live with a workaround, as there doesn't seem to be anyone with the time to find a fix. It'd be great if someone could confirm this is an issue with GHC's unused symbol elimination and report this to upstream, though.
I did mention this on GHC's IRC channel and it looks like it's a problem to do with the LLVM back-end. once we move to NCG, it looks like this problem will be fixed. Another solution that was suggested is to use Cabal's option. That prevents paths from being set in the phantom module. I'm not too sure how to enable this option in the nix haskell machinery though?
It can be done with in configuration-, but it doesn't seem to work: It doesn't like the fact that niv-0.2.19-bin/bin is not inside niv-0.2.19/.
I think that relocatable only makes the paths relative, which is very much not a valid solution for our case. I think the "correct" option would be to patch Cabal such that the non-bin path functions are never generated in the paths module on split builds. This would cause a compile-time error if the application actually uses them (in which case, the correct solution is to disable split building for that package), otherwise it would have no effect, and would solve our issue here, regardless of which optimisations do or do not occur. The path-generating code to patch is in (or ).
I'm fairly certain we should add a flag to to not generate Path's modules if not explicitly requested. It's an absolute misfeature, and one of the few places that completely break relocatability. We'd likely want to either outright disable: or put it behind some flag .
I don't know what's generating suffixes. But the LLVM backend on darwin does not have dead code elimination. It's imply can't as darwins dead code elimination is done through the directive. However we can't get LLVM to emit proper code to retain prefix data, which we use due to Tables Next To Code in GHC. This is one of the mismatches between what GHC needs and what LLVM provides. We could probably try to fix this up by hand-injecting extra symbols to tie prefix data to their functions, but mangling assembly is bad enough and now starting to do this across multiple architectures is even worse. So yes, this will get better with the aarch64 NCG, but it's a generic issue on darwin if you use the LLVM codegen. The x8664-darwin LLVM codegen will have the same issue.
So let's disable bin splitting for aach64-darwin and revert that once we have GHC 9.2 as the default?
the issue here is that all three problem packages do actively use the paths module! The thing is, they use it solely to get their own version number, not to access any problematic paths. (This is why I suggested patching out generation of the specific variables)
yes, I fully agree that patching it out is the correct solution. But the better solution would be to outright prevent packages from doing this kind of garbage.
Let me reiterate my opinion: the module was and is a bad idea and should never have been conceived. It should be outright removed and packages need to be fixed properly.
What's the "fixed" way to get your own version number?
We could probably stick it into ?
Why not? Referencing certain paths is completely fine, e. g. the output is often necessary to reference. That unused values end up in the binary is the problem. In any case, seems like we are stuck with this problem until 9.2.1 (which is going to be quite some time for us).
2, 9.2.1 is a dud.
if you need to access , build a wrapper script around your executable, and configure your path through some env var. If you need to look it up relative to your executable, we can do this today on most operating systems. GHC has the same issue, it needs to lookup it path. Baking in paths breaks relocatability. It's a bad, bad, idea. The only case where I have some sympathy for this is again operating systems that can't find their executables absolute path. If you are a distribution that ends up splitting bin and lib or share apart anyway, you'll need to pass that information to the executable one way or the other. A common way to do this is to wrap the executable in a shell script with an ENV var telling the executable where to find it's data dir. Again, the module is a terrible solution.
I've been looking at this today and I've got a patch that prevents cabal creating the problematic symbols above. GHC built fine and I can confirm this fixes the build for . However the following packages couldn't be built: This fails on building as it has a directive in the cabal file. Since we've removed the generation of , this causes a compilation failure with . This fails on building for the same reason above. In this case, it's when is trying to emit a template. While this does fix the build for , it does break the build for other packages. The only other thing that I could think of doing is creating a dummy value for so that it does exist, but will fail when it's actually used.
It's crucial that data dir works and the reference incurred due to it is unproblematic.
Shouldn't the contents of be made its own derivation, so the derivation can reference it (and only it)?
They are installed to a separate output.
In which case, I think we're stuck since the data dir is one the symbols creating a cycle.
Not necessarily, data files are installed to a different output, so I guess we could try something that compares the string to the prefix and only emits it if they difer (or rather only emits paths if they are different from the prefix).
I've got a partial fix at .
Guess talking about this in detail on matrix nix Haskell channel and not brining that discussion back left out some details. the approach is good. You can keep all directives, just modify the call to just emit the EnvVar lookup. Then patch the install phase to remit a wrapper around the binary setting the absolute path for the data dir via the env var.
I would not like that, it's a far to invasive change just to work around that GHC is missing dead tree elimination in the default backend for a single platform. This would also require to add a ton of new stuff to the generic builder and we still wouldn't eliminate the reference cycle for free.
just to be clear here. Ghc doesn't do any dead code elimination by itself. It relies on the linker to do so and tries to produce code that's kinda dead-strippable. But there is no major logic in GHC to do DCE outside of split-sections for ELF and subsectionsviasymbols for Mach-O. The right fix imho is to fix cabal to not be an utterly idiotic tool with its stupid Paths_ module. Relying on DCE to fix your broken code is not the right strategy. Fix the broken code from the get go would be.
To reiterate my point: relying on magic/heuristics in the tail end of the pipeline to paper over sloppiness somewhere in the front and middle part of the pipeline is just bad engineering.
We package GHC and last time I checked it is far from our responsibility to “Fix the broken code from the get go would be”. We merely rely on behavior GHC plus whatever linker exhibit for all decently supported targets.
I've now got a patch that removes the hard-coded paths and just relies on environment variables for finding the symbols exposed by . As a compromise, we could use that without any modificaiton to the generic builder and just accept the fact that Haskell packages that use in their cabal files will be broken (which AFAICS isn't that many), but at least we can get packages built. Note: this approach does allow to build and function on my machine.
Honestly then it's still a better solution to disable separate outputs completely for that target.
Agreed.
I’ve been wanting to patch cabal so that it only generates the symbol in by default, and then have overrides in nixpkgs that we can selectively enable for packages that also need to access the symbols which expose paths like . The we won’t run into these accidentally in the future. Maybe somebody else wants to do that?
I was working on that approach, similar to what suggested. I'm removing bits of the module that hard-code paths and get these values via env-vars. Then use wrappers around any binaries that are outputted to set the appropriate environment.
Although, one major downside is that we'd have to patch every new version of GHC to remove the bits of the module generation that we don't want.
iirc pandoc is one of the packages depending heavily on data-dirs, and we certainly wouldn’t want to break that. So one way or another, we are going to have to patch cabal to make Paths_ generation configurable (defaulting to in nixpkgs and to in cabal itself).
Pretty sure that module hasn’t changed in a few years.
We can always try to upstream stuff. Getting stuff in GHC should be fairly easy, getting stuff into Cabal might require a bit more cajoling. I still think Version should be set via , e.g. made available as some VERSION value. We already have VERSION values in the cabal macros. It might already be in there. So just use + the version value from the cabalmacros, instead of reaching into the Paths module. Again Paths module is wrong on so many levels.
Here is an example application that does exactly that without any of the junk.
Just for completeness sake: this is what's in the
Agreed that approach seems the most sensible going forward, however that would be a breaking change for most current packages, right? What's the best approach to solve this particular issue? I think we've got two options: Disable separate build outputs on aarch64-darwin for the time being Look at eliminating the paths symbols and set them via environment variables (I have a patch that's nearly there for this).
That's an oversimplification. It is irrelevant whether you use env vars or not, you rather need to somehow disable emitting references (to at least ) only if they are not needed. Using the env var approach would actually make it impossible to catch a omitted reference needed by a package at build time. The funny thing is that, with how things currently are (on non-), we get this for free. With the proposed change we need to work really hard to figure everything out. A robust solution would in theory be to convert etc. to macros, so unused paths would never leak into an object file, but that's not really possible to do in a non breaking fashion.
Right, I see. Since the env-var approach makes no distinction whether the reference is used or not, it's always set. Whereas we get this 'for free' at the moment with DCE?
Exactly. I think we could make a hack in the module generation, using that the only "problematic" reference is and the prefix is always set to : We could not emit the things for paths that are equal to or below if is not below . In theory, it should not emit any problematic references anymore and fail if there would be a reference cycle with or without DCE. But this is a hack, really, and specific to nixpkgs.
Sounds good. I'll try and implement something in the next few days.
Summary: cabal provides a rather bad module; which hardcodes paths at build time. We rely on dead code elimination, to strip unused path symbols from binaries. On darwin, when using GHC's LLVM backend, dead code elimination is disabled, and thus we end up with unstripped binaries, that still contain those references. A lot of packages use the module for info, which they could equally well just get from the file. Building wrapper scripts with all path data is equally bad. What we really want: if you need a certain feature from cabal, you'd have to explicitly declare that. But even better, there should be no module to begin with. If an application needs to reach for a directory, there should be a library that tries to locate that library relative to the executable on platforms that support this (e.g. in the build tree structure that cabal produces). This should be overridable with an evn var; if the application needs a path value (and a poor mans hack to get this info is to grep the source code for the relevant getDir function) during install, a wrapper script is produces that contains that path (or one specified during the configure phase, which I believe cabal already supports) as an env var. Anyway, I'll leave it at that, but maybe that's helpful for someone reading just the end(?) of this thread.
I've updated with suggestion. This fixes the build for all the problematic programs listed here.
I don’t think this is an actually viable solution to be honest. Bazel does something similar with their libraries, which means they have to implement the same library for every single language (just . And* they don’t have the problem of having different file setups (which would break Haskell’s neck since every distro can make arbitrary choices and heuristics suck!
ghc has relative lookup code in its codebase. You can use ghc without the retarded wrapper files on most architectures as long as you keep bin and lib sibling directories. If you don't, you need the wrapper. I did not intent a general library for relative lookup. I meant a haskell library, to prevent people from implementing the same functionality in broken ways over and over again and to enforce some coherence.
Regarding the pull requests and this will be fixed soon. But I am curious to understand how to implement this workaround: I have a basic provided on my project, and I don't have any clue on how to do this fix... Any help/explanation would be nice.
Why is this issue closed? I am still having the trouble (on for example): error: cycle detected in build of '/nix/store/gsm34npdhjpzn1kl7drd1k118mmwvqg5-niv-' in the references of output 'bin' from output 'out'
Update nixpkgs, according to Hydra this is no longer an issue on master.
As in the PR with the fix, the patch for Cabal will need to be ported to GHC 9.0.2 (which also uses the LLVM-based backend), as that has become the default Haskell compiler on now. Anyone interested in implementing and testing the change?
The default version is definitely 9.0.2, you seem to be using the (stale) flake instead of the local checkout you updated.
Oops, my bad. Just noticed that! Indeed it is the right version!
Good news, I've just had a look and the patch to appliles cleanly on 9.0.2 so it looks like we'll be able to reuse the same patch. I'm just building now to confirm.
GHC 9.0.2 and compiled with no problems. PR is in .
FTR, this issue reoccurs in 's ghcid, etc.
Yes, the patch by hasn't been applied to 9.2.3. Feel free to try if it applies, test the resulting GHC derivation and create a PR.
I played around with the patch on 9.2.3, and it seems like it will need some reworking. Specifically, changed the implementation in Cabal to use some jinja-like templating library, so at the very least the logic needs to be translated to the appropriate lines of this file. I might take a crack at this over the weekend. e: wonder if it would be worthwhile reopening this issue or opening a new one to track the ghc923 failure, since it won't be totally trivial
Unfortunately, I think I messed something up, as building worked, but no output was included. Sharing this here in case anyone can clean this up and get it working quicker than I can. e: hold on, i think i made a mistake, i should have tried , which works! also works. I'll see if I can get a PR up today.
The issue reoccurs:
Yes, we'll have to finish and merge which requires a completely new patch to .
For those wondering, the workaround meanwhile is to override your haskell package set as follows: See
On linux this works because dead code elimination takes care of pruning unused constants in On macOS it's most likely because of not enough DCE, I've only found in ghc about this. cc for help
Building Haskell Language Server with GHC 9.2.5 runs into the same issue. Does your reference cycle patch still work Maybe I'm doing something wrong :sweat_smile: The overlay (imported by my ), trying to use code:
"Killed" in the error message suggests that the kernel killed the build process? Out of memory? By the way, for anyone that uses , I have just created a module making it easier to incorporate the workaround for this bug in their Haskell projects:
Hi thank you. Yes, it seemingly continuously rebuilds the plugins for until my computer runs out of memory and kills the build.
I revived/reworked the PR to workaround this for 9.2.x releases:
Does this fix also work on ?
I haven't tested it myself, you could check out my PR and try applying the patch to the appropriate file or whatnot

Discussion:
stdenv.mkDerivation rec { name = "vlc-${version}"; <del> version = "2.0.3"; </del> <ins> version = "2.0.4"; </ins> src = fetchurl { url = "http://download.videolan.org/pub/videolan/vlc/${version}/${name}.tar.xz"; <del> sha256 = "1lnjfpizgp8slj6i4fgk5wld6nfw08wfhkb1i1dvzbhmfigq1agv"; </del> <ins> sha256 = "1dixankckfxf8xixfc32rc9mfsv6mx2lk5h13ym8bp4dsk86w1jf"; </ins> }; buildInputs =