cabal icon indicating copy to clipboard operation
cabal copied to clipboard

Cabal provides additional runtime library paths to executables it runs

Open abailly-iohk opened this issue 1 year ago • 11 comments

When building a Haskell project that uses foreign libraries, Cabal allows one to specify additional compile-time paths that will be passed to the linker to produce libraries and executables. This is particularly convenient when those libraries are bundled as part of the Haskell project as one can use package-relative paths which are resolved by Cabal. In a recent project which mixes Haskell and Rust, we have been using a custom Setup.hs to compile the Rust library and link it to the Haskell test executable.

However, this does not help when running the executable with cabal test: If the library is not installed in a location the system dynamic loader already knows, it won't be found. The usual workaround is to set some environment variable, eg. LD_LIBRARY_PATH on linux, or DYLD_FALLBACK_LIBRARY_PATH on Mac OS X, but this is of course unwieldy esp. as one needs to set those paths either absolute or relative to the directory from which the executable is run, which in a multi-package project, can be different from the directory one runs the command.

Therefore, it would be great if cabal could provide this information directly to the executable it runs, for example through an extra-lib-dir field. The build-tools-depend mechanism for tests and benchmarks provides something similar for runtime dependencies which are executable.

abailly-iohk avatar Oct 05 '23 05:10 abailly-iohk

If that feature proposal makes sense, I would be happy to try to implement it myself with some guidances on where to look at :)

abailly-iohk avatar Oct 05 '23 05:10 abailly-iohk

It makes sense to me.

mouse07410 avatar Oct 05 '23 10:10 mouse07410

@abailly-iohk: thank you very much for the proposal. I remember a recent ticket with a similar (?) problem and some discussion about it. Was it your ticket? Could you perhaps find and link some related tickets here and perhaps ping some most active participants so that we can discuss with more context?

Mikolaj avatar Oct 05 '23 10:10 Mikolaj

To be clear, do you propose only that one specifies a string in .cabal that cabal appends to the invocation of the test binary when doing cabal test? Or something more general? I must be missing something, because you can already do cabal test foo --test-options=bar

Mikolaj avatar Oct 05 '23 10:10 Mikolaj

Was it your ticket?

No, this is my first issue here ever ;)

Could you perhaps find and link some related tickets here and perhaps ping some most active participants so that we can discuss with more context?

Sure thing. I did a quick search but could not find anything, will try again

abailly-iohk avatar Oct 05 '23 10:10 abailly-iohk

To be clear, do you propose only that one specifies a string in .cabal that cabal appends to the invocation of the test binary when doing cabal test?

No. I am proposing to configure in the cabal file(s) (could be also done in the cabal.project perhaps?) extra paths that will be used when executing tests and benchmarks (and perhaps other exe components too) to resolve dynamic libraries. The use case is a Haskell project that also compiles a foreign DLL that is required to be found at runtime in tests

abailly-iohk avatar Oct 05 '23 10:10 abailly-iohk

Pardon my clueless questions. :)

could be also done in the cabal.project perhaps?

Yes, makes sense.

extra paths that will be used when executing tests

But cabal test foo --test-options=bar adds bar to the commandline of the test binary when executing it, right?

and benchmarks (and perhaps other exe components too)

Oh, ok, so it's more general. Probably better that way. We already have ghc-options: "-with-rtsopts=bar" that does a subset of this. Am I closer to the mark now?

Mikolaj avatar Oct 05 '23 11:10 Mikolaj

Wouldn't one way to achieve this to modify the rpath of the executable to point to the build location of the rust library?

A further question is how any downstream dependencies work, as it doesn't appear you install the built rust library anywhere (the copy hook is not modified).

mpickering avatar Oct 05 '23 11:10 mpickering

The use case of the rust lib does make things more complicated.

I fear it means that there is not a single value to use for --extra-lib-dirs because there's one location for the local build tree instance, and another location for the final installed location. The existing --extra-lib-dirs feature is designed for using things that are already installed, not for things within the build tree.

dcoutts avatar Oct 05 '23 11:10 dcoutts

Sure thing. I did a quick search but could not find anything, will try again

Thank you. But you may be right there is no precedent --- now I remember the issues I had in mind were about link-time library paths, which is a different thing, unless what Matthew says about RPATH relates the two.

Mikolaj avatar Oct 05 '23 11:10 Mikolaj

Wouldn't one way to achieve this to modify the rpath of the executable to point to the build location of the rust library?

The rpath approach makes sense for the installed locations of a foreign lib, but isn't appropriate for finding a lib that lives somewhere within the build tree. For running things in the build tree, that need to find other things in the build tree, one wants to use LD_LIBRARY_PATH.

dcoutts avatar Oct 05 '23 11:10 dcoutts