Skip to content

Add cabal scripting support #5483

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

Merged
merged 7 commits into from
Aug 2, 2018

Conversation

typedrat
Copy link
Collaborator

@typedrat typedrat commented Jul 31, 2018

Closes #3843. Implements effectively the design given, with some changes:

  • cabal new-run allows the user to run scripts in files without shebangs
  • The {- cabal: -} syntax is now that of the executable block

Please include the following checklist in your PR:

  • Patches conform to the coding conventions.
  • Any changes that could be relevant to users have been recorded in the changelog.
  • The documentation has been updated, if necessary.

@23Skidoo
Copy link
Member

Nice! Needs docs though.

@typedrat typedrat force-pushed the cabal-scripting-support branch from 0a5aea3 to b26a029 Compare August 1, 2018 00:18
@23Skidoo
Copy link
Member

23Skidoo commented Aug 1, 2018

I tried this with a multi-module script and got the following error:

$ cabal-typedrat new-run Shake/Shake.hs
Resolving dependencies...
Build profile: -w ghc-8.4.3 -O1
In order, the following will be built (use -v for more details):
 - fake-package-0 (exe:script) (configuration changed)
Configuring executable 'script' for fake-package-0..
Preprocessing executable 'script' for fake-package-0..
cabal-typedrat: can't find source for Shake/Cabal in .,
[...]/dist-newstyle/build/x86_64-linux/ghc-8.4.3/fake-package-0/x/script/build/script/autogen,
[...]/dist-newstyle/build/x86_64-linux/ghc-8.4.3/fake-package-0/x/script/build/global-autogen

In the Shake/Shake.hs file I have

{- cabal:
build-depends: base, aeson ^>= 1.4, shake ^>= 0.16
other-modules: Shake.Cabal
               Shake.DBSchema
               Shake.Flags
               Shake.GetHsDeps
               Shake.NewBuild
               Shake.Oracles
               Shake.TeamCity
               Shake.Utils
ghc-options: -with-rtsopts=-I0
default-language: Haskell2010
-}

@typedrat
Copy link
Collaborator Author

typedrat commented Aug 1, 2018

That’s not something I even considered on the docket. Easy enough to implement I suppose.


::

$ cabal new-run script.hs
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please also add an example of how to pass command-line arguments to a script started with new-run? I expect something like cabal new-run script.hs -- --foo bar.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's exactly right, I thought it was regular enough with the rest of new-run that it didn't need to be called out explicitly, but you're right that it could use a mention.

#!/usr/bin/env cabal
{- cabal:
build-depends: base ^>= 4.11
, shelly ^>= 1.8.1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably needs default-language: Haskell2010 as well, since otherwise you always get a warning. Unless we decide to splice that in automagically.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@23Skidoo actually this makes me think of something... I think we should encode the spec-version somehow... e.g.

#!/usr/bin/env cabal
{-# LANGUAGE Haskell2010, GADTs #-}
{- cabal:2.4
build-depends: ...
-}

and we might want to tolerate not having to specify default-language w/ scripts, as default-{extensions,language} makes less sense imho for scripts, as we have actual language pragmas (I've intentionally added one in the example above), and you certainly wouldn't want to replicate those...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about multi-file scripts? Easier to set default-language in one place than use a pragma in each file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@23Skidoo we can still support default-language; I just think we shouldn't force people to use it by emitting nasty warnings like we do for .cabal files...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It skips that check on purpose.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't we then need to parse LANGUAGE pragmas to make sure that they are actually specified when default-language is absent?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@23Skidoo depends on the semantics you want to have for scripts...

However, I suggest we postpone this design/bikeshedding issue to a followup-task in order not to hold up merging this PR; I think all @typedrat needs to do is tweaks the docs and we're ready to go?

@typedrat typedrat merged commit 6b6d588 into haskell:master Aug 2, 2018
@hvr hvr added this to the 2.4 milestone Aug 2, 2018
@hvr
Copy link
Member

hvr commented Aug 2, 2018

@23Skidoo any objections to cherry picking this to 2.4?

@23Skidoo
Copy link
Member

23Skidoo commented Aug 2, 2018

@hvr What about the spec-version thing?

@hvr
Copy link
Member

hvr commented Aug 2, 2018

@23Skidoo well, technically this is still all a tech-preview in 2.4, thanks to the new-* prefix... so we don't need this to be "final", no? :-)

As for what to do about the spec-version, I intend to write up a design ticket to discuss how to pin down the semantics in a robust way so that scripts don't bitrot if cabal keeps changing its semantics.

In any case, I consider the benefit of making this feature available to users in 2.4 in a tech-preview to gain more feedback & experience to outweight the potential risk of having to break those early adopters in 3.0...

@23Skidoo
Copy link
Member

23Skidoo commented Aug 7, 2018

@hvr OK, sure, let's backport this to 2.4.

@hvr
Copy link
Member

hvr commented Aug 7, 2018

@23Skidoo turns out it's been already done via 3e6a2c4 :-)

@bgamari
Copy link
Contributor

bgamari commented Jan 18, 2020

Where is the documentation for this feature?

@phadej
Copy link
Collaborator

phadej commented Jan 18, 2020

@expipiplus1
Copy link

Is there any documentation on that this {- cabal: ... section should/can contain?

@expipiplus1
Copy link

There are a couple of immediate issues I found:

  • Cabal prints out a bunch of diagnostic information to stdout! This makes it hard to use any Haskell script's stdout without having to filter the cabal stuff first.

    Resolving dependencies...
    Build profile: -w ghc-8.8.4 -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, /run/user/1000/cabal-repl.-25667/dist-newstyle/build/x86_64-linux/ghc-8.8.4/fake-package-0/x/script/build/script/script-tmp/Main.o )
    Linking /run/user/1000/cabal-repl.-25667/dist-newstyle/build/x86_64-linux/ghc-8.8.4/fake-package-0/x/script/build/script/script ...
    
  • Scripts aren't standalone, in the example I found, they don't work in a directory which contains an unparseable .cabal file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RFC: Add support for "#! /usr/bin/env cabal
6 participants