Offline compilation with Stack/Cabal

Hi, Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity. Is that possible with Stack or Cabal? Any pointers would be much appreciated. Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change. Best Jan

On 24 November 2016 at 17:57, Jan von Löwenstein
Hi,
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
I believe (but have not verified) that it is possible with both of them to specify local directories where source tarballs can be found. Alternatively, both definitely support through various mechanisms to be pointed at local unpacked copies of source files (directly in stack.yaml files).
Best Jan
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com

Another, rather drastic, solution would be to run a hackage server locally
on the target, and point the relevant DNS entries to localhosts via the
hosts file. Probably not necessary though.
On Nov 24, 2016 8:02 AM, "Ivan Lazar Miljenovic"
On 24 November 2016 at 17:57, Jan von Löwenstein
wrote: Hi,
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
I believe (but have not verified) that it is possible with both of them to specify local directories where source tarballs can be found. Alternatively, both definitely support through various mechanisms to be pointed at local unpacked copies of source files (directly in stack.yaml files).
Best Jan
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Hi,
Does
stack build --prefetch --dry-run
get close to what you want? That seems to download all the necessary
packages, and by using stack you get the ability to share compiled
dependencies between packages.
Cheers,
David
On 24 November 2016 at 06:57, Jan von Löwenstein
Hi,
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
Best Jan
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Thanks for all the responses.
@Ivan
I couldn't yet find an option in stack to point to local source tarballs.
Custom snapshots at least currently only support Hackage packages and that
was the closest I found.
I briefly looked into `stack unpack <package>`, that might indeed provide a
workable solution. Although options other than the list of packages would
have to be duplicated between my "normal" stack.yaml and the one I use to
enable offline compilation.
@Tobias
I already thought about that, yackage sounds like a package that would help
implement it. Not sure if I like that option very much though.
@David
Not sure if I get your proposal.
Running `stack build --prefetch --dry-run` lists my local packages as
"Would build". How would I get source tarballs of my dependencies and how
would I build them on an offline machine?
Best
Jan
David Turner
Hi,
Does
stack build --prefetch --dry-run
get close to what you want? That seems to download all the necessary packages, and by using stack you get the ability to share compiled dependencies between packages.
Cheers,
David
On 24 November 2016 at 06:57, Jan von Löwenstein < jan.loewenstein@gmail.com> wrote:
Hi,
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
Best Jan
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On 24 November 2016 at 23:34, Jan von Löwenstein
Thanks for all the responses.
@Ivan I couldn't yet find an option in stack to point to local source tarballs. Custom snapshots at least currently only support Hackage packages and that was the closest I found.
https://docs.haskellstack.org/en/stable/yaml_configuration/#packages
I briefly looked into `stack unpack <package>`, that might indeed provide a workable solution. Although options other than the list of packages would have to be duplicated between my "normal" stack.yaml and the one I use to enable offline compilation.
@Tobias I already thought about that, yackage sounds like a package that would help implement it. Not sure if I like that option very much though.
@David Not sure if I get your proposal. Running `stack build --prefetch --dry-run` lists my local packages as "Would build". How would I get source tarballs of my dependencies and how would I build them on an offline machine?
Best Jan
David Turner
schrieb am Do., 24. Nov. 2016 um 10:13 Uhr: Hi,
Does
stack build --prefetch --dry-run
get close to what you want? That seems to download all the necessary packages, and by using stack you get the ability to share compiled dependencies between packages.
Cheers,
David
On 24 November 2016 at 06:57, Jan von Löwenstein
wrote: Hi,
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
Best Jan
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com

Hi, > Running `stack build --prefetch --dry-run` lists my local packages as "Would build". How would I get source tarballs of my dependencies and how would I build them on an offline machine? I think that means you've already got all the source tarballs that you would need. On a reasonably clean machine (no $HOME/.stack directory at least), running `stack setup` and then `stack build --prefetch --dry-run` does a bunch of downloading (but nothing else), such that I can switch to aeroplane mode and then run `stack build` without needing further network access. There's a full transcript below. This certainly seems to imply that all the source tarballs are available locally - I think they go somewhere in $HOME/.stack. What I think this means is that if you do this then copy your $HOME/.stack across to the isolated machine then that should be everything you need in order to build everything. HTH, David $ stack setup Downloaded lts-3.6 build plan. Fetching package index ...remote: Counting objects: 233532, done. remote: Compressing objects: 100% (188553/188553), done. remote: Total 233532 (delta 62098), reused 185305 (delta 42595), pack-reused 0 Receiving objects: 100% (233532/233532), 55.26 MiB | 1.97 MiB/s, done. Resolving deltas: 100% (62098/62098), completed with 1 local objects. >From https://github.com/commercialhaskell/all-cabal-hashes * [new tag] current-hackage -> current-hackage Fetched package index. Populated index cache. Preparing to install GHC to an isolated location. This will not interfere with any system-level installation. Downloaded ghc-7.10.2. Installed GHC. stack will use a locally installed GHC For more information on paths, see 'stack path' and 'stack exec env' To use this GHC and packages outside of a project, consider using: stack ghc, stack ghci, stack runghc, or stack exec $ stack build --prefetch --dry-run asn1-parse-0.9.1: download ansi-terminal-0.6.2.3: download asn1-types-0.3.0: download aeson-0.8.0.2: download async-2.0.2: download attoparsec-0.12.1.6: download ansi-wl-pprint-0.6.7.3: download base64-bytestring-1.0.0.1: download blaze-builder-0.4.0.1: download byteable-0.1.1: download asn1-encoding-0.9.2: download case-insensitive-1.2.0.4: download cookie-0.4.1.6: download cereal-0.4.1.1: download connection-0.2.5: download cryptonite-0.6: download data-default-class-0.0.1: download exceptions-0.8.0.2: download dlist-0.7.1.2: download http-client-tls-0.2.2: download hourglass-0.2.9: download http-client-0.4.23: download hashable-1.2.3.3: download memory-0.7: download http-types-0.8.6: download mime-types-0.1.0.6: download network-2.6.2.1: download mtl-2.2.1: download old-locale-1.0.0.7: download optparse-applicative-0.11.0.2: download network-uri-2.6.0.3: download parsec-3.1.9: download pem-0.2.2: download scientific-0.3.3.8: download primitive-0.6: download socks-0.5.4: download stm-2.4.4: download random-1.1: download syb-0.5.1: download text-1.2.1.3: download streaming-commons-0.1.13: download transformers-compat-0.4.0.4: download unordered-containers-0.2.5.1: download tls-1.3.2: download x509-1.6.1: download x509-validation-1.6.2: download x509-store-1.6.1: download vector-0.10.12.3: download zlib-0.5.4.2: download x509-system-1.6.1: download No packages would be unregistered. Would build: aeson-0.8.0.2: database=snapshot, source=package index, after: attoparsec-0.12.1.6,dlist-0.7.1.2,hashable-1.2.3.3,mtl-2.2.1,scientific-0.3.3.8,syb-0.5.1,text-1.2.1.3,unordered-containers-0.2.5.1,vector-0.10.12.3 ansi-terminal-0.6.2.3: database=snapshot, source=package index ansi-wl-pprint-0.6.7.3: database=snapshot, source=package index, after: ansi-terminal-0.6.2.3 asn1-encoding-0.9.2: database=snapshot, source=package index, after: asn1-types-0.3.0,hourglass-0.2.9,mtl-2.2.1 asn1-parse-0.9.1: database=snapshot, source=package index, after: asn1-encoding-0.9.2,asn1-types-0.3.0,mtl-2.2.1 asn1-types-0.3.0: database=snapshot, source=package index, after: hourglass-0.2.9 async-2.0.2: database=snapshot, source=package index, after: stm-2.4.4 attoparsec-0.12.1.6: database=snapshot, source=package index, after: scientific-0.3.3.8,text-1.2.1.3 autoharvest-0.1.0.0: database=local, source=/home/davidturner/autoharvest/, after: aeson-0.8.0.2,http-client-0.4.23,http-client-tls-0.2.2,http-types-0.8.6,optparse-applicative-0.11.0.2,text-1.2.1.3 base64-bytestring-1.0.0.1: database=snapshot, source=package index blaze-builder-0.4.0.1: database=snapshot, source=package index, after: text-1.2.1.3 byteable-0.1.1: database=snapshot, source=package index case-insensitive-1.2.0.4: database=snapshot, source=package index, after: hashable-1.2.3.3,text-1.2.1.3 cereal-0.4.1.1: database=snapshot, source=package index connection-0.2.5: database=snapshot, source=package index, after: byteable-0.1.1,data-default-class-0.0.1,network-2.6.2.1,socks-0.5.4,tls-1.3.2,x509-1.6.1,x509-store-1.6.1,x509-system-1.6.1,x509-validation-1.6.2 cookie-0.4.1.6: database=snapshot, source=package index, after: blaze-builder-0.4.0.1,data-default-class-0.0.1,old-locale-1.0.0.7,text-1.2.1.3 cryptonite-0.6: database=snapshot, source=package index, after: memory-0.7 data-default-class-0.0.1: database=snapshot, source=package index dlist-0.7.1.2: database=snapshot, source=package index exceptions-0.8.0.2: database=snapshot, source=package index, after: mtl-2.2.1,stm-2.4.4,transformers-compat-0.4.0.4 hashable-1.2.3.3: database=snapshot, source=package index, after: text-1.2.1.3 hourglass-0.2.9: database=snapshot, source=package index http-client-0.4.23: database=snapshot, source=package index, after: base64-bytestring-1.0.0.1,blaze-builder-0.4.0.1,case-insensitive-1.2.0.4,cookie-0.4.1.6,data-default-class-0.0.1,exceptions-0.8.0.2,http-types-0.8.6,mime-types-0.1.0.6,network-2.6.2.1,network-uri-2.6.0.3,random-1.1,streaming-commons-0.1.13,text-1.2.1.3 http-client-tls-0.2.2: database=snapshot, source=package index, after: connection-0.2.5,data-default-class-0.0.1,http-client-0.4.23,network-2.6.2.1,tls-1.3.2 http-types-0.8.6: database=snapshot, source=package index, after: blaze-builder-0.4.0.1,case-insensitive-1.2.0.4,text-1.2.1.3 memory-0.7: database=snapshot, source=package index mime-types-0.1.0.6: database=snapshot, source=package index, after: text-1.2.1.3 mtl-2.2.1: database=snapshot, source=package index network-2.6.2.1: database=snapshot, source=package index network-uri-2.6.0.3: database=snapshot, source=package index, after: parsec-3.1.9 old-locale-1.0.0.7: database=snapshot, source=package index optparse-applicative-0.11.0.2: database=snapshot, source=package index, after: ansi-wl-pprint-0.6.7.3,transformers-compat-0.4.0.4 parsec-3.1.9: database=snapshot, source=package index, after: mtl-2.2.1,text-1.2.1.3 pem-0.2.2: database=snapshot, source=package index, after: base64-bytestring-1.0.0.1,mtl-2.2.1 primitive-0.6: database=snapshot, source=package index random-1.1: database=snapshot, source=package index scientific-0.3.3.8: database=snapshot, source=package index, after: hashable-1.2.3.3,text-1.2.1.3 socks-0.5.4: database=snapshot, source=package index, after: cereal-0.4.1.1,network-2.6.2.1 stm-2.4.4: database=snapshot, source=package index streaming-commons-0.1.13: database=snapshot, source=package index, after: blaze-builder-0.4.0.1,network-2.6.2.1,random-1.1,stm-2.4.4,text-1.2.1.3,zlib-0.5.4.2 syb-0.5.1: database=snapshot, source=package index text-1.2.1.3: database=snapshot, source=package index tls-1.3.2: database=snapshot, source=package index, after: asn1-encoding-0.9.2,asn1-types-0.3.0,async-2.0.2,cereal-0.4.1.1,cryptonite-0.6,data-default-class-0.0.1,memory-0.7,mtl-2.2.1,network-2.6.2.1,x509-1.6.1,x509-store-1.6.1,x509-validation-1.6.2 transformers-compat-0.4.0.4: database=snapshot, source=package index unordered-containers-0.2.5.1: database=snapshot, source=package index, after: hashable-1.2.3.3 vector-0.10.12.3: database=snapshot, source=package index, after: primitive-0.6 x509-1.6.1: database=snapshot, source=package index, after: asn1-encoding-0.9.2,asn1-parse-0.9.1,asn1-types-0.3.0,cryptonite-0.6,hourglass-0.2.9,memory-0.7,mtl-2.2.1,pem-0.2.2 x509-store-1.6.1: database=snapshot, source=package index, after: asn1-encoding-0.9.2,asn1-types-0.3.0,cryptonite-0.6,mtl-2.2.1,pem-0.2.2,x509-1.6.1 x509-system-1.6.1: database=snapshot, source=package index, after: mtl-2.2.1,pem-0.2.2,x509-1.6.1,x509-store-1.6.1 x509-validation-1.6.2: database=snapshot, source=package index, after: asn1-encoding-0.9.2,asn1-types-0.3.0,byteable-0.1.1,cryptonite-0.6,data-default-class-0.0.1,hourglass-0.2.9,memory-0.7,mtl-2.2.1,pem-0.2.2,x509-1.6.1,x509-store-1.6.1 zlib-0.5.4.2: database=snapshot, source=package index No executables to be installed. On 24 November 2016 at 12:34, Jan von Löwensteinwrote: > > Thanks for all the responses. > > @Ivan > I couldn't yet find an option in stack to point to local source tarballs. Custom snapshots at least currently only support Hackage packages and that was the closest I found. > > I briefly looked into `stack unpack `, that might indeed provide a workable solution. Although options other than the list of packages would have to be duplicated between my "normal" stack.yaml and the one I use to enable offline compilation. > > @Tobias > I already thought about that, yackage sounds like a package that would help implement it. Not sure if I like that option very much though. > > @David > Not sure if I get your proposal. > Running `stack build --prefetch --dry-run` lists my local packages as "Would build". How would I get source tarballs of my dependencies and how would I build them on an offline machine? > > Best > Jan > > David Turner schrieb am Do., 24. Nov. 2016 um 10:13 Uhr: >> >> Hi, >> >> Does >> >> stack build --prefetch --dry-run >> >> get close to what you want? That seems to download all the necessary packages, and by using stack you get the ability to share compiled dependencies between packages. >> >> Cheers, >> >> David >> >> On 24 November 2016 at 06:57, Jan von Löwenstein < jan.loewenstein@gmail.com> wrote: >>> >>> Hi, >>> >>> Consider the following use case: >>> I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity. >>> >>> Is that possible with Stack or Cabal? >>> Any pointers would be much appreciated. >>> >>> Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change. >>> >>> Best >>> Jan >>> >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> To (un)subscribe, modify options or view archives go to: >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> Only members subscribed via the mailman list are allowed to post.

Hi, On 2016-11-24 at 07:57:57 +0100, Jan von Löwenstein wrote:
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
This situation is not that uncommon; one example is when you have build-bots which a more or less cut off from the internet (such as Ubuntu's launchpad buildfarm)
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
This sounds like something I'd use cabal's filesystem-local repository feature[1] for, and it should be possible to specify such local repositories in your `cabal.config` or `cabal.project`[2] files to produce a self-contained source distribution. If you're interested in pursuing this approach or have any questions about it, let me know! [1]: http://cabal.readthedocs.io/en/latest/installing-packages.html#repository-sp... [2]: http://cabal.readthedocs.io/en/latest/nix-local-build-overview.html Cheers

If anybody else is interested.
For now, I settled with a Stack based solution.
`STACK_ROOT=<some-temp-folder> stack build --dry-run --prefetch`
works like a charm. What I didn't tackle yet is having multiple ghc
installations in that folder. Somehow I will find a solution for that as
well.
For now I live with the fact that
`STACK_ROOT=<extracted-archive-from-prior-step> stack build --install-ghc`
will connect to the internet to download ghc.
Thanks for all the responses. I'll send an update when the ghc thing is
solved as well.
Best
Jan
Herbert Valerio Riedel
Hi,
On 2016-11-24 at 07:57:57 +0100, Jan von Löwenstein wrote:
Consider the following use case: I have to ship a Haskell application as source, bundled with its dependencies and a script that can produce the binary on a machine without internet connectivity.
This situation is not that uncommon; one example is when you have build-bots which a more or less cut off from the internet (such as Ubuntu's launchpad buildfarm)
Is that possible with Stack or Cabal? Any pointers would be much appreciated.
Ideally I would like to build each dependency package individually. That way I could cache results per Haskell package and don't need to rebuild dependencies until they actually change.
This sounds like something I'd use cabal's filesystem-local repository feature[1] for, and it should be possible to specify such local repositories in your `cabal.config` or `cabal.project`[2] files to produce a self-contained source distribution.
If you're interested in pursuing this approach or have any questions about it, let me know!
[1]: http://cabal.readthedocs.io/en/latest/installing-packages.html#repository-sp... [2]: http://cabal.readthedocs.io/en/latest/nix-local-build-overview.html
Cheers
participants (5)
-
David Turner
-
Herbert Valerio Riedel
-
Ivan Lazar Miljenovic
-
Jan von Löwenstein
-
Tobias Dammers