Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi module script support #6787

Open
harendra-kumar opened this issue May 12, 2020 · 9 comments
Open

Multi module script support #6787

harendra-kumar opened this issue May 12, 2020 · 9 comments

Comments

@harendra-kumar
Copy link

Describe the bug
shebang script interpreter fails if the script spans over multiple modules

To Reproduce
ghc compiles this program successfully.

$ cat OtherModule.hs
module OtherModule (hello) where

hello :: String
hello = "hello"

$ cat hello.hs
#! /usr/bin/env cabal
{- cabal:
    build-depends: base
    ghc-options: -Wall
-}
module Main where

import Example.Hello (hello)

main = putStrLn hello

$ ghc hello.hs
[1 of 2] Compiling OtherModule      ( OtherModule.hs, OtherModule.o )
Linking hello ...

But cabal run fails:

$ cabal v2-run hello.hs
Resolving dependencies...
Build profile: -w ghc-8.8.3 -O1
In order, the following will be built (use -v for more details):
 - fake-package-0 (exe:script) (first run)
Configuring executable 'script' for fake-package-0..
Preprocessing executable 'script' for fake-package-0..
Building executable 'script' for fake-package-0..
[1 of 1] Compiling Main             ( Main.hs, /var/folders/p4/fdt36vy95f52t_3dnpcx8_340000gn/T/cabal-repl.-24197/dist-newstyle/build/x86_64-osx/ghc-8.8.3/fake-package-0/x/script/build/script/script-tmp/Main.o )

Main.hs:7:1: error:
    Could not find module ‘OtherModule’
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
  |
7 | import OtherModule (hello)
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^

Expected behavior
cabal script interpreter should be able to compile and run the above program.

System information

  • Mac OSX
$ cabal --version
cabal-install version 3.2.0.0
compiled using version 3.2.0.0 of the Cabal library 

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.8.3
@phadej
Copy link
Collaborator

phadej commented May 12, 2020

I think this is out of scope of interpreter functionality. At that point you should create a package.

cc @hvr

@harendra-kumar
Copy link
Author

That's fine too, it will be nice if we can mention this in the user guide. I was just wondering if this is easy to implement.

@ju1m
Copy link

ju1m commented May 8, 2021

This would enable the usage of TemplateHaskell which can only run a function at compile time if it is imported from another module.
A workaround is to add hs-source-dirs: /absolute/path/to/directory, but this has poor portability.

@jneira jneira added cabal-install: cmd/run can-workaround There is a (maybe partial) workaround for the issue or missing feature type: enhancement labels Aug 18, 2021
@georgefst
Copy link

A workaround is to add hs-source-dirs: /absolute/path/to/directory

With 3.6.2.0, that's given me:

Warning: script block:5:57:
unexpected absolute FilePath
cabal: Failed parsing "script block".

And presumably relative paths is yet another thing blocked on #6977.

@fgaz fgaz removed the can-workaround There is a (maybe partial) workaround for the issue or missing feature label Dec 10, 2021
@bacchanalia
Copy link
Collaborator

A trick to fake an absolute path as a relative path is to add a while lot of ../../../../ to the front (enough to ensure you get all the way to root no mater where you want to use it from). I've been using this on my work for repl support baring a better solution being found so I'd expect it to work here too.

@bacchanalia
Copy link
Collaborator

I have multi module script support working in #7851

bacchanalia added a commit to bacchanalia/cabal that referenced this issue Dec 11, 2021
- Set the hs-source-dir to the location of the script for build and run,
  the same as with repl
- This removes the need to copy the script
- repl no longer needs a separate cache because all three commands
  use identical project files
- Adds multi-module support to scripts for free (haskell#6787)
- Add new build/repl test and run multi-module test

PR haskell#7851
@fgaz
Copy link
Member

fgaz commented Dec 11, 2021

Hmm, even though that commit makes it possible, I'd still not advertise multi-module scripts as supported. I agree with @phadej that at that point you really should create a package since you already have multiple files anyway

@jneira
Copy link
Member

jneira commented Dec 11, 2021

Also agree, you aways can create a dummy script to access the package like we did in hls: https://github.com/haskell/haskell-language-server/blob/master/install.hs

bacchanalia added a commit to bacchanalia/cabal that referenced this issue Dec 13, 2021
- Set the hs-source-dir to the location of the script for build and run,
  the same as with repl
- This removes the need to copy the script
- repl no longer needs a separate cache because all three commands
  use identical project files
- Adds multi-module support to scripts for free (haskell#6787)
- Add new build/repl test and run multi-module test

PR haskell#7851
@bacchanalia
Copy link
Collaborator

Unfortunately, the final version of #7851 will not allow for multi-module scripts, because I had to balance it against other considerations. I think it's unlikely to be added in the future do to those same considerations.

bacchanalia added a commit to bacchanalia/cabal that referenced this issue Dec 23, 2021
- Set the hs-source-dir to the location of the script for build and run,
  the same as with repl
- This removes the need to copy the script
- repl no longer needs a separate cache because all three commands
  use identical project files
- Adds multi-module support to scripts for free (haskell#6787)
- Add new build/repl test and run multi-module test

PR haskell#7851
jneira pushed a commit to bacchanalia/cabal that referenced this issue Dec 31, 2021
- Set the hs-source-dir to the location of the script for build and run,
  the same as with repl
- This removes the need to copy the script
- repl no longer needs a separate cache because all three commands
  use identical project files
- Adds multi-module support to scripts for free (haskell#6787)
- Add new build/repl test and run multi-module test

PR haskell#7851
mergify bot pushed a commit that referenced this issue Dec 31, 2021
* Add support for script build caching to cabal run

Enable caching of script builds by changing the location of the fake
package directory from a tmp directory to:
<cabal_dir>/scipt-builds/abs/path/to/script/

Resolves: #6354
WIP: #7842

* Add support for scripts to cabal build.

Added module Distribution.Client.ScriptUtils for code to deal with
scripts that is common between commands.

WIP: #7842

* Add script support to cabal clean.

This changes the behaviour of cabal clean to accept extra args, which it
now interprets as script files. The behaviour of cabal clean is the same
when given extra args. When given extra args it instead removes the
caches for those scripts and also any orphaned caches (caches for which
the script no longer exists)

In addition this commit changes the cache to use hashes of paths because
this significantly simplifies the implementation of clean, and more
importantly it prevents collisions when a script has the name of the
subdirectory of a previously cached script.

WIP: #7842

* Add script support to cabal repl

repl starts in the correct directory and points directly to rather than
a dummy, so that reloading works properly.

There is a downside to the current approach which is that it uses a
different fake-project.cabal file from run and build, so it cannot share
the same cache with them.

WIP: #7842
WIP: #6149

* Added changelog for pr #7851

* Fix `cabal run script.hs` issue with --builddir

Fixes tests:
cabal-testsuite/PackageTests/NewBuild/CmdRun/Script/cabal.test.hs
cabal-testsuite/PackageTests/NewBuild/CmdRun/ScriptLiterate/cabal.test.hs

* Fixes for `build script` and `repl script`

- Fix build issue introduced in 079c5f0, where build was being passed
the wrong target filter
- Fix repl issue where script didn't work in a project context.
- Refactor code to share logic between repl and build/run
- Ensure temp directories are only created when needed

* Bug fixes relating to script support

ScriptUtils:
- Hash prefix for cache dirs was applied incorrectly.
- Overwriting fake-package files causes repeated work in some cases.
CmdClean:
- Clean distdir for script when --builddir is passed
- Always clean orphans because because there is no good way to specify
they should be cleaned. This may be bad behaviour in some obscure cases
(a cache is temporarily orphaned and an unrelated clean is run), but at
worst results in a cache rebuild.

* Add tests for improved script support

- Basic script support for build/repl/clean which checks for cached
project files
- Add check for cached project files to basic run script test
- No repeated work for build/build, build/run, run/run, and repl/repl
- Clean does not remove cache for existing scripts
- Clean does remove orphaned script caches

* Fix clean bug uncovered by 5fad121

- clean was trying to read source-builds even if it didn't exist
- add test specific to this case with other clean tests

* Update documentation for better script support

Ready for review: #7851
May close: #7842, #6354, #6149

* Attempt to fix `repl script` on Windows

PR #7851

* Attempt to fix remote test failures

Test logs showed that the failures where because the tests depended on a
module from cabal-install that some ghc versions could not find.

Instead of depending on cabal-install, I copied the needed function into
Test.Cabal.Prelude (It seemed like an acceptable place for it)

PR #7851

* Attempt to fix `repl script` on Windows

PR #7851

* Attempt to fix tests on old ghc versions

Tests failing on pre-AMP ghcs due to unsanctioned use of (<$>)

PR #7851

* Feedback: Update docs and formatting

PR #7851

* Feedback: code style changes

- remove partial selectors
- make a constant for fake-package.cabal

PR #7851

* Feedback: make hidden control flow explicit

PR #7851

* Feedback: add expected fail script run tests

PR #7851

* Fix `repl script` when cwd is deeper than cachedir

PR #7851

* Use script in-place for build or run

- Set the hs-source-dir to the location of the script for build and run,
  the same as with repl
- This removes the need to copy the script
- repl no longer needs a separate cache because all three commands
  use identical project files
- Adds multi-module support to scripts for free (#6787)
- Add new build/repl test and run multi-module test

PR #7851

* Fix file-locking issue on Windows

PR #7851

* Fix script recompilation based on cwd

- Pass info about cwd to repl through --repl-options instead of hacking
  it into the project file.
- Improve paths output by makeRelativeCanonical, makeRelativeToDir, and
  makeRelativeToCwd.
- Script multi-module support works, but with warning in repl.
- Remove script multi-module mention support in docs.

PR #7851

* Make `repl script` respect --repl-no-load

* Feedback: minor refactor

Move argument truncation from targetStrings out of
withScriptContextAndSelectors to runAction

PR #7851

* Feedback: refactor and comments for repl options

PR #7851

* Don't use hs-source-dirs for scripts.

- instead pass absolute path to script in main-is
- resolves issue with relative paths on Windows
- simplifies code and gives prettier build output
- update tests because build output has changed
- removes ability to use multi-module scripts
  (which was never officially endorsed)
- remove test for multi-module scripts
- add checks for unsupported fields in scripts

PR #7851

* Update changelog for PR #7851
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants