Skip to content

Local component build-tool-depends should work with multi-repl #11850

Description

@fendor

Describe the bug

See bug report #10626

The issue is that trying to load a component into a GHCi repl while also depending on it via buld-tool-depends causes hard to decipher errors.

To Reproduce
Steps to reproduce the behavior:

$ mkdir cabal-build-tool-depends-issue
$ cd cabal-build-tool-depends-issue
$ cabal init --libandexe -n --no-comments --tests
# Change .cabal file to add `build-tool-depends:  cabal-build-tool-depends-issue:cabal-build-tool-depends-issue` to test stanza
$ cabal test --enable-tests
...
Test suite cabal-build-tool-depends-issue-test: RUNNING...
Test suite not yet implemented.
Test suite cabal-build-tool-depends-issue-test: PASS
Test suite logged to:
/home/hugin/Documents/haskell/cabal-build-tool-depends-issue/./dist-newstyle/build/x86_64-linux/ghc-9.10.3/cabal-build-tool-depends-issue-0.1.0.0/t/cabal-build-tool-depends-issue-test/test/cabal-build-tool-depends-issue-0.1.0.0-cabal-build-tool-depends-issue-test.log
1 of 1 test suites (1 of 1 test cases) passed.
$ rm -r dist-newstyle # delete the build directory
$ cabal repl --enable-multi-repl --enable-tests all
Resolving dependencies...
Build profile: -w ghc-9.10.3 -O1
In order, the following will be built (use -v for more details):
 - cabal-build-tool-depends-issue-0.1.0.0 (interactive) (lib) (first run)
 - cabal-build-tool-depends-issue-0.1.0.0 (interactive) (exe:cabal-build-tool-depends-issue) (first run)
 - cabal-build-tool-depends-issue-0.1.0.0 (interactive) (test:cabal-build-tool-depends-issue-test) (first run)
Configuring library for cabal-build-tool-depends-issue-0.1.0.0...
Preprocessing library for cabal-build-tool-depends-issue-0.1.0.0...
Configuring executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
Preprocessing executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
Building executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
<command line>: cannot satisfy -package-id cabal-build-tool-depends-issue-0.1.0.0-inplace
    (use -v for more information)
Error: [Cabal-7125]
Failed to build exe:cabal-build-tool-depends-issue from cabal-build-tool-depends-issue-0.1.0.0 (which is required by test:cabal-build-tool-depends-issue-test from cabal-build-tool-depends-issue-0.1.0.0).
`cabal-build-tool-depends-issue.cabal`
cabal-version:      3.8
name:               cabal-build-tool-depends-issue
version:            0.1.0.0
-- synopsis:
-- description:
license:            NONE
author:             fendor
maintainer:         fendor@posteo.de
-- copyright:
build-type:         Simple
extra-doc-files:    CHANGELOG.md
-- extra-source-files:

common warnings
    ghc-options: -Wall

library
    import:           warnings
    exposed-modules:  MyLib
    -- other-modules:
    -- other-extensions:
    build-depends:    base ^>=4.20.2.0
    hs-source-dirs:   src
    default-language: Haskell2010

executable cabal-build-tool-depends-issue
    import:           warnings
    main-is:          Main.hs
    -- other-modules:
    -- other-extensions:
    build-depends:
        base ^>=4.20.2.0,
        cabal-build-tool-depends-issue

    hs-source-dirs:   app
    default-language: Haskell2010

test-suite cabal-build-tool-depends-issue-test
    import:           warnings
    default-language: Haskell2010
    type:             exitcode-stdio-1.0
    hs-source-dirs:   test
    main-is:          Main.hs
    build-tool-depends:  cabal-build-tool-depends-issue:cabal-build-tool-depends-issue
    build-depends:
        base ^>=4.20.2.0,
        cabal-build-tool-depends-issue

Expected behavior

In my opinion, this should succeed. In fact, it will succeed if you build the executable before running cabal repl --enable-multi-repl --enable-tests all (hence we deleted the dist-newstyle before running it).

So, this works:

$ cabal build tests --enable-tests
$ cabal repl --enable-multi-repl --enable-tests all
Resolving dependencies...
Build profile: -w ghc-9.10.3 -O1
In order, the following will be built (use -v for more details):
 - cabal-build-tool-depends-issue-0.1.0.0 (interactive) (lib) (configuration changed)
 - cabal-build-tool-depends-issue-0.1.0.0 (interactive) (exe:cabal-build-tool-depends-issue) (configuration changed)
 - cabal-build-tool-depends-issue-0.1.0.0 (interactive) (test:cabal-build-tool-depends-issue-test) (configuration changed)
Configuring library for cabal-build-tool-depends-issue-0.1.0.0...
Preprocessing library for cabal-build-tool-depends-issue-0.1.0.0...
Configuring executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
Preprocessing executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
Building executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
Preprocessing executable 'cabal-build-tool-depends-issue' for cabal-build-tool-depends-issue-0.1.0.0...
Configuring test suite 'cabal-build-tool-depends-issue-test' for cabal-build-tool-depends-issue-0.1.0.0...
Preprocessing test suite 'cabal-build-tool-depends-issue-test' for cabal-build-tool-depends-issue-0.1.0.0...
GHCi, version 9.10.3: https://www.haskell.org/ghc/  :? for help
[1 of 5] Compiling Main             ( /home/hugin/Documents/haskell/cabal-build-tool-depends-issue/test/Main.hs, interpreted )[cabal-build-tool-depends-issue-0.1.0.0-inplace-cabal-build-tool-depends-issue-test]
[2 of 5] Compiling MyLib            ( /home/hugin/Documents/haskell/cabal-build-tool-depends-issue/src/MyLib.hs, interpreted )[cabal-build-tool-depends-issue-0.1.0.0-inplace]
[3 of 5] Compiling Main             ( /home/hugin/Documents/haskell/cabal-build-tool-depends-issue/app/Main.hs, interpreted )[cabal-build-tool-depends-issue-0.1.0.0-inplace-cabal-build-tool-depends-issue]
Ok, three modules loaded.
ghci> 

The solution might be not ideal, but I think that it is a sane one:

If a requested target is also a build-tool-depends, then we build the executable normally before returning the ghc options for launching the GHCi session.

The disadvantage is that if we change the executable, a :reload wouldn't recompile the executable, leading to stale artefacts...
I am not sure we can avoid that though, if we think creatively, we could try to produce a wrapper shim named after the executable which wraps a call to runghc running the bytecode artefacts of the executable. These could be automatically updated on :reload, allowing us to even get an updated executable. However, I am not sure whether this works or is worth the effort.

System information

  • arch linux
  • cabal 3.16.1.0, GHC 9.10.3

Additional context

This is the same as #10626 but including a suggestion to move forward and with a fitting title.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions