ryantrinkle / nixpkgs

Nix Packages collection
Other
4 stars 2 forks source link

Any simple example to use ghcjs using nixpkgs? #1

Closed wavewave closed 9 years ago

wavewave commented 9 years ago

I installed ghcjs with nixpkgs using the master branch of this repo. (btw, needed to patch for making transformer-compat compatible with ghcjs ). I am now trying to figure out how to use ghcjs. Especially, I would like to test ghcjs-examples in ghcjs github organization with node.js. Any simple instructions? I saw a helloworld repo here but not able to make everything work. Thank you for your great work!

wavewave commented 9 years ago

Okay, now I made one working environment for ghcjs using myEnvFun. At least, simple ghcjs test.hs works with node.js.

# in ~/.nixpkgs/config.nix
{
   packageOverrides = pkgs: rec {
     ghcjsEnv =
         pkgs.myEnvFun {
            name = "ghcjs";
            buildInputs = with pkgs; [ haskellPackages_ghcjs.ghc nodejs ];
       }; 
  };  
}

I still couldn't figure out how to make cabal-js work with preinstalled ghcjs cabal packages. Some function corresponding to ghcWithPackages seems missing yet.

wavewave commented 9 years ago

@jwiegley : I guess that you are also a developer of this nixpkgs for ghcjs. Am I right?

ryantrinkle commented 9 years ago

Take a look at my repository, https://github.com/ryantrinkle/ghcjs-setup , which provides a script that should get you into a working ghcjs prompt.

I'm curious what you needed to patch for transformers-compat; do you have that code on github somewhere?

The cabal-js provided in this package should only find ghcjs packages installed with nix, not in the usual places ghcjs puts them. So, if you want to use a package, you'll need to put it in your buildInputs. You can also do it on the command line like so:

nix-shell -p haskellPackages_ghcjs.ghc haskellPackages_ghcjs.aeson nodejs <<EOF
  cat >aesonTest.hs <<FILE
    import Data.Aeson
    main = print $ encode ("Hello", "world!")
FILE
  ghcjs aesonTest.hs
  node aesonTest.jsexe/all.js
EOF
wavewave commented 9 years ago

I've managed to use cabal inside nix-shell. In ryantrinkle/helloworld,

> nix-shell 
> eval "$configurePhase"
> eval "$buildPhase".

For the time being, I can use nix-shell for single package development. If we can use myEnvFun and load-env-blah for ghcjs development, it will be super!

wavewave commented 9 years ago

Ah. you answered me while I was writing. :-D transformers-compat is not needed at all now. I was using your nixpkgs in a wrong way at the beginning. Thanks for the answer!

wavewave commented 9 years ago

For your reference, https://nixos.org/wiki/Haskell#Customized_GHC_environment ghcWithPackages must be implemented for ghcjs if we want to have this kind of setup in parallel.

With this environment, we can load multiple necessary packages and use cabal sandbox for user's cabal package in addition.

ryantrinkle commented 9 years ago

I haven't used ghcWithPackages myself, but it looks like it wouldn't work with the current setup, at the very least because it has an assertion on the version of ghc that will fail with ghcjs. @cstrahan is working on moving the ghcjs integration upstream, and I believe that some of his work may fix that.

jwiegley commented 9 years ago

@wavewave Hi, I did help with the development at the beginning, but @ryantrinkle has really run with it!

cstrahan commented 9 years ago

I should have some time to hack on my ghcjs work this weekend, fwiw.

basvandijk commented 9 years ago

I'm trying to get ghcWithPackages to work with ghcjs but ghcjs-pkg is currently failing with:

$ ghcjs-pkg check
There are problems in package haddock-library-1.1.1:
  dependency "base-4.7.0.1-e4b74d27ad8c8987c63abc42a80e7335" doesn't exist
  dependency "bytestring-0.10.4.0-9f46be651278ecf2e2b21a220bfff6bf" doesn't exist
  dependency "deepseq-1.3.0.2-733fe43e121f761739636bd6670bea77" doesn't exist
There are problems in package semigroupoids-4.2:
  dependency "base-4.7.0.1-e4b74d27ad8c8987c63abc42a80e7335" doesn't exist
  dependency "containers-0.5.5.1-23e2a2b94d6e452c773209f31d8672c5" doesn't exist
  dependency "transformers-0.3.0.0-16a97696ae672940f1523b262e566ba5" doesn't exist
There are problems in package contravariant-1.2:
  dependency "base-4.7.0.1-e4b74d27ad8c8987c63abc42a80e7335" doesn't exist
  dependency "transformers-0.3.0.0-16a97696ae672940f1523b262e566ba5" doesn't exist
...

The following packages are broken, either because they have a problem
listed above, or because they depend on a broken package.
haddock-library-1.1.1
semigroupoids-4.2
contravariant-1.2
...

Has anybody made any progress on ghcWithPackages?

ryantrinkle commented 9 years ago

Hmm. I haven't tried that one, but this works for me: $ nix-shell -p haskellPackages_ghcjs.ghc [nix-shell:~]$ ghcjs-pkg check [nix-shell:~]$

I can also add additional packages this way, and it will build them if necessary. Sometimes I find that adding --pure will help ghc-pkg check run successfully, but I haven't seen it help with ghcjs-pkg - perhaps because i don't have any ghcjs packages installed in my home directory that can "bleed into" the nix shell.

I hope that's helpful! It would be great to get this stuff ironed out enough that we can get ghcjs support pushed upstream.

basvandijk commented 9 years ago

Yes nix-shell -p haskellPackages_ghcjs.ghc works for me to.

However, my project is build using cabal so in my nix-shell I would like to have access to cabal-install with ghcjs support. What I currently have is the following:

default.nix:

{ haskellPackages ? (import <nixpkgs> {}).pkgs.haskellPackages_ghcjs }:
haskellPackages.callPackage (import ./web-experiment.nix) {

  # These are some dependencies that are not in nixpkgs:
  languagePython = haskellPackages.callPackage ./nix/language-python {};
  zenc           = haskellPackages.callPackage ./nix/zenc            {};
  ghcjsJquery    = haskellPackages.callPackage ./nix/ghcjs-jquery    {};
}

web-experiment.nix

{ cabal, aeson, aesonPretty, baseUnicodeSymbols, blazeHtml
, dataDefault, either, languagePython, safe
, systemFilepath, text, transformers, unorderedContainers, vector
, zenc
, ghcjsJquery
}:

cabal.mkDerivation (self: {
  pname = "web-experiment";
  version = "0.0.1";
  src = ./.;
  isLibrary = false;
  isExecutable = true;
  buildDepends = [
    aeson aesonPretty baseUnicodeSymbols blazeHtml dataDefault either
    languagePython safe systemFilepath text transformers
    unorderedContainers vector zenc
    ghcjsJquery
  ];
  meta = {
    license = self.stdenv.lib.licenses.unfree;
    platforms = self.ghc.meta.platforms;
  };
})

I can successfully build the project using:

$ nix-build -I .  # Note that I have your fork of nixpkgs checked out in .
...

$ ls ./result/bin/client.jsexe
all.js  index.html  lib1.js  lib1.js.files  lib.js  lib.js.files  out.js  out.stats  rts.js

However, for development, using nix-build every time you want to compile the project is not so nice since it takes too much time. So I would like to have a shell in which I have all the dependencies in scope and then I can just use cabal build to compile the project.

Normally I would just use nix-shell like:

$ nix-shell -I . --pure

# However I don't have access to cabal-install from this shell
$ cabal --version
cabal: command not found

This should be easily fixed with a "hack" like adding buildTools = [ cabalInstallGhcjs ]; to the web-experiment.nix derivation. In normal (non ghcjs) projects this trick of adding cabalInstall to buildTools works. However for some reason adding cabalInstallGhcjs to buildTools doesn't bring cabal into scope.

Any idea why?

ryantrinkle commented 9 years ago

I think cabalInstallGhcjs exposes a binary called cabal-js, not cabal. Something like this might work: nix-shell -p haskellPackages_ghcjs.ghc haskellPackages_ghcjs.ghc.ghc.parent.cabalInstallGhcjs

The reason for the weird attribute path for cabalInstallGhcjs is that it's going through the ghcjs wrapper to the actual ghcjs instance, then to the "parent environment", i.e. a customized haskellPackages_ghc783, then grabbing cabalInstallGhcjs. This ensures you'll get the same version of cabal-js as was used to build other things in the ghcjs ecosystem.

basvandijk commented 9 years ago

I think cabalInstallGhcjs exposes a binary called cabal-js, not cabal. Something like this might work: nix-shell -p haskellPackages_ghcjs.ghc haskellPackages_ghcjs.ghc.ghc.parent.cabalInstallGhcjs

Thanks, I'm now using the following default.nix and I included buildTools = [ cabalInstallGhcjs ]; in web-experiment.nix:

let pkgs = import <nixpkgs> {}; in
{ haskellPackages_ghcjs ? pkgs.haskellPackages_ghcjs }:
haskellPackages_ghcjs.callPackage (import ./web-experiment.nix) {
  languagePython    = haskellPackages_ghcjs.callPackage ./nix/language-python {};
  zenc              = haskellPackages_ghcjs.callPackage ./nix/zenc            {};
  ghcjsJquery       = haskellPackages_ghcjs.callPackage ./nix/ghcjs-jquery    {};

  cabalInstallGhcjs = haskellPackages_ghcjs.ghc.ghc.parent.cabalInstallGhcjs;
}

This indeed gives me cabal-js which I can use to successfully configure my project:

$ cabal-js configure --ghcjs
Resolving dependencies...
Configuring web-experiment-0.0.1...

However, building fails in the Cabal library:

$ cabal-js build
Building web-experiment-0.0.1...
cabal-js: Distribution/Simple/Build.hs:120:7-70: 
  Irrefutable pattern failed for pattern Data.Maybe.Just ghcPkgProg

I believe Cabal is failing because it's looking up the ghc-pkg program which doesn't exist. Maybe it should look for ghcjs-pkg instead...

ryantrinkle commented 9 years ago

I think you need to supply --ghcjs to cabal-js configure. Even though it's called cabal-js, it still defaults to regular ghc; it just also supports ghcjs.

basvandijk commented 9 years ago

If I add nativeGhc to the buildTools in web-experiment.nix:

  buildTools = [
    cabalInstallGhcjs
    nativeGhc
  ];

And bind it to the actual haskellPackages.ghc in default.nix I can successfully run nix-shell and build my project using cabal-js.

let pkgs = import <nixpkgs> {}; in
{ haskellPackages_ghcjs ? pkgs.haskellPackages_ghcjs }:
haskellPackages_ghcjs.callPackage (import ./web-experiment.nix) {
  languagePython    = haskellPackages_ghcjs.callPackage ./nix/language-python {};
  zenc              = haskellPackages_ghcjs.callPackage ./nix/zenc            {};
  ghcjsJquery       = haskellPackages_ghcjs.callPackage ./nix/ghcjs-jquery    {};

  cabalInstallGhcjs = haskellPackages_ghcjs.ghc.ghc.parent.cabalInstallGhcjs;
  nativeGhc         = pkgs.haskellPackages.ghc;
}
ryantrinkle commented 9 years ago

It would be better to use haskellPackages_ghcjs.ghc.ghc.parent.ghc rather than haskellPackages.ghc as the definition of nativeGhc, because that would ensure that it's exactly the same GHC that was used to build GHCJS. other than that, that looks right to me.

This issue has gotten a bit off-topic, so I'm going to close it here; please feel free to open a new issue or send me an email to continue the discussion.

basvandijk commented 9 years ago

It would be better to use haskellPackages_ghcjs.ghc.ghc.parent.ghc rather than haskellPackages.ghc as the definition of nativeGhc, because that would ensure that it's exactly the same GHC that was used to build GHCJS.

Great, thanks for the tip.