4 ms·
The new improvements to Cabal have been super nice of late, but one thing I _really_ wish Cabal would do is allow for multiple versions of a library to be used
by bjz_ 6y ago
The new improvements to Cabal have been super nice of late, but one thing I _really_ wish Cabal would do is allow for multiple versions of a library to be used in the same project. Having to satisfy a single library version is incredibly frustrating, and the solver errors are incredibly confusing. This is especially confusing when it complains about a library deep in your dependency graph being in conflict.
Ultimately the failure mode means that you can't build your package and are blocked until a fix is made upstream, where as with a package manager like Cargo you can still build your project. The downside is that you have a duplicate in your dependency graph - but this can be fixed upstream in an asynchronous fashion.
- ulrikrasmussen 6y agoI agree that this is a pain point. I not familiar with Cargo and would like to know how this actually works. Don't you risk binary incompatibility issues because the same symbols are occupied by different versions of the same package? For example, what if my package depends on A(v1.0) and B, B depends on A(v2.0), and furthermore B exposes a type from A(v2.0) in its API? Does the package manager distinguish internal dependencies from dependencies that are exposed in the API of the package?
- bjz_ 6y agoI think Rust gives the symbols unique hashes for each crate version to avoid this. See this answer on Stack Overflow for more information: https://stackoverflow.com/a/51722134 https://stackoverflow.com/a/51722134 - not sure if there is a better reference document though. You sometimes get weird errors like expected `A` but found `A` in the unusual event that you actually run into this, but this is probably something that could be fixed.
- ulrikrasmussen 6y agoThank you for the link, that clarified it for me. It seems that it requires compiler support to do it in the same way as Rust does it, but I like that approach better than complicating the package definitions with two types of dependencies. Reading that post also reminded me of the Unison language [1] which would even allow the same type from different versions of a library to be identified as the same if it wasn't altered. It does this by identifying every type and function by the hash of their respective definitions. [1] https://www.unisonweb.org/ https://www.unisonweb.org/
- PhineasRex 6y agoWhat's interesting is that GHC absolutely supports this already. If you manually link your projects you can use multiple versions of the same library in your project. Cabal doesn't support multiple versions of the same library.
- Vosporos 6y agoYou might be interested in package-qualified import, for overlapping types and symbols: https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#package-qualified-imports https://downloads.haskell.org/~ghc/latest/docs/html/users_gu...
- thepratt 6y agoUsing bazel as a build tool (on top of cabal) allows you to provide patches or modifications to found versions.
- bjz_ 6y agoWhat happens if you are building a library that is published to Hackage?
- thepratt 6y agoYes, you can apply patches from (mostly) any source. There'd be a slightly different markup/setup depending on how you popoulate your stackage/hackage - nix or http_archive (stack_snapshot). If you're modifying something from an upstream it'd be best to reference it as vendored, e.g. `@org//:package` and not the stack populated version `@stack//:package`. This is how you'd do it pulling from git directly (there's a whole lot more involved if this were to be done for a stackage package). http_archive( name = ..., build_file_content = """ load( "@org//bazel:defs.bzl", "pai_haskell_library", ) pai_haskell_library( name = ..., version = ..., srcs = glob(["src/**/*.hs"]), stackage_deps = [...], visibility = ["//visibility:public"] ) """, patch_args = ["-p1"], patches = [ "//dir:git-patch-file", ], sha256 = "...", urls = ["https://github.com/org/repo/archive/1.0.0.0.tar.gz"], )
- ghostwriter 6y agoSource Repository stanzas and github's fork button (or similar buttons on other platforms) help me to avoid any blocking coming from upstream packages[1]: [1] https://www.haskell.org/cabal/users-guide/nix-local-build.html#specifying-packages-from-remote-version-control-locations https://www.haskell.org/cabal/users-guide/nix-local-build.ht...