diff --git a/HACKING.md b/HACKING.md index 596f40c..47f4385 100644 --- a/HACKING.md +++ b/HACKING.md @@ -11,33 +11,33 @@ develop/maintain Megaparsec. ## Development with `ghcid` -We use `nix` for development. First enter the `nix-shell`: +We use `nix` for development. First enter the Nix shell: ```console -$ nix-shell +$ nix develop ``` Inside the shell you can: -* Build the `megaparsec` and `megaparsec-tests` packages with `cabal - new-build all`. +* Build the `megaparsec` and `megaparsec-tests` packages with `cabal build + all`. -* Run tests from the `megaparsec-tests` package with `cabal new-test all`. +* Run tests from the `megaparsec-tests` package with `cabal test all`. * Run `ghcid` for interactive feedback as you edit with `ghcid - --command="cabal new-repl megaparsec"` or `ghcid --command="cabal new-repl + --command="cabal repl megaparsec"` or `ghcid --command="cabal repl megaparsec-tests --enable-tests"` depending on the package you're editing. ## Running unit tests The tests in `megaparsec-tests` are usually not enough to gain confidence in -your changes. It is wise to use tests from other packages: +non-trivial changes. It is wise to use tests from other packages: ```console -$ nix-build -A base --no-out-link +$ nix build .#all_base --no-link ``` -`base` derivation includes building and testing the following packages: +The `base` group includes building and testing the following packages: * `megaparsec` * `hspec-megaparsec` @@ -48,7 +48,7 @@ It is worth noting that individual derivations from `base` can be built like this: ```console -$ nix-build -A base.parser-combinators-tests --no-out-link +$ nix build .#base/parser-combinators-tests --no-link ``` ## Checking dependent packages @@ -56,7 +56,7 @@ $ nix-build -A base.parser-combinators-tests --no-out-link To find out how your changes affect a selected set of dependent packages do: ```console -$ nix-build -A deps --no-out-link +$ nix build .#all_deps --no-link ``` The “selected set” includes packages that are known to be high-quality, @@ -64,7 +64,7 @@ well-tested, and non-trivial, so they are good targets for this sort of testing. You can also try to build and test a particular package like this: ```console -$ nix-build -A deps.mmark --no-out-link +$ nix build .#deps/mmark --no-link ``` When you introduce a breaking change, some packages may stop compiling. @@ -92,7 +92,7 @@ current dev version of Megaparsec. To do so, follow these steps: ```nix # Dependent packages of interest: - deps = pkgs.recurseIntoAttrs { + deps = { # ... idris = patch haskellPackages.idris ./nix/patches/idris.patch; }; @@ -103,19 +103,19 @@ current dev version of Megaparsec. To do so, follow these steps: To build all benchmarks run: ```console -$ nix-build -A benches +$ nix build .#all_benches ``` -This will create several `result-*` symlinks with benchmarks. It is also -possible to build benchmarks for just a specific package: +This will create several symlinks in `result`. It is also possible to build +benchmarks for just a specific package: ```console -$ nix-build -A benches.megaparsec # builds megaparsec's microbenchmarks +$ nix build .#benches/megaparsec # builds megaparsec's microbenchmarks ``` -`cd` to `result/bench` and run benchmarks from there because some benchmarks -need data to run on and the paths are relative, so it'll fail if run from -root of Megaparsec's repo. +`cd` to the `bench` sub-directory and run benchmarks from there because some +benchmarks need data to run on and the paths are relative, so it'll fail if +run from the root of Megaparsec's repo. ## Releasing a new version @@ -132,15 +132,16 @@ To release a new version of Megaparsec, follow these steps: * Generate distribution tarballs by running: ```console - $ nix-build -A dist + $ nix build .#all_dist ``` - This will create two symlinks to directories containing the tarballs. - Typically they are called `result` and `result-2`. + This will create `result` with two symlinks to directories containing the + tarballs. Typically they are called `result/megaparsec-source-*` and + `result/megaparsec-tests-source-*`. * To upload the tarballs to Hackage, execute the following: ```console - $ cabal upload --publish result/megaparsec-*.tar.gz - $ cabal upload --publish result-2/megaparsec-tests-*.tar.gz + $ cabal upload --publish result/megaparsec-source-*/megaparsec-*.tar.gz + $ cabal upload --publish result/megaparsec-tests-source-*/megaparsec-tests-*.tar.gz ``` diff --git a/cabal.project b/cabal.project index 28b8c09..8b675a6 100644 --- a/cabal.project +++ b/cabal.project @@ -1,2 +1 @@ -packages: megaparsec.cabal - , megaparsec-tests/megaparsec-tests.cabal +packages: . megaparsec-tests diff --git a/default.nix b/default.nix deleted file mode 100644 index c741aeb..0000000 --- a/default.nix +++ /dev/null @@ -1,146 +0,0 @@ -{ pkgs ? (import ./nix/nixpkgs) -, ghc ? "ghc884" -}: - -let - - megaparsecSource = pkgs.lib.sourceByRegex ./. [ - "^CHANGELOG\.md$" - "^LICENSE\.md$" - "^README\.md$" - "^Text.*$" - "^bench.*$" - "^megaparsec\.cabal$" - ]; - - megaparsecTestsSource = pkgs.lib.sourceByRegex ./megaparsec-tests [ - "^LICENSE\.md$" - "^README\.md$" - "^megaparsec-tests\.cabal$" - "^src.*$" - "^tests.*$" - ]; - - parsersBenchSource = pkgs.lib.sourceByRegex ./parsers-bench [ - "^README\.md$" - "^parsers-bench\.cabal$" - "^ParsersBench.*$" - "^bench.*$" - "^data.*$" - ]; - - doBenchmark = p: - let targets = ["bench-speed" "bench-memory"]; - copying = pkgs.lib.concatMapStrings - (t: "cp dist/build/${t}/${t} $out/bench/\n") - targets; - in pkgs.haskell.lib.doBenchmark - (p.overrideAttrs (drv: { - postInstall = '' - mkdir -p $out/bench - if test -d data/ - then - mkdir -p $out/bench/data - cp data/* $out/bench/data/ - fi - ${copying} - ''; - })); - - doJailbreak = pkgs.haskell.lib.doJailbreak; - - megaparsecOverlay = self: super: { - "megaparsec" = doBenchmark - (super.callCabal2nix "megaparsec" megaparsecSource { }); - "megaparsec-tests" = - super.callCabal2nix "megaparsec-tests" megaparsecTestsSource { }; - # The ‘parser-combinators-tests’ package is a bit special because it - # does not contain an executable nor a library, so its install phase - # normally fails. We want to build it and run the tests anyway, so we - # have to do these manipulations. - "parser-combinators-tests" = pkgs.haskell.lib.dontHaddock - (super.parser-combinators-tests.overrideAttrs (drv: { - installPhase = "mkdir $out"; - broken = false; - })); - "modern-uri" = doBenchmark super.modern-uri; - "parsers-bench" = doBenchmark - (super.callCabal2nix "parsers-bench" parsersBenchSource { }); - "hspec-megaparsec" = super.hspec-megaparsec_2_2_0; - "dhall" = doJailbreak (patch super.dhall ./nix/patches/dhall.patch); - "idris" = doJailbreak (patch super.idris ./nix/patches/idris.patch); - "tomland" = super.tomland_1_3_1_0; - "stache" = super.stache_2_2_0; - "language-puppet" = doJailbreak super.language-puppet; - }; - - updatedPkgs = pkgs // { - haskell = pkgs.haskell // { - packages = pkgs.haskell.packages // { - "${ghc}" = pkgs.haskell.packages.${ghc}.override { - overrides = megaparsecOverlay; - }; - }; - }; - }; - - haskellPackages = updatedPkgs.haskell.packages.${ghc}; - - patch = p: patch: - pkgs.haskell.lib.appendPatch p patch; - -in { - # Base: Megaparsec and its unit tests: - base = pkgs.recurseIntoAttrs { - inherit (haskellPackages) - hspec-megaparsec - megaparsec - megaparsec-tests - parser-combinators-tests; - }; - - # Dependent packages of interest: - deps = pkgs.recurseIntoAttrs { - inherit (haskellPackages) - cachix - cassava-megaparsec - cue-sheet - dhall - hledger - hnix - idris - language-puppet - mmark - modern-uri - replace-megaparsec - stache - tomland; - }; - - # Benchmarks: - benches = pkgs.recurseIntoAttrs { - inherit (haskellPackages) - megaparsec - mmark - modern-uri - parsers-bench; - }; - - # For development: - shell = haskellPackages.shellFor { - packages = ps: [ - ps.megaparsec - ps.megaparsec-tests - ]; - buildInputs = with haskellPackages; [ - cabal-install - ghcid - ]; - }; - - # Distribution tarballs: - dist = with pkgs.haskell.lib; pkgs.recurseIntoAttrs { - megaparsec = sdistTarball haskellPackages.megaparsec; - megaparsec-tests = sdistTarball haskellPackages.megaparsec-tests; - }; -} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c17c00e --- /dev/null +++ b/flake.lock @@ -0,0 +1,43 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1668443372, + "narHash": "sha256-lXNlVyNWwO22/JUdBtUWz68jZB3DM+Jq/irlsbwncI0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "dad4de1694cd92d9a0e123bfdf134d0047b836a5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..de30811 --- /dev/null +++ b/flake.nix @@ -0,0 +1,169 @@ +{ + description = "Megaparsec Nix helpers"; + inputs = { + nixpkgs = { + type = "github"; + owner = "NixOS"; + repo = "nixpkgs"; + ref = "nixpkgs-unstable"; + }; + flake-utils = { + type = "github"; + owner = "numtide"; + repo = "flake-utils"; + }; + }; + outputs = { self, nixpkgs, flake-utils }: + let + pkgs = import nixpkgs { + system = "x86_64-linux"; + config.allowBroken = true; + }; + ghc = "ghc924"; + + megaparsecSource = pkgs.lib.sourceByRegex ./. [ + "^CHANGELOG\.md$" + "^LICENSE\.md$" + "^README\.md$" + "^Text.*$" + "^bench.*$" + "^megaparsec\.cabal$" + ]; + + megaparsecTestsSource = pkgs.lib.sourceByRegex ./megaparsec-tests [ + "^LICENSE\.md$" + "^README\.md$" + "^megaparsec-tests\.cabal$" + "^src.*$" + "^tests.*$" + ]; + + parsersBenchSource = pkgs.lib.sourceByRegex ./parsers-bench [ + "^README\.md$" + "^parsers-bench\.cabal$" + "^ParsersBench.*$" + "^bench.*$" + "^data.*$" + ]; + + doBenchmark = p: + let + targets = [ "bench-speed" "bench-memory" ]; + copying = pkgs.lib.concatMapStrings + (t: "cp dist/build/${t}/${t} $out/bench/\n") + targets; + in + pkgs.haskell.lib.doBenchmark + (p.overrideAttrs (drv: { + postInstall = '' + mkdir -p $out/bench + if test -d data/ + then + mkdir -p $out/bench/data + cp data/* $out/bench/data/ + fi + ${copying} + ''; + })); + + doJailbreak = pkgs.haskell.lib.doJailbreak; + + patch = p: patch: + pkgs.haskell.lib.appendPatch p patch; + + megaparsecOverlay = self: super: { + "megaparsec" = doBenchmark + (super.callCabal2nix "megaparsec" megaparsecSource { }); + "megaparsec-tests" = + super.callCabal2nix "megaparsec-tests" megaparsecTestsSource { }; + # The ‘parser-combinators-tests’ package is a bit special because it + # does not contain an executable nor a library, so its install phase + # normally fails. We want to build it and run the tests anyway, so we + # have to do these manipulations. + "parser-combinators-tests" = pkgs.haskell.lib.dontHaddock + (super.parser-combinators-tests.overrideAttrs (drv: { + installPhase = "mkdir $out"; + })); + "modern-uri" = doBenchmark super.modern-uri; + "parsers-bench" = doBenchmark + (super.callCabal2nix "parsers-bench" parsersBenchSource { }); + }; + + updatedPkgs = pkgs // { + haskell = pkgs.haskell // { + packages = pkgs.haskell.packages // { + "${ghc}" = pkgs.haskell.packages.${ghc}.override { + overrides = megaparsecOverlay; + }; + }; + }; + }; + + haskellPackages = updatedPkgs.haskell.packages.${ghc}; + + # Base: Megaparsec and its unit tests: + base = { + inherit (haskellPackages) + hspec-megaparsec + megaparsec + megaparsec-tests + parser-combinators-tests; + }; + + # Dependent packages of interest: + deps = { + inherit (haskellPackages) + cachix + cassava-megaparsec + cue-sheet + dhall + hledger + idris + mmark + modern-uri + replace-megaparsec + stache + tomland; + }; + + # Benchmarks: + benches = { + inherit (haskellPackages) + megaparsec + mmark + modern-uri + parsers-bench; + }; + + # Source distributions: + dist = with pkgs.haskell.lib; { + megaparsec = sdistTarball haskellPackages.megaparsec; + megaparsec-tests = sdistTarball haskellPackages.megaparsec-tests; + }; + + in + flake-utils.lib.eachDefaultSystem (system: + { + packages = flake-utils.lib.flattenTree { + base = pkgs.recurseIntoAttrs base; + all_base = pkgs.linkFarmFromDrvs "base" (builtins.attrValues base); + deps = pkgs.recurseIntoAttrs deps; + all_deps = pkgs.linkFarmFromDrvs "deps" (builtins.attrValues deps); + benches = pkgs.recurseIntoAttrs benches; + all_benches = pkgs.linkFarmFromDrvs "benches" (builtins.attrValues benches); + dist = pkgs.recurseIntoAttrs dist; + all_dist = pkgs.linkFarmFromDrvs "dist" (builtins.attrValues dist); + }; + defaultPackage = base.megaparsec; + devShells.default = haskellPackages.shellFor { + packages = ps: [ + ps.megaparsec + ps.megaparsec-tests + ]; + buildInputs = with haskellPackages; [ + cabal-install + ghcid + ]; + }; + }); +} diff --git a/nix/nixpkgs/default.nix b/nix/nixpkgs/default.nix deleted file mode 100644 index 3007c54..0000000 --- a/nix/nixpkgs/default.nix +++ /dev/null @@ -1,12 +0,0 @@ -let - rev = "84d74ae9c9cbed73274b8e4e00be14688ffc93fe"; - sha256 = "0ww70kl08rpcsxb9xdx8m48vz41dpss4hh3vvsmswll35l158x0v"; - nixpkgs = builtins.fetchTarball { - url = "https://github.com/NixOS/nixpkgs/archive/${rev}.tar.gz"; - inherit sha256; - }; - pkgs = import nixpkgs { - config.allowBroken = true; - config.allowUnfree = true; - }; -in pkgs diff --git a/nix/patches/dhall.patch b/nix/patches/dhall.patch deleted file mode 100644 index 8a98b04..0000000 --- a/nix/patches/dhall.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/Dhall/Parser/Expression.hs b/src/Dhall/Parser/Expression.hs -index 3cd51406..0def6b22 100644 ---- a/src/Dhall/Parser/Expression.hs -+++ b/src/Dhall/Parser/Expression.hs -@@ -36,7 +36,7 @@ import Dhall.Parser.Combinators - import Dhall.Parser.Token - - -- | Get the current source position --getSourcePos :: Text.Megaparsec.MonadParsec e s m => -+getSourcePos :: (Text.Megaparsec.MonadParsec e s m, Text.Megaparsec.TraversableStream s) => - m Text.Megaparsec.SourcePos - getSourcePos = - Text.Megaparsec.getSourcePos diff --git a/nix/patches/idris.patch b/nix/patches/idris.patch deleted file mode 100644 index c82c7bc..0000000 --- a/nix/patches/idris.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/src/Idris/Parser/Stack.hs b/src/Idris/Parser/Stack.hs -index fb7b61144..991f50d48 100644 ---- a/src/Idris/Parser/Stack.hs -+++ b/src/Idris/Parser/Stack.hs -@@ -84,7 +84,7 @@ instance Message ParseError where - (pos, _) = P.reachOffsetNoLine (parseErrorOffset err) (parseErrorPosState err) - #endif - messageText = PP.text . init . P.parseErrorTextPretty . parseError -- messageSource err = Just sline -+ messageSource err = sline - where - #if MIN_VERSION_megaparsec(8,0,0) - (sline, _) = P.reachOffset (parseErrorOffset err) (parseErrorPosState err)