From 6da4584acf4478b04457d57f3881b3aca7d3f7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Domen=20Ko=C5=BEar?= Date: Thu, 3 Jan 2019 16:31:00 +0000 Subject: [PATCH] Elm: automate packaging with elm2nix - rewrite documentation - automate whole process into update.sh - remove all legacy snippets --- doc/package-notes.xml | 18 ++--- pkgs/development/compilers/elm/README.md | 24 +++++++ pkgs/development/compilers/elm/default.nix | 54 +-------------- pkgs/development/compilers/elm/elm2nix.rb | 26 -------- .../compilers/elm/packages/elm-elm.nix | 50 -------------- .../compilers/elm/packages/elm-srcs.nix | 62 ++++++++++++++++++ .../compilers/elm/packages/elm.nix | 1 + pkgs/development/compilers/elm/update.sh | 9 ++- pkgs/development/compilers/elm/versions.dat | Bin 83377 -> 94810 bytes 9 files changed, 104 insertions(+), 140 deletions(-) create mode 100644 pkgs/development/compilers/elm/README.md delete mode 100755 pkgs/development/compilers/elm/elm2nix.rb delete mode 100644 pkgs/development/compilers/elm/packages/elm-elm.nix create mode 100644 pkgs/development/compilers/elm/packages/elm-srcs.nix diff --git a/doc/package-notes.xml b/doc/package-notes.xml index 803d343aa096..e23593107d8d 100644 --- a/doc/package-notes.xml +++ b/doc/package-notes.xml @@ -307,23 +307,19 @@ packageOverrides = pkgs: { +
Elm - The Nix expressions for Elm reside in - pkgs/development/compilers/elm. They are generated - automatically by update-elm.rb script. One should specify - versions of Elm packages inside the script, clear the - packages directory and run the script from inside it. - elm-reactor is special because it also has Elm package - dependencies. The process is not automated very much for now -- you should - get the elm-reactor source tree (e.g. with - nix-shell) and run elm2nix.rb inside - it. Place the resulting package.nix file into - packages/elm-reactor-elm.nix. + To update Elm compiler, see nixpkgs/pkgs/development/compilers/elm/README.md. + + + + To package Elm applications, read about elm2nix.
+
Interactive shell helpers diff --git a/pkgs/development/compilers/elm/README.md b/pkgs/development/compilers/elm/README.md new file mode 100644 index 000000000000..f0254d0f9547 --- /dev/null +++ b/pkgs/development/compilers/elm/README.md @@ -0,0 +1,24 @@ +# To update Elm: + +Modify revision in ./update.sh and run it + +# Notes about the build process: + +The elm binary embeds a piece of pre-compiled elm code, used by 'elm +reactor'. This means that the build process for 'elm' effectively +executes 'elm make'. that in turn expects to retrieve the elm +dependencies of that code (elm/core, etc.) from +package.elm-lang.org, as well as a cached bit of metadata +(versions.dat). + +The makeDotElm function lets us retrieve these dependencies in the +standard nix way. we have to copy them in (rather than symlink) and +make them writable because the elm compiler writes other .dat files +alongside the source code. versions.dat was produced during an +impure build of this same code; the build complains that it can't +update this cache, but continues past that warning. + +Finally, we set ELM_HOME to point to these pre-fetched artifacts so +that the default of ~/.elm isn't used. + +More: https://blog.hercules-ci.com/elm/2019/01/03/elm2nix-0.1/ diff --git a/pkgs/development/compilers/elm/default.nix b/pkgs/development/compilers/elm/default.nix index 47a0d459a93d..3c8ae70981e6 100644 --- a/pkgs/development/compilers/elm/default.nix +++ b/pkgs/development/compilers/elm/default.nix @@ -2,54 +2,6 @@ , haskell, nodejs , fetchurl, fetchpatch, makeWrapper, git }: -# To update: - -# 1) Modify ./update.sh and run it - -# 2) to generate versions.dat: -# 2.1) git clone https://github.com/elm/compiler.git -# 2.2) cd compiler -# 2.3) cabal2nix --shell . | sed 's/"default",/"ghc822",/' > shell.nix -# 2.4) nix-shell -# 2.5) mkdir .elm -# 2.6) export ELM_HOME=$(pwd)/.elm -# 2.7) cabal build -# 2.8) cp .elm/0.19.0/package/versions.dat ... - -# 3) generate a template for elm-elm.nix with: -# ( -# echo "{"; -# jq '.dependencies | .direct, .indirect | to_entries | .[] | { (.key) : { version : .value, sha256: "" } } ' \ -# < ui/browser/elm.json \ -# | sed 's/:/ =/' \ -# | sed 's/^[{}]//' \ -# | sed -E 's/(["}]),?$/\1;/' \ -# | sed -E 's/"(version|sha256)"/\1/' \ -# | grep -v '^$'; -# echo "}" -# ) -# -# ... then fill in the sha256s - -# Notes: - -# the elm binary embeds a piece of pre-compiled elm code, used by 'elm -# reactor'. this means that the build process for 'elm' effectively -# executes 'elm make'. that in turn expects to retrieve the elm -# dependencies of that code (elm/core, etc.) from -# package.elm-lang.org, as well as a cached bit of metadata -# (versions.dat). - -# the makeDotElm function lets us retrieve these dependencies in the -# standard nix way. we have to copy them in (rather than symlink) and -# make them writable because the elm compiler writes other .dat files -# alongside the source code. versions.dat was produced during an -# impure build of this same code; the build complains that it can't -# update this cache, but continues past that warning. - -# finally, we set ELM_HOME to point to these pre-fetched artifacts so -# that the default of ~/.elm isn't used. - let fetchElmDeps = import ./fetchElmDeps.nix { inherit stdenv lib fetchurl; }; hsPkgs = haskell.packages.ghc822.override { @@ -58,8 +10,8 @@ let elm = overrideCabal (self.callPackage ./packages/elm.nix { }) (drv: { # sadly with parallelism most of the time breaks compilation enableParallelBuilding = false; - preConfigure = fetchElmDeps { - elmPackages = (import ./packages/elm-elm.nix); + preConfigure = self.fetchElmDeps { + elmPackages = (import ./packages/elm-srcs.nix); versionsDat = ./versions.dat; }; buildTools = drv.buildTools or [] ++ [ makeWrapper ]; @@ -75,8 +27,6 @@ let ''; }); - - /* The elm-format expression is updated via a script in the https://github.com/avh4/elm-format repo: `pacakge/nix/build.sh` diff --git a/pkgs/development/compilers/elm/elm2nix.rb b/pkgs/development/compilers/elm/elm2nix.rb deleted file mode 100755 index fab5551ca158..000000000000 --- a/pkgs/development/compilers/elm/elm2nix.rb +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env ruby - -require 'json' - -system("elm-package install -y") -depsSrc = JSON.parse(File.read("elm-stuff/exact-dependencies.json")) -deps = Hash[ depsSrc.map { |pkg, ver| - url = "https://github.com/#{pkg}/archive/#{ver}.tar.gz" - sha256 = `nix-prefetch-url #{url}` - - [ pkg, { version: ver, - sha256: sha256.strip - } - ] -} ] - -File.open("package.nix", 'w') do |file| - file.puts "{" - for pkg, info in deps - file.puts " \"#{pkg}\" = {" - file.puts " version = \"#{info[:version]}\";" - file.puts " sha256 = \"#{info[:sha256]}\";" - file.puts " };" - end - file.puts "}" -end diff --git a/pkgs/development/compilers/elm/packages/elm-elm.nix b/pkgs/development/compilers/elm/packages/elm-elm.nix deleted file mode 100644 index a38e21daa06d..000000000000 --- a/pkgs/development/compilers/elm/packages/elm-elm.nix +++ /dev/null @@ -1,50 +0,0 @@ -{ - "elm/browser" = { - version = "1.0.0"; - sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; - }; - "elm/core" = { - version = "1.0.0"; - sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; - }; - "elm/html" = { - version = "1.0.0"; - sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; - }; - "elm/http" = { - version = "1.0.0"; - sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; - }; - "elm/json" = { - version = "1.0.0"; - sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; - }; - "elm/project-metadata-utils" = { - version = "1.0.0"; - sha256 = "1d4rd4grrnbdvj9gf00h7dr6hbkjzawgkzpizfrkp1z1pyr3mvq9"; - }; - "elm/svg" = { - version = "1.0.0"; - sha256 = "08x0v8p9wm699jjmsnbq69pxv3jh60j4f6fg7y6hyr7xxj85y390"; - }; - "elm-explorations/markdown" = { - version = "1.0.0"; - sha256 = "0k3110ixa4wwf3vkkdplagwah9ypr965qxr1y147rnsc1xsxmr6y"; - }; - "elm/parser" = { - version = "1.0.0"; - sha256 = "0k4zlq30lrvawqvzwbvsl0hrmwf9s832mb41z7fdspm4549dj7wc"; - }; - "elm/time" = { - version = "1.0.0"; - sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; - }; - "elm/url" = { - version = "1.0.0"; - sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; - }; - "elm/virtual-dom" = { - version = "1.0.0"; - sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; - }; -} diff --git a/pkgs/development/compilers/elm/packages/elm-srcs.nix b/pkgs/development/compilers/elm/packages/elm-srcs.nix new file mode 100644 index 000000000000..e1f941626dd7 --- /dev/null +++ b/pkgs/development/compilers/elm/packages/elm-srcs.nix @@ -0,0 +1,62 @@ +{ + + "elm-explorations/markdown" = { + sha256 = "0k3110ixa4wwf3vkkdplagwah9ypr965qxr1y147rnsc1xsxmr6y"; + version = "1.0.0"; + }; + + "elm/json" = { + sha256 = "1g0hafkqf2q633r7ir9wxpb1lnlzskhpsyi0h5bkzj0gl072zfnb"; + version = "1.0.0"; + }; + + "elm/html" = { + sha256 = "1n3gpzmpqqdsldys4ipgyl1zacn0kbpc3g4v3hdpiyfjlgh8bf3k"; + version = "1.0.0"; + }; + + "elm/svg" = { + sha256 = "08x0v8p9wm699jjmsnbq69pxv3jh60j4f6fg7y6hyr7xxj85y390"; + version = "1.0.0"; + }; + + "elm/project-metadata-utils" = { + sha256 = "1d4rd4grrnbdvj9gf00h7dr6hbkjzawgkzpizfrkp1z1pyr3mvq9"; + version = "1.0.0"; + }; + + "elm/browser" = { + sha256 = "1apmvyax93nvmagwj00y16zx10kfv640cxpi64xgqbgy7d2wphy4"; + version = "1.0.0"; + }; + + "elm/core" = { + sha256 = "10kr86h4v5h4p0586q406a5wbl8xvr1jyrf6097zp2wb8sv21ylw"; + version = "1.0.0"; + }; + + "elm/http" = { + sha256 = "1igmm89ialzrjib1j8xagkxalq1x2gj4l0hfxcd66mpwmvg7psl8"; + version = "1.0.0"; + }; + + "elm/parser" = { + sha256 = "0k4zlq30lrvawqvzwbvsl0hrmwf9s832mb41z7fdspm4549dj7wc"; + version = "1.0.0"; + }; + + "elm/url" = { + sha256 = "0av8x5syid40sgpl5vd7pry2rq0q4pga28b4yykn9gd9v12rs3l4"; + version = "1.0.0"; + }; + + "elm/time" = { + sha256 = "0vch7i86vn0x8b850w1p69vplll1bnbkp8s383z7pinyg94cm2z1"; + version = "1.0.0"; + }; + + "elm/virtual-dom" = { + sha256 = "0hm8g92h7z39km325dlnhk8n00nlyjkqp3r3jppr37k2k13md6aq"; + version = "1.0.0"; + }; +} diff --git a/pkgs/development/compilers/elm/packages/elm.nix b/pkgs/development/compilers/elm/packages/elm.nix index 41998f4c9b3d..67e63ea2b8e8 100644 --- a/pkgs/development/compilers/elm/packages/elm.nix +++ b/pkgs/development/compilers/elm/packages/elm.nix @@ -13,6 +13,7 @@ mkDerivation { url = "https://github.com/elm/compiler"; sha256 = "13jks6c6i80z71mjjfg46ri570g5ini0k3xw3857v6z66zcl56x4"; rev = "d5cbc41aac23da463236bbc250933d037da4055a"; + fetchSubmodules = true; }; isLibrary = false; isExecutable = true; diff --git a/pkgs/development/compilers/elm/update.sh b/pkgs/development/compilers/elm/update.sh index 2b5d85feeb28..920b95e5ad95 100755 --- a/pkgs/development/compilers/elm/update.sh +++ b/pkgs/development/compilers/elm/update.sh @@ -1 +1,8 @@ -cabal2nix https://github.com/elm/compiler --revision 32059a289d27e303fa1665e9ada0a52eb688f302 > packages/elm.nix +#!/usr/bin/env nix-shell +#!nix-shell -p cabal2nix elm2nix -i bash ../../.. + +cabal2nix https://github.com/elm/compiler --revision d5cbc41aac23da463236bbc250933d037da4055a > packages/elm.nix +elm2nix snapshot > versions.dat +pushd "$(nix-build -A elmPackages.elm.src --no-out-link ../../../..)/ui/browser" + elm2nix convert > $OLDPWD/packages/elm-srcs.nix +popd diff --git a/pkgs/development/compilers/elm/versions.dat b/pkgs/development/compilers/elm/versions.dat index 824ab383057f2138d4dcd431b52851a2e6b8b127..9dcfd8a2808f666b0cff1a54b79a6543e46451d9 100644 GIT binary patch delta 11082 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�M%Fgl(e@SXts!x#PeXJ2DzgxKJ`5Yf2|d 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 F|2Mqsjt~F<