diff options
Diffstat (limited to 'infra/libkookie/nixpkgs/pkgs/development/compilers/crystal')
4 files changed, 434 insertions, 0 deletions
diff --git a/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/build-package.nix b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/build-package.nix new file mode 100644 index 000000000000..856c6e58bc18 --- /dev/null +++ b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/build-package.nix @@ -0,0 +1,109 @@ +{ stdenv, lib, crystal, shards, git, pkgconfig, which, linkFarm, fetchFromGitHub, installShellFiles }: + +{ # Some projects do not include a lock file, so you can pass one + lockFile ? null + # Generate shards.nix with `nix-shell -p crystal2nix --run crystal2nix` in the projects root +, shardsFile ? null + # We support different builders. To make things more straight forward, make it + # user selectable instead of trying to autodetect +, format ? "make" +, installManPages ? true + # Specify binaries to build in the form { foo.src = "src/foo.cr"; } + # The default `crystal build` options can be overridden with { foo.options = [ "--no-debug" ]; } +, crystalBinaries ? { }, ... }@args: + +assert (builtins.elem format [ "make" "crystal" "shards" ]); + +let + mkDerivationArgs = builtins.removeAttrs args [ + "format" + "installManPages" + "lockFile" + "shardsFile" + "crystalBinaries" + ]; + + crystalLib = linkFarm "crystal-lib" (lib.mapAttrsToList (name: value: { + inherit name; + path = fetchFromGitHub value; + }) (import shardsFile)); + + # we previously had --no-debug here but that is not recommended by upstream + defaultOptions = [ "--release" "--progress" "--verbose" ]; + + buildDirectly = shardsFile == null || crystalBinaries != { }; +in stdenv.mkDerivation (mkDerivationArgs // { + + configurePhase = args.configurePhase or lib.concatStringsSep "\n" ([ + "runHook preConfigure" + ] ++ lib.optional (lockFile != null) "ln -s ${lockFile} ./shard.lock" + ++ lib.optional (shardsFile != null) "ln -s ${crystalLib} lib" + ++ [ "runHook postConfigure "]); + + CRFLAGS = lib.concatStringsSep " " defaultOptions; + + PREFIX = placeholder "out"; + + buildInputs = args.buildInputs or [ ] ++ [ crystal ] + ++ lib.optional (format != "crystal") shards; + + nativeBuildInputs = args.nativeBuildInputs or [ ] ++ [ git installShellFiles pkgconfig which ]; + + buildPhase = args.buildPhase or (lib.concatStringsSep "\n" ([ + "runHook preBuild" + ] ++ lib.optional (format == "make") + ''make ''${buildTargets:-build} $makeFlags'' + ++ lib.optionals (format == "crystal") (lib.mapAttrsToList (bin: attrs: '' + crystal ${lib.escapeShellArgs (["build" "-o" bin + (attrs.src or (throw "No source file for crystal binary ${bin} provided")) + ] ++ (attrs.options or defaultOptions))} + '') crystalBinaries) + ++ lib.optional (format == "shards") + "shards build --local --production ${lib.concatStringsSep " " defaultOptions}" + ++ [ "runHook postBuild" ])); + + installPhase = args.installPhase or (lib.concatStringsSep "\n" ([ + "runHook preInstall" + ] ++ lib.optional (format == "make") + ''make ''${installTargets:-install} $installFlags'' + ++ lib.optionals (format == "crystal") (map (bin: '' + install -Dm555 ${lib.escapeShellArgs [ bin "${placeholder "out"}/bin/${bin}" ]} + '') (lib.attrNames crystalBinaries)) + ++ lib.optional (format == "shards") + ''install -Dm555 bin/* -t $out/bin'' + ++ [ + '' + for f in README* *.md LICENSE; do + test -f $f && install -Dm444 $f -t $out/share/doc/${args.pname} + done + '' + ] ++ (lib.optional installManPages '' + if [ -d man ]; then + installManPage man/*.? + fi + '') ++ [ + "runHook postInstall" + ])); + + doCheck = args.doCheck or true; + + checkPhase = args.checkPhase or (lib.concatStringsSep "\n" ([ + "runHook preCheck" + ] ++ lib.optional (format == "make") + ''make ''${checkTarget:-test} $checkFlags'' + ++ lib.optional (format != "make") + ''crystal ''${checkTarget:-spec} $checkFlags'' + ++ [ "runHook postCheck" ])); + + doInstallCheck = args.doInstallCheck or true; + + installCheckPhase = args.installCheckPhase or '' + for f in $out/bin/*; do + $f --help + done + ''; + + meta = args.meta or { } // { + platforms = args.meta.platforms or crystal.meta.platforms; + }; +}) diff --git a/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/crystal2nix.cr b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/crystal2nix.cr new file mode 100644 index 000000000000..0610de5cfa4d --- /dev/null +++ b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/crystal2nix.cr @@ -0,0 +1,42 @@ +require "yaml" +require "json" + +class PrefetchJSON + JSON.mapping(sha256: String) +end + +class ShardLock + YAML.mapping( + version: Float32, + shards: Hash(String, Hash(String, String)) + ) +end + +File.open "shards.nix", "w+" do |file| + file.puts %({) + yaml = ShardLock.from_yaml(File.read("shard.lock")) + yaml.shards.each do |key, value| + owner, repo = value["github"].split("/") + url = "https://github.com/#{value["github"]}" + rev = if value["version"]? + "v#{value["version"]}" + else + value["commit"] + end + + sha256 = "" + args = ["--url", url, "--rev", rev] + Process.run("@nixPrefetchGit@", args: args) do |x| + x.error.each_line { |e| puts e } + sha256 = PrefetchJSON.from_json(x.output).sha256 + end + + file.puts %( #{key} = {) + file.puts %( owner = "#{owner}";) + file.puts %( repo = "#{repo}";) + file.puts %( rev = "#{rev}";) + file.puts %( sha256 = "#{sha256}";) + file.puts %( };) + end + file.puts %(}) +end diff --git a/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/crystal2nix.nix b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/crystal2nix.nix new file mode 100644 index 000000000000..5fc40cd23741 --- /dev/null +++ b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/crystal2nix.nix @@ -0,0 +1,22 @@ +{ lib, crystal, nix-prefetch-git }: + +crystal.buildCrystalPackage { + pname = "crystal2nix"; + version = "unstable-2018-07-31"; + + nixPrefetchGit = "${lib.getBin nix-prefetch-git}/bin/nix-prefetch-git"; + unpackPhase = "substituteAll ${./crystal2nix.cr} crystal2nix.cr"; + + format = "crystal"; + + crystalBinaries.crystal2nix.src = "crystal2nix.cr"; + + # it will blow up without a shard.yml file + doInstallCheck = false; + + meta = with lib; { + description = "Utility to convert Crystal's shard.lock files to a Nix file"; + license = licenses.mit; + maintainers = with maintainers; [ manveru ]; + }; +} diff --git a/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/default.nix b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/default.nix new file mode 100644 index 000000000000..fa8198fabad9 --- /dev/null +++ b/infra/libkookie/nixpkgs/pkgs/development/compilers/crystal/default.nix @@ -0,0 +1,261 @@ +{ stdenv +, callPackage +, fetchFromGitHub +, fetchurl +, lib +# Dependencies +, boehmgc +, coreutils +, git +, gmp +, hostname +, libatomic_ops +, libevent +, libiconv +, libxml2 +, libyaml +, llvmPackages +, makeWrapper +, openssl +, pcre +, pkgconfig +, readline +, tzdata +, which +, zlib +}: + +# We need multiple binaries as a given binary isn't always able to build +# (even slightly) older or newer versions. +# - 0.26.1 can build 0.25.x and 0.26.x but not 0.27.x +# - 0.27.2 can build 0.27.x but not 0.25.x, 0.26.x and 0.29.x +# +# We need to keep around at least the latest version released with a stable +# NixOS + +let + archs = { + x86_64-linux = "linux-x86_64"; + i686-linux = "linux-i686"; + x86_64-darwin = "darwin-x86_64"; + }; + + arch = archs.${stdenv.system} or (throw "system ${stdenv.system} not supported"); + + checkInputs = [ git gmp openssl readline libxml2 libyaml ]; + + genericBinary = { version, sha256s, rel ? 1 }: + stdenv.mkDerivation rec { + pname = "crystal-binary"; + inherit version; + + src = fetchurl { + url = "https://github.com/crystal-lang/crystal/releases/download/${version}/crystal-${version}-${toString rel}-${arch}.tar.gz"; + sha256 = sha256s.${stdenv.system}; + }; + + buildCommand = '' + mkdir -p $out + tar --strip-components=1 -C $out -xf ${src} + ''; + }; + + commonBuildInputs = extraBuildInputs: [ + boehmgc libatomic_ops pcre libevent libyaml zlib libxml2 openssl + ] ++ extraBuildInputs + ++ stdenv.lib.optionals stdenv.isDarwin [ libiconv ]; + + generic = ( + { version + , sha256 + , binary + , doCheck ? true + , extraBuildInputs ? [] + , buildFlags ? ["all" "docs"] + }: + lib.fix (compiler: stdenv.mkDerivation { + pname = "crystal"; + inherit buildFlags doCheck version; + + src = fetchFromGitHub { + owner = "crystal-lang"; + repo = "crystal"; + rev = version; + inherit sha256; + }; + + outputs = [ "out" "lib" "bin" ]; + + postPatch = '' + # Add dependency of crystal to docs to avoid issue on flag changes between releases + # https://github.com/crystal-lang/crystal/pull/8792#issuecomment-614004782 + substituteInPlace Makefile \ + --replace 'docs: ## Generate standard library documentation' 'docs: crystal ## Generate standard library documentation' + + substituteInPlace src/crystal/system/unix/time.cr \ + --replace /usr/share/zoneinfo ${tzdata}/share/zoneinfo + + ln -sf spec/compiler spec/std + + # Dirty fix for when no sandboxing is enabled + rm -rf /tmp/crystal + mkdir -p /tmp/crystal + + substituteInPlace spec/std/file_spec.cr \ + --replace '/bin/ls' '${coreutils}/bin/ls' \ + --replace '/usr/share' '/tmp/crystal' \ + --replace '/usr' '/tmp' + + substituteInPlace spec/std/process_spec.cr \ + --replace '/bin/cat' '${coreutils}/bin/cat' \ + --replace '/bin/ls' '${coreutils}/bin/ls' \ + --replace '/usr/bin/env' '${coreutils}/bin/env' \ + --replace '"env"' '"${coreutils}/bin/env"' \ + --replace '"/usr"' '"/tmp"' + + substituteInPlace spec/std/socket/tcp_server_spec.cr \ + --replace '{% if flag?(:gnu) %}"listen: "{% else %}"bind: "{% end %}' '"bind: "' + + substituteInPlace spec/std/system_spec.cr \ + --replace '`hostname`' '`${hostname}/bin/hostname`' + + # See https://github.com/crystal-lang/crystal/pull/8640 + substituteInPlace spec/std/http/cookie_spec.cr \ + --replace '01 Jan 2020' '01 Jan #{Time.utc.year + 2}' + + # See https://github.com/crystal-lang/crystal/issues/8629 + substituteInPlace spec/std/socket/udp_socket_spec.cr \ + --replace 'it "joins and transmits to multicast groups"' 'pending "joins and transmits to multicast groups"' + + # See https://github.com/crystal-lang/crystal/pull/8699 + substituteInPlace spec/std/xml/xml_spec.cr \ + --replace 'it "handles errors"' 'pending "handles errors"' + ''; + + buildInputs = commonBuildInputs extraBuildInputs; + + nativeBuildInputs = [ binary makeWrapper which pkgconfig llvmPackages.llvm ]; + + makeFlags = [ + "CRYSTAL_CONFIG_VERSION=${version}" + ]; + + LLVM_CONFIG = "${llvmPackages.llvm}/bin/llvm-config"; + + FLAGS = [ + "--release" + "--single-module" # needed for deterministic builds + ]; + + # This makes sure we don't keep depending on the previous version of + # crystal used to build this one. + CRYSTAL_LIBRARY_PATH = "${placeholder "lib"}/crystal"; + + # We *have* to add `which` to the PATH or crystal is unable to build + # stuff later if which is not available. + installPhase = '' + runHook preInstall + + install -Dm755 .build/crystal $bin/bin/crystal + wrapProgram $bin/bin/crystal \ + --suffix PATH : ${lib.makeBinPath [ pkgconfig llvmPackages.clang which ]} \ + --suffix CRYSTAL_PATH : lib:$lib/crystal \ + --suffix CRYSTAL_LIBRARY_PATH : ${ + lib.makeLibraryPath (commonBuildInputs extraBuildInputs) + } + install -dm755 $lib/crystal + cp -r src/* $lib/crystal/ + + install -dm755 $out/share/doc/crystal/api + cp -r docs/* $out/share/doc/crystal/api/ + cp -r samples $out/share/doc/crystal/ + + install -Dm644 etc/completion.bash $out/share/bash-completion/completions/crystal + install -Dm644 etc/completion.zsh $out/share/zsh/site-functions/_crystal + + install -Dm644 man/crystal.1 $out/share/man/man1/crystal.1 + + install -Dm644 -t $out/share/licenses/crystal LICENSE README.md + + mkdir -p $out + ln -s $bin/bin $out/bin + ln -s $lib $out/lib + + runHook postInstall + ''; + + enableParallelBuilding = true; + + dontStrip = true; + + checkTarget = "compiler_spec"; + + preCheck = '' + export HOME=/tmp + mkdir -p $HOME/test + + export LIBRARY_PATH=${lib.makeLibraryPath checkInputs}:$LIBRARY_PATH + export PATH=${lib.makeBinPath checkInputs}:$PATH + ''; + + passthru.buildCrystalPackage = callPackage ./build-package.nix { + crystal = compiler; + }; + + meta = with lib; { + description = "A compiled language with Ruby like syntax and type inference"; + homepage = "https://crystal-lang.org/"; + license = licenses.asl20; + maintainers = with maintainers; [ david50407 fabianhjr manveru peterhoeg ]; + platforms = builtins.attrNames archs; + }; + }) + ); + +in rec { + binaryCrystal_0_31 = genericBinary { + version = "0.31.1"; + sha256s = { + x86_64-linux = "0r8salf572xrnr4m6ll9q5hz6jj8q7ff1rljlhmqb1r26a8mi2ih"; + i686-linux = "0hridnis5vvrswflx0q67xfg5hryhz6ivlwrb9n4pryj5d1gwjrr"; + x86_64-darwin = "1dgxgv0s3swkc5cwawzgpbc6bcd2nx4hjxc7iw2h907y1vgmbipz"; + }; + }; + + crystal_0_31 = generic { + version = "0.31.1"; + sha256 = "1dswxa32w16gnc6yjym12xj7ibg0g6zk3ngvl76lwdjqb1h6lwz8"; + doCheck = false; # 5 checks are failing now + binary = binaryCrystal_0_31; + }; + + crystal_0_32 = generic { + version = "0.32.1"; + sha256 = "120ndi3nhh2r52hjvhwfb49cdggr1bzdq6b8xg7irzavhjinfza6"; + binary = crystal_0_31; + }; + + crystal_0_33 = generic { + version = "0.33.0"; + sha256 = "1zg0qixcws81s083wrh54hp83ng2pa8iyyafaha55mzrh8293jbi"; + binary = crystal_0_32; + }; + + crystal_0_34 = generic { + version = "0.34.0"; + sha256 = "110lfpxk9jnqyznbfnilys65ixj5sdmy8pvvnlhqhc3ccvrlnmq4"; + binary = crystal_0_33; + }; + + crystal_0_35 = generic { + version = "0.35.1"; + sha256 = "0p51bjl1nsvwsm64lqq421dcsxa201w7wwq8plw4r8wqarpq0g69"; + binary = crystal_0_34; + # Needs git to build as per https://github.com/crystal-lang/crystal/issues/9789 + extraBuildInputs = [ git ]; + }; + + crystal = crystal_0_35; + + crystal2nix = callPackage ./crystal2nix.nix {}; +} |