Skip to content

Instantly share code, notes, and snippets.

@YuMingLiao
Created August 3, 2018 03:46
Show Gist options
  • Save YuMingLiao/1682a571dcad9e3d50a9d6631b1e51db to your computer and use it in GitHub Desktop.
Save YuMingLiao/1682a571dcad9e3d50a9d6631b1e51db to your computer and use it in GitHub Desktop.
{ nixpkgsFunc ? import ./nixpkgs
, system ? builtins.currentSystem
, config ? {}
, enableLibraryProfiling ? false
, enableExposeAllUnfoldings ? true
, enableTraceReflexEvents ? false
, useFastWeak ? true
, useReflexOptimizer ? false
, useTextJSString ? true
, iosSdkVersion ? "10.2"
, iosSdkLocation ? "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${iosSdkVersion}.sdk"
, iosSupportForce ? false
}:
let iosSupport =
if system != "x86_64-darwin" then false
else if iosSupportForce || builtins.pathExists iosSdkLocation then true
else builtins.trace "Warning: No iOS sdk found at ${iosSdkLocation}; iOS support disabled. To enable, either install a version of Xcode that provides that SDK or override the value of iosSdkVersion to match your installed version." false;
globalOverlay = self: super: {
all-cabal-hashes = super.all-cabal-hashes.override {
src-spec = {
owner = "commercialhaskell";
repo = "all-cabal-hashes";
rev = "82a8a1a49240a1b465c95de6fa6bf56323ee858f";
sha256 = "1jdzl5fyp1qcsi1anjig6kglq4jjsdll53nissjcnxpy3jscmarm";
};
};
};
appleLibiconvHack = self: super: {
darwin = super.darwin // {
libiconv =
if self.hostPlatform == self.buildPlatform
then super.darwin.libiconv
else super.darwin.libiconv.overrideAttrs (o: {
postInstall = "rm $out/include/libcharset.h $out/include/localcharset.h";
configureFlags = ["--disable-shared" "--enable-static"];
});
};
};
nixpkgs = nixpkgsFunc ({
inherit system;
overlays = [globalOverlay];
config = {
allowUnfree = true;
allowBroken = true; # GHCJS is marked broken in 011c149ed5e5a336c3039f0b9d4303020cff1d86
permittedInsecurePackages = [
"webkitgtk-2.4.11"
];
packageOverrides = pkgs: {
webkitgtk = pkgs.webkitgtk216x;
# cabal2nix's tests crash on 32-bit linux; see https://github.com/NixOS/cabal2nix/issues/272
${if system == "i686-linux" then "cabal2nix" else null} = pkgs.haskell.lib.dontCheck pkgs.cabal2nix;
};
} // config;
});
inherit (nixpkgs) fetchurl fetchgit fetchgitPrivate fetchFromGitHub;
nixpkgsCross = {
android = nixpkgs.lib.mapAttrs (_: args: if args == null then null else nixpkgsFunc args) rec {
arm64 = {
system = "x86_64-linux";
overlays = [globalOverlay];
crossSystem = {
config = "aarch64-unknown-linux-android";
arch = "arm64";
libc = "bionic";
withTLS = true;
openssl.system = "linux-generic64";
platform = nixpkgs.pkgs.platforms.aarch64-multiplatform;
};
config.allowUnfree = true;
};
arm64Impure = arm64 // {
crossSystem = arm64.crossSystem // { useAndroidPrebuilt = true; };
};
armv7a = {
system = "x86_64-linux";
overlays = [globalOverlay];
crossSystem = {
config = "arm-unknown-linux-androideabi";
arch = "armv7";
libc = "bionic";
withTLS = true;
openssl.system = "linux-generic32";
platform = nixpkgs.pkgs.platforms.armv7l-hf-multiplatform;
};
config.allowUnfree = true;
};
armv7aImpure = armv7a // {
crossSystem = armv7a.crossSystem // { useAndroidPrebuilt = true; };
};
};
ios =
let config = {
allowUnfree = true;
packageOverrides = p: {
darwin = p.darwin // {
ios-cross = p.darwin.ios-cross.override {
# Depending on where ghcHEAD is in your nixpkgs checkout, you may need llvm 39 here instead
inherit (p.llvmPackages_39) llvm clang;
};
};
buildPackages = p.buildPackages // {
osx_sdk = p.buildPackages.callPackage ({ stdenv }:
let version = "10";
in stdenv.mkDerivation rec {
name = "iOS.sdk";
src = p.stdenv.cc.sdk;
unpackPhase = "true";
configurePhase = "true";
buildPhase = "true";
target_prefix = stdenv.lib.replaceStrings ["-"] ["_"] p.targetPlatform.config;
setupHook = ./scripts/setup-hook-ios.sh;
installPhase = ''
mkdir -p $out/
echo "Source is: $src"
cp -r $src/* $out/
'';
meta = with stdenv.lib; {
description = "The IOS OS ${version} SDK";
maintainers = with maintainers; [ copumpkin ];
platforms = platforms.darwin;
license = licenses.unfree;
};
}) {};
};
};
};
in nixpkgs.lib.mapAttrs (_: args: if args == null then null else nixpkgsFunc args) {
simulator64 = {
system = "x86_64-darwin";
overlays = [globalOverlay appleLibiconvHack];
crossSystem = {
useIosPrebuilt = true;
# You can change config/arch/isiPhoneSimulator depending on your target:
# aarch64-apple-darwin14 | arm64 | false
# arm-apple-darwin10 | armv7 | false
# i386-apple-darwin11 | i386 | true
# x86_64-apple-darwin14 | x86_64 | true
config = "x86_64-apple-darwin14";
arch = "x86_64";
isiPhoneSimulator = true;
sdkVer = iosSdkVersion;
useiOSCross = true;
openssl.system = "darwin64-x86_64-cc";
libc = "libSystem";
};
inherit config;
};
arm64 = {
system = "x86_64-darwin";
overlays = [globalOverlay appleLibiconvHack];
crossSystem = {
useIosPrebuilt = true;
# You can change config/arch/isiPhoneSimulator depending on your target:
# aarch64-apple-darwin14 | arm64 | false
# arm-apple-darwin10 | armv7 | false
# i386-apple-darwin11 | i386 | true
# x86_64-apple-darwin14 | x86_64 | true
config = "aarch64-apple-darwin14";
arch = "arm64";
isiPhoneSimulator = false;
sdkVer = iosSdkVersion;
useiOSCross = true;
openssl.system = "ios64-cross";
libc = "libSystem";
};
inherit config;
};
};
};
haskellLib = nixpkgs.haskell.lib;
filterGit = builtins.filterSource (path: type: !(builtins.any (x: x == baseNameOf path) [".git" "tags" "TAGS" "dist"]));
# Retrieve source that is controlled by the hack-* scripts; it may be either a stub or a checked-out git repo
hackGet = p:
if builtins.pathExists (p + "/git.json") then (
let gitArgs = builtins.fromJSON (builtins.readFile (p + "/git.json"));
in if builtins.elem "@" (nixpkgs.lib.stringToCharacters gitArgs.url)
then fetchgitPrivate gitArgs
else fetchgit gitArgs)
else if builtins.pathExists (p + "/github.json") then fetchFromGitHub (builtins.fromJSON (builtins.readFile (p + "/github.json")))
else {
name = baseNameOf p;
outPath = filterGit p;
};
# All imports of sources need to go here, so that they can be explicitly cached
sources = {
ghcjs-boot = hackGet ./ghcjs-boot;
shims = hackGet ./shims;
ghcjs = hackGet ./ghcjs;
};
inherit (nixpkgs.stdenv.lib) optional optionals optionalAttrs;
optionalExtension = cond: overlay: if cond then overlay else _: _: {};
in with haskellLib;
let overrideCabal = pkg: f: if pkg == null then null else haskellLib.overrideCabal pkg f;
replaceSrc = pkg: src: version: overrideCabal pkg (drv: {
inherit src version;
sha256 = null;
revision = null;
editedCabalFile = null;
});
combineOverrides = old: new: (old // new) // {
overrides = nixpkgs.lib.composeExtensions old.overrides new.overrides;
};
makeRecursivelyOverridable = x: old: x.override old // {
override = new: makeRecursivelyOverridable x (combineOverrides old new);
};
foreignLibSmuggleHeaders = pkg: overrideCabal pkg (drv: {
postInstall = ''
cd dist/build/${pkg.pname}/${pkg.pname}-tmp
for header in $(find . | grep '\.h'$); do
local dest_dir=$out/include/$(dirname "$header")
mkdir -p "$dest_dir"
cp "$header" "$dest_dir"
done
'';
});
cabal2nixResult = src: builtins.trace "cabal2nixResult is deprecated; use ghc.haskellSrc2nix or ghc.callCabal2nix instead" (ghc.haskellSrc2nix {
name = "for-unknown-package";
src = "file://${src}";
sha256 = null;
});
addReflexTraceEventsFlag = if enableTraceReflexEvents
then drv: appendConfigureFlag drv "-fdebug-trace-events"
else drv: drv;
addFastWeakFlag = if useFastWeak
then drv: enableCabalFlag drv "fast-weak"
else drv: drv;
extendHaskellPackages = haskellPackages: makeRecursivelyOverridable haskellPackages {
overrides = self: super:
let reflexDom = import (hackGet ./reflex-dom) self nixpkgs;
jsaddlePkgs = import (hackGet ./jsaddle) self;
gargoylePkgs = self.callPackage (hackGet ./gargoyle) self;
ghcjsDom = import (hackGet ./ghcjs-dom) self;
addReflexOptimizerFlag = if useReflexOptimizer && (self.ghc.cross or null) == null
then drv: appendConfigureFlag drv "-fuse-reflex-optimizer"
else drv: drv;
in {
base-compat = self.callHackage "base-compat" "0.9.2" {};
constraints = self.callHackage "constraints" "0.9" {};
servant-auth-server = self.callHackage "servant-auth-server" "0.3.1.0" {};
vector = doJailbreak super.vector;
these = doJailbreak super.these;
aeson-compat = doJailbreak super.aeson-compat;
timezone-series = self.callCabal2nix "timezone-series" (fetchFromGitHub {
owner = "ygale";
repo = "timezone-series";
rev = "9f42baf542c54ad554bd53582819eaa454ed633d";
sha256 = "1axrx8lziwi6pixws4lq3yz871vxi81rib6cpdl62xb5bh9y03j6";
}) {};
timezone-olson = self.callCabal2nix "timezone-olson" (fetchFromGitHub {
owner = "ygale";
repo = "timezone-olson";
rev = "aecec86be48580f23145ffb3bf12a4ae191d12d3";
sha256 = "1xxbwb8z27qbcscbg5qdyzlc2czg5i3b0y04s9h36hfcb07hasnz";
}) {};
quickcheck-instances = doJailbreak super.quickcheck-instances;
haskell-src-meta = self.callHackage "haskell-src-meta" "0.8.0.1" {};
gtk2hs-buildtools = doJailbreak super.gtk2hs-buildtools;
# hindent was overriden with a newer version of haskell-src-exts for some reason
hindent = super.hindent.override { haskell-src-exts = self.haskell-src-exts; };
# Not sure why these tests fail...
hfmt = dontCheck super.hfmt;
########################################################################
# Reflex packages
########################################################################
reflex = addFastWeakFlag (addReflexTraceEventsFlag (addReflexOptimizerFlag (self.callPackage (hackGet ./reflex) {})));
reflex-dom = addReflexOptimizerFlag (doJailbreak reflexDom.reflex-dom);
reflex-dom-core = addReflexOptimizerFlag (doJailbreak reflexDom.reflex-dom-core);
reflex-todomvc = self.callPackage (hackGet ./reflex-todomvc) {};
reflex-aeson-orphans = self.callPackage (hackGet ./reflex-aeson-orphans) {};
haven = self.callHackage "haven" "0.2.0.0" {};
inherit (jsaddlePkgs) jsaddle jsaddle-clib jsaddle-wkwebview jsaddle-webkit2gtk jsaddle-webkitgtk;
jsaddle-warp = dontCheck jsaddlePkgs.jsaddle-warp;
jsaddle-dom = overrideCabal (self.callPackage (hackGet ./jsaddle-dom) {}) (drv: {
# On macOS, the jsaddle-dom build will run out of file handles the first time it runs
preBuild = ''./setup build || true'';
});
inherit (ghcjsDom) ghcjs-dom-jsffi;
# TODO: Fix this in Cabal
# When building a package with no haskell files, cabal haddock shouldn't fail
ghcjs-dom-jsaddle = dontHaddock ghcjsDom.ghcjs-dom-jsaddle;
ghcjs-dom = dontHaddock ghcjsDom.ghcjs-dom;
inherit (gargoylePkgs) gargoyle gargoyle-postgresql;
########################################################################
# Tweaks
########################################################################
gi-glib = self.callPackage ./gi-glib.nix {};
gi-gio = self.callPackage ./gi-gio.nix {};
gi-gtk = self.callPackage ./gi-gtk.nix {
gtk3 = nixpkgs.gnome3.gtk;
};
gi-javascriptcore = self.callPackage ./gi-javascriptcore.nix {};
gi-webkit2 = self.callPackage ./gi-webkit2.nix {
webkitgtk = nixpkgs.webkitgtk216x;
};
gi-gtksource = super.gi-gtksource.override {
inherit (nixpkgs.gnome3) gtksourceview;
};
ghcjs-base-stub = dontHaddock super.ghcjs-base-stub;
haskell-gi-overloading = super.haskell-gi-overloading_0_0;
webkit2gtk3-javascriptcore = super.webkit2gtk3-javascriptcore.override {
webkitgtk = nixpkgs.webkitgtk216x;
};
cabal-macosx = overrideCabal super.cabal-macosx (drv: {
src = fetchFromGitHub {
owner = "obsidiansystems";
repo = "cabal-macosx";
rev = "b1e22331ffa91d66da32763c0d581b5d9a61481b";
sha256 = "1y2qk61ciflbxjm0b1ab3h9lk8cm7m6ln5ranpf1lg01z1qk28m8";
};
doCheck = false;
});
########################################################################
# Fixes to be upstreamed
########################################################################
foundation = dontCheck super.foundation;
MonadCatchIO-transformers = doJailbreak super.MonadCatchIO-transformers;
blaze-builder-enumerator = doJailbreak super.blaze-builder-enumerator;
process-extras = dontCheck super.process-extras;
miso = addBuildDepend (self.callHackage "miso" "0.12.0.0" {}) self.ghcjs-base;
########################################################################
# Packages not in hackage
########################################################################
servant-reflex = self.callCabal2nix "servant-reflex" (fetchFromGitHub {
owner = "imalsogreg";
repo = "servant-reflex";
rev = "5cd3098880741e6ade52ef4477422d9c776e5478";
sha256 = "18yjfamx3k9xd8pz251jsmvhlj4riw0brk2fyvjq00r87cx67a6f";
}) {};
concat = dontHaddock (dontCheck (self.callCabal2nix "concat" (fetchFromGitHub {
owner = "conal";
repo = "concat";
rev = "24a4b8ccc883605ea2b0b4295460be2f8a245154";
sha256 = "0mcwqzjk3f8qymmkbpa80l6mh6aa4vcyxky3gpwbnx19g721mj35";
}) {}));
direct-sqlite = self.callCabal2nix "direct-sqlite" (fetchFromGitHub {
owner = "IreneKnapp";
repo = "direct-sqlite";
rev = "cd1ab3c0ee7894d888be826fc653b75813fd53c9";
sha256 = "13i6lz99x0jb9fgns7brlqnv5s5w4clp26l8c3kxd318r1krvr6w";
}) {};
superconstraints =
# Remove override when assertion fails
assert (super.superconstraints or null) == null;
self.callPackage (self.haskellSrc2nix {
name = "superconstraints";
src = fetchurl {
url = "https://hackage.haskell.org/package/superconstraints-0.0.1/superconstraints.cabal";
sha256 = "0bgc8ldml3533522gp1x2bjiazllknslpl2rvdkd1k1zfdbh3g9m";
};
sha256 = "1gx9p9i5jli91dnvvrc30j04h1v2m3d71i8sxli6qrhplq5y63dk";
}) {};
} // (if enableLibraryProfiling then {
mkDerivation = expr: super.mkDerivation (expr // { enableLibraryProfiling = true; });
} else {});
};
haskellOverlays = import ./haskell-overlays {
inherit
haskellLib
nixpkgs jdk fetchFromGitHub
useReflexOptimizer stage2Script;
androidActivity = hackGet ./android-activity;
};
stage2Script = nixpkgs.runCommand "stage2.nix" {
GEN_STAGE2 = builtins.readFile (nixpkgs.path + "/pkgs/development/compilers/ghcjs/gen-stage2.rb");
buildCommand = ''
echo "$GEN_STAGE2" > gen-stage2.rb && chmod +x gen-stage2.rb
patchShebangs .
./gen-stage2.rb "${sources.ghcjs-boot}" >"$out"
'';
nativeBuildInputs = with nixpkgs; [
ruby cabal2nix
];
} "";
ghcjsCompiler = ghc.callPackage (nixpkgs.path + "/pkgs/development/compilers/ghcjs/base.nix") {
bootPkgs = ghc;
ghcjsSrc = sources.ghcjs;
ghcjsBootSrc = sources.ghcjs-boot;
shims = sources.shims;
stage2 = import stage2Script;
};
ghcjsPackages = nixpkgs.callPackage (nixpkgs.path + "/pkgs/development/haskell-modules") {
ghc = ghcjsCompiler;
compilerConfig = nixpkgs.callPackage (nixpkgs.path + "/pkgs/development/haskell-modules/configuration-ghc-7.10.x.nix") { inherit haskellLib; };
packageSetConfig = nixpkgs.callPackage (nixpkgs.path + "/pkgs/development/haskell-modules/configuration-ghcjs.nix") { inherit haskellLib; };
inherit haskellLib;
};
# TODO: Figure out why this approach doesn't work; it doesn't seem to evaluate our overridden ghc at all
# ghcjsPackages = nixpkgs.haskell.packages.ghcjs.override {
# ghc = builtins.trace "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ghcjsCompiler;
# };
ghcjs = (extendHaskellPackages ghcjsPackages).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghcjs
(optionalExtension useTextJSString haskellOverlays.textJSString)
];
};
ghcHEAD = (extendHaskellPackages nixpkgs.pkgs.haskell.packages.ghcHEAD).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-head
];
};
ghc8_2_1 = (extendHaskellPackages nixpkgs.pkgs.haskell.packages.ghc821).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8_2_1
];
};
ghc = (extendHaskellPackages nixpkgs.pkgs.haskell.packages.ghc802).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8
];
};
ghc7 = (extendHaskellPackages nixpkgs.pkgs.haskell.packages.ghc7103).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-7
];
};
ghc7_8 = (extendHaskellPackages nixpkgs.pkgs.haskell.packages.ghc784).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-7_8
];
};
ghcAndroidArm64 = (extendHaskellPackages nixpkgsCross.android.arm64Impure.pkgs.haskell.packages.ghc821).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8_2_1
haskellOverlays.disableTemplateHaskell
haskellOverlays.android
];
};
ghcAndroidArmv7a = (extendHaskellPackages nixpkgsCross.android.armv7aImpure.pkgs.haskell.packages.ghc821).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8_2_1
haskellOverlays.disableTemplateHaskell
haskellOverlays.android
];
};
ghcIosSimulator64 = (extendHaskellPackages nixpkgsCross.ios.simulator64.pkgs.haskell.packages.ghc821).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8_2_1
];
};
ghcIosArm64 = (extendHaskellPackages nixpkgsCross.ios.arm64.pkgs.haskell.packages.ghc821).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8_2_1
haskellOverlays.disableTemplateHaskell
haskellOverlays.ios
];
};
ghcIosArmv7 = (extendHaskellPackages nixpkgsCross.ios.armv7.pkgs.haskell.packages.ghc821).override {
overrides = nixpkgs.lib.foldr nixpkgs.lib.composeExtensions (_: _: {}) [
(optionalExtension enableExposeAllUnfoldings haskellOverlays.exposeAllUnfoldings)
haskellOverlays.ghc-8_2_1
haskellOverlays.disableTemplateHaskell
haskellOverlays.ios
];
};
#TODO: Separate debug and release APKs
#TODO: Warn the user that the android app name can't include dashes
android = androidWithHaskellPackages { inherit ghcAndroidArm64 ghcAndroidArmv7a; };
androidWithHaskellPackages = { ghcAndroidArm64, ghcAndroidArmv7a }: import ./android {
nixpkgs = nixpkgsFunc { system = "x86_64-linux"; };
inherit nixpkgsCross ghcAndroidArm64 ghcAndroidArmv7a overrideCabal;
};
nix-darwin = fetchFromGitHub {
owner = "3noch"; # TODO: Update to LnL7 once PR is merged: https://github.com/LnL7/nix-darwin/pull/78
repo = "nix-darwin";
rev = "adfe63988d8e0f07739bc7dafd7249c3a78faf96";
sha256 = "0rca00lajdzf8lf2hgwn6mbmii656dnw725y6nnraz4qf87907zq";
};
# TODO: This should probably be upstreamed to nixpkgs.
plistLib = import (nix-darwin + /modules/launchd/lib.nix) { lib = nixpkgs.lib; };
ios = iosWithHaskellPackages ghcIosArm64;
iosWithHaskellPackages = ghcIosArm64: {
buildApp = import ./ios {
inherit ghcIosArm64 plistLib;
nixpkgs = nixpkgsFunc { system = "x86_64-darwin"; };
};
};
in let this = rec {
inherit nixpkgs
nixpkgsCross
overrideCabal
hackGet
extendHaskellPackages
foreignLibSmuggleHeaders
stage2Script
ghc
ghcHEAD
ghc8_2_1
ghc8_0_1
ghc7
ghc7_8
ghcIosSimulator64
ghcIosArm64
ghcIosArmv7
ghcAndroidArm64
ghcAndroidArmv7a
ghcjs
android
androidWithHaskellPackages
ios
iosWithHaskellPackages
filterGit;
androidReflexTodomvc = android.buildApp {
package = p: p.reflex-todomvc;
executableName = "reflex-todomvc";
applicationId = "org.reflexfrp.todomvc";
displayName = "Reflex TodoMVC";
};
iosReflexTodomvc = ios.buildApp {
package = p: p.reflex-todomvc;
executableName = "reflex-todomvc";
bundleIdentifier = "org.reflexfrp.todomvc";
bundleName = "Reflex TodoMVC";
};
setGhcLibdir = ghcLibdir: inputGhcjs:
let libDir = "$out/lib/ghcjs-${inputGhcjs.version}";
ghcLibdirLink = nixpkgs.stdenv.mkDerivation {
name = "ghc_libdir";
inherit ghcLibdir;
buildCommand = ''
mkdir -p ${libDir}
echo "$ghcLibdir" > ${libDir}/ghc_libdir_override
'';
};
in inputGhcjs // {
outPath = nixpkgs.buildEnv {
inherit (inputGhcjs) name;
paths = [ inputGhcjs ghcLibdirLink ];
postBuild = ''
mv ${libDir}/ghc_libdir_override ${libDir}/ghc_libdir
'';
};
};
platforms = [
"ghcjs"
"ghc"
];
attrsToList = s: map (name: { inherit name; value = builtins.getAttr name s; }) (builtins.attrNames s);
mapSet = f: s: builtins.listToAttrs (map ({name, value}: {
inherit name;
value = f value;
}) (attrsToList s));
mkSdist = pkg: pkg.override {
mkDerivation = drv: ghc.mkDerivation (drv // {
postConfigure = ''
./Setup sdist
mkdir "$out"
mv dist/*.tar.gz "$out/${drv.pname}-${drv.version}.tar.gz"
exit 0
'';
doHaddock = false;
});
};
sdists = mapSet mkSdist ghc;
mkHackageDocs = pkg: pkg.override {
mkDerivation = drv: ghc.mkDerivation (drv // {
postConfigure = ''
./Setup haddock --hoogle --hyperlink-source --html --for-hackage --haddock-option=--built-in-themes
cd dist/doc/html
mkdir "$out"
tar cz --format=ustar -f "$out/${drv.pname}-${drv.version}-docs.tar.gz" "${drv.pname}-${drv.version}-docs"
exit 0
'';
doHaddock = false;
});
};
hackageDocs = mapSet mkHackageDocs ghc;
mkReleaseCandidate = pkg: nixpkgs.stdenv.mkDerivation (rec {
name = pkg.name + "-rc";
sdist = mkSdist pkg + "/${pkg.pname}-${pkg.version}.tar.gz";
docs = mkHackageDocs pkg + "/${pkg.pname}-${pkg.version}-docs.tar.gz";
builder = builtins.toFile "builder.sh" ''
source $stdenv/setup
mkdir "$out"
echo -n "${pkg.pname}-${pkg.version}" >"$out/pkgname"
ln -s "$sdist" "$docs" "$out"
'';
# 'checked' isn't used, but it is here so that the build will fail if tests fail
checked = overrideCabal pkg (drv: {
doCheck = true;
src = sdist;
});
});
releaseCandidates = mapSet mkReleaseCandidate ghc;
androidDevTools = [
ghc.haven
nixpkgs.maven
nixpkgs.androidsdk
];
# Tools that are useful for development under both ghc and ghcjs
generalDevToolsAttrs = haskellPackages:
let nativeHaskellPackages = ghc;
in {
inherit (nativeHaskellPackages)
Cabal
cabal-install
ghcid
hasktags
hlint;
inherit (nixpkgs)
cabal2nix
curl
nix-prefetch-scripts
nodejs
pkgconfig
closurecompiler;
} // (optionalAttrs (!(haskellPackages.ghc.isGhcjs or false) && builtins.compareVersions haskellPackages.ghc.version "8.2" < 0) {
# ghc-mod doesn't currently work on ghc 8.2.2; revisit when https://github.com/DanielG/ghc-mod/pull/911 is closed
# When ghc-mod is included in the environment without being wrapped in justStaticExecutables, it prevents ghc-pkg from seeing the libraries we install
ghc-mod = (nixpkgs.haskell.lib.justStaticExecutables nativeHaskellPackages.ghc-mod);
inherit (haskellPackages) hdevtools;
}) // (optionalAttrs (builtins.compareVersions haskellPackages.ghc.version "7.10" >= 0) {
inherit (nativeHaskellPackages) stylish-haskell; # Recent stylish-haskell only builds with AMP in place
});
generalDevTools = haskellPackages: builtins.attrValues (generalDevToolsAttrs haskellPackages);
nativeHaskellPackages = haskellPackages:
if haskellPackages.isGhcjs or false
then haskellPackages.ghc
else haskellPackages;
workOn = haskellPackages: package: (overrideCabal package (drv: {
buildDepends = (drv.buildDepends or []) ++ generalDevTools (nativeHaskellPackages haskellPackages);
})).env;
workOnMulti' = { env, packageNames, tools ? _: [], shellToolOverrides ? _: _: {} }:
let ghcEnv =
let inherit (builtins) filter all concatLists;
dependenciesOf = x: (x.buildDepends or [])
++ (x.libraryHaskellDepends or [])
++ (x.executableHaskellDepends or [])
++ (x.testHaskellDepends or []);
elemByPname = p: all (pname: (p.pname or "") != pname) packageNames;
overiddenOut = pkgEnv: n: (overrideCabal pkgEnv.${n} (args: {
passthru = (args.passthru or {}) // {
out = filter elemByPname (dependenciesOf args);
};
})).out;
in env.ghc.withPackages (pkgEnv: concatLists (map (overiddenOut pkgEnv) packageNames));
baseTools = generalDevToolsAttrs env;
overriddenTools = baseTools // shellToolOverrides env baseTools;
in nixpkgs.runCommand "shell" (ghcEnv.ghcEnvVars // {
buildInputs = [
ghcEnv
] ++ builtins.attrValues overriddenTools ++ tools env;
}) "";
workOnMulti = env: packageNames: workOnMulti' { inherit env packageNames; };
# A simple derivation that just creates a file with the names of all of its inputs. If built, it will have a runtime dependency on all of the given build inputs.
pinBuildInputs = drvName: buildInputs: otherDeps: nixpkgs.runCommand drvName {
buildCommand = ''
mkdir "$out"
echo "$propagatedBuildInputs $buildInputs $nativeBuildInputs $propagatedNativeBuildInputs $otherDeps" > "$out/deps"
'';
inherit buildInputs otherDeps;
} "";
# The systems that we want to build for on the current system
cacheTargetSystems = [
"x86_64-linux"
"i686-linux"
"x86_64-darwin"
];
isSuffixOf = suffix: s:
let suffixLen = builtins.stringLength suffix;
in builtins.substring (builtins.stringLength s - suffixLen) suffixLen s == suffix;
reflexEnv = platform:
let haskellPackages = builtins.getAttr platform this;
ghcWithStuff = if platform == "ghc" || platform == "ghcjs" then haskellPackages.ghcWithHoogle else haskellPackages.ghcWithPackages;
in ghcWithStuff (p: import ./packages.nix { haskellPackages = p; inherit platform; });
tryReflexPackages = generalDevTools ghc
++ builtins.map reflexEnv platforms;
cachePackages =
let otherPlatforms = optionals (system == "x86_64-linux") [
"ghcAndroidArm64"
"ghcAndroidArmv7a"
] ++ optional iosSupport "ghcIosArm64";
in tryReflexPackages
++ builtins.map reflexEnv otherPlatforms
++ optionals (system == "x86_64-linux") [
androidDevTools
androidReflexTodomvc
] ++ optionals iosSupport [
iosReflexTodomvc
];
demoVM = (import "${nixpkgs.path}/nixos" {
configuration = {
imports = [
"${nixpkgs.path}/nixos/modules/virtualisation/virtualbox-image.nix"
"${nixpkgs.path}/nixos/modules/profiles/demo.nix"
];
environment.systemPackages = tryReflexPackages;
};
}).config.system.build.virtualBoxOVA;
lib = haskellLib;
inherit cabal2nixResult sources system iosSupport;
project = args: import ./project this (args ({ pkgs = nixpkgs; } // this));
tryReflexShell = pinBuildInputs ("shell-" + system) tryReflexPackages [];
js-framework-benchmark-src = hackGet ./js-framework-benchmark;
ghcjsExternsJs = ./ghcjs.externs.js;
}; in this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment