TLDR
Relative paths in command line flags --extra-include-dirs, --extra-lib-dirs and their counterparts in cabal.project resolved against each package's root which causes surprising and user-unfriendly build errors.
Details
I created following repository to reproduce: https://github.com/random-random-stuff/test-cabal-relative-extra-include-and-lib-dirs and guide the following explanation.
I have a package cabal-test-dependency which wraps a foreign library. When building it a cabal_test_foo.h header and a libcabal_test_foo.so file must be available.
Then I have my main package cabal-test-main that uses cabal-test-dependency:
packages:
cabal-test-main.cabal
../dependency/cabal-test-dependency.cabal
The directory with cabal-test-main is where I, as a user, is working in and is where I’m calling cabal from.
I have local copy of .h and .so that are needed to complete the build in root of cabal-test-main package under directory deps (in this though experiment a user puts .so where needed beforehand like here).
$ ls deps/
cabal_test_foo.c cabal_test_foo.h libcabal_test_foo.so
Now from cabal-test-main root I’m calling cabal build and pass deps/ directory so that dependency would build but the build fails:
$ cabal build --extra-lib-dirs deps --extra-include-dirs deps
Resolving dependencies...
Build profile: -w ghc-9.14.1 -O1
In order, the following will be built (use -v for more details):
- cabal-test-dependency-0.1 (lib) (first run)
- cabal-test-main-0.1 (exe:main) (first run)
Configuring library for cabal-test-dependency-0.1...
Warning: [unknown-directory] 'extra-lib-dirs: deps' specifies a directory
which does not exist.
Warning: [unknown-directory] 'include-dirs: deps' specifies a directory which
does not exist.
Error: [Cabal-4345]
Missing dependency on a foreign library:
* Missing (or bad) header file: cabal_test_foo.h
* Missing (or bad) C library: cabal_test_foo
If the header file does exist, it may contain errors that are caught by the C compiler at the preprocessing stage. In this case you can re-run 'Setup configure' with the verbosity flag -v3 to see the error messages.
Error: [Cabal-7125]
Failed to build cabal-test-dependency-0.1 (which is required by exe:main from cabal-test-main-0.1). The failure occurred during the configure step.
The errors are
Warning: [unknown-directory] 'extra-lib-dirs: deps' specifies a directory
which does not exist.
Warning: [unknown-directory] 'include-dirs: deps' specifies a directory which
does not exist.
apparently because deps directory is being resolved under root directory of cabal-test-dependency package where it does not exist.
If I specify absolute paths, e.g. cabal build --extra-lib-dirs "$(pwd)/deps" --extra-include-dirs "$(pwd)/deps" then build succeeds.
It seems like relative paths should work too and should resolve against where user is currently situated. For command line options that would be the current working directory and for cabal.project options it seems the location of the cabal.project file should serve as a root to resolve relative paths against.
According to #2641 the relative paths for extra-include-dirs and extra-lib-dirs are allowed but neither that PR nor manual provide concrete information as to how relative paths are resolved.
Current behavior seems like an artefact of the implementation where extra-include-dirs and extra-lib-dirs are added to each package’s include-dirs and library-dirs respectively and only then are resolved in each package’s context.
It does not seems like a good idea that that standing in package A and specifying a path relative to A’s root, e.g. foo/ results in dependent package B getting a relative foo/ directory in any part of its package description. While looking at A the user has no visibility under package B and what directories it contains.
System information
- Operating system - Linux x86_64
cabal - 3.17.0.0, built from master, ghc - 9.14.1
TLDR
Relative paths in command line flags
--extra-include-dirs,--extra-lib-dirsand their counterparts incabal.projectresolved against each package's root which causes surprising and user-unfriendly build errors.Details
I created following repository to reproduce: https://github.com/random-random-stuff/test-cabal-relative-extra-include-and-lib-dirs and guide the following explanation.
I have a package
cabal-test-dependencywhich wraps a foreign library. When building it acabal_test_foo.hheader and alibcabal_test_foo.sofile must be available.Then I have my main package
cabal-test-mainthat usescabal-test-dependency:The directory with
cabal-test-mainis where I, as a user, is working in and is where I’m calling cabal from.I have local copy of
.hand.sothat are needed to complete the build in root ofcabal-test-mainpackage under directorydeps(in this though experiment a user puts.sowhere needed beforehand like here).Now from
cabal-test-mainroot I’m callingcabal buildand passdeps/directory so that dependency would build but the build fails:The errors are
apparently because
depsdirectory is being resolved under root directory ofcabal-test-dependencypackage where it does not exist.If I specify absolute paths, e.g.
cabal build --extra-lib-dirs "$(pwd)/deps" --extra-include-dirs "$(pwd)/deps"then build succeeds.It seems like relative paths should work too and should resolve against where user is currently situated. For command line options that would be the current working directory and for
cabal.projectoptions it seems the location of thecabal.projectfile should serve as a root to resolve relative paths against.According to #2641 the relative paths for
extra-include-dirsandextra-lib-dirsare allowed but neither that PR nor manual provide concrete information as to how relative paths are resolved.Current behavior seems like an artefact of the implementation where
extra-include-dirsandextra-lib-dirsare added to each package’sinclude-dirsandlibrary-dirsrespectively and only then are resolved in each package’s context.It does not seems like a good idea that that standing in package
Aand specifying a path relative toA’s root, e.g.foo/results in dependent packageBgetting a relativefoo/directory in any part of its package description. While looking atAthe user has no visibility under packageBand what directories it contains.System information
cabal- 3.17.0.0, built from master,ghc- 9.14.1