vifm: 0.13 -> 0.14 (#380559)
[NixPkgs.git] / pkgs / development / compilers / crystal / build-package.nix
blobc7c29f12caa473c42f2edef49cbd566af2448cfe
2   stdenv,
3   lib,
4   crystal,
5   pcre2,
6   shards,
7   git,
8   pkg-config,
9   which,
10   linkFarm,
11   fetchgit,
12   fetchFromGitHub,
13   installShellFiles,
14   removeReferencesTo,
18   # Some projects do not include a lock file, so you can pass one
19   lockFile ? null,
20   # Generate shards.nix with `nix-shell -p crystal2nix --run crystal2nix` in the projects root
21   shardsFile ? null,
22   # We support different builders. To make things more straight forward, make it
23   # user selectable instead of trying to autodetect
24   format ? "make",
25   installManPages ? true,
26   # Specify binaries to build in the form { foo.src = "src/foo.cr"; }
27   # The default `crystal build` options can be overridden with { foo.options = [ "--optionname" ]; }
28   crystalBinaries ? { },
29   enableParallelBuilding ? true,
30   # Copy all shards dependencies instead of symlinking and add write permissions
31   # to make environment more local-like
32   copyShardDeps ? false,
33   ...
34 }@args:
36 assert (
37   builtins.elem format [
38     "make"
39     "crystal"
40     "shards"
41   ]
43 let
44   mkDerivationArgs = builtins.removeAttrs args [
45     "format"
46     "installManPages"
47     "lockFile"
48     "shardsFile"
49     "crystalBinaries"
50   ];
52   crystalLib = linkFarm "crystal-lib" (
53     lib.mapAttrsToList (name: value: {
54       inherit name;
55       path = if (builtins.hasAttr "url" value) then fetchgit value else fetchFromGitHub value;
56     }) (import shardsFile)
57   );
59   # We no longer use --no-debug in accordance with upstream's recommendation
60   defaultOptions = [
61     "--release"
62     "--progress"
63     "--verbose"
64   ];
66   buildDirectly = shardsFile == null || crystalBinaries != { };
68   mkCrystalBuildArgs =
69     bin: attrs:
70     lib.concatStringsSep " " (
71       [
72         "crystal"
73         "build"
74       ]
75       ++ lib.optionals enableParallelBuilding [
76         "--threads"
77         "$NIX_BUILD_CORES"
78       ]
79       ++ [
80         "-o"
81         bin
82         (attrs.src or (throw "No source file for crystal binary ${bin} provided"))
83         (lib.concatStringsSep " " (attrs.options or defaultOptions))
84       ]
85     );
88 stdenv.mkDerivation (
89   mkDerivationArgs
90   // {
92     configurePhase =
93       args.configurePhase or (lib.concatStringsSep "\n" (
94         [
95           "runHook preConfigure"
96         ]
97         ++ lib.optional (lockFile != null) "cp ${lockFile} ./shard.lock"
98         ++ lib.optionals (shardsFile != null) [
99           "test -e lib || mkdir lib"
100           (
101             if copyShardDeps then
102               "for d in ${crystalLib}/*; do cp -r $d/ lib/; done; chmod -R +w lib/"
103             else
104               "for d in ${crystalLib}/*; do ln -s $d lib/; done"
105           )
106           "cp shard.lock lib/.shards.info"
107         ]
108         ++ [ "runHook postConfigure" ]
109       ));
111     CRFLAGS = lib.concatStringsSep " " defaultOptions;
113     PREFIX = placeholder "out";
115     inherit enableParallelBuilding;
116     strictDeps = true;
117     buildInputs =
118       args.buildInputs or [ ]
119       ++ [ crystal ]
120       ++ lib.optional (lib.versionAtLeast crystal.version "1.8") pcre2;
122     nativeBuildInputs =
123       args.nativeBuildInputs or [ ]
124       ++ [
125         crystal
126         git
127         installShellFiles
128         removeReferencesTo
129         pkg-config
130         which
131       ]
132       ++ lib.optional (format != "crystal") shards;
134     buildPhase =
135       args.buildPhase or (lib.concatStringsSep "\n" (
136         [
137           "runHook preBuild"
138         ]
139         ++ lib.optional (format == "make") "make \${buildTargets:-build} $makeFlags"
140         ++ lib.optionals (format == "crystal") (lib.mapAttrsToList mkCrystalBuildArgs crystalBinaries)
141         ++
142           lib.optional (format == "shards")
143             "shards build --local --production ${lib.concatStringsSep " " (args.options or defaultOptions)}"
144         ++ [ "runHook postBuild" ]
145       ));
147     installPhase =
148       args.installPhase or (lib.concatStringsSep "\n" (
149         [
150           "runHook preInstall"
151         ]
152         ++ lib.optional (format == "make") "make \${installTargets:-install} $installFlags"
153         ++ lib.optionals (format == "crystal") (
154           map (bin: ''
155             install -Dm555 ${
156               lib.escapeShellArgs [
157                 bin
158                 "${placeholder "out"}/bin/${bin}"
159               ]
160             }
161           '') (lib.attrNames crystalBinaries)
162         )
163         ++ lib.optional (format == "shards") "install -Dm555 bin/* -t $out/bin"
164         ++ [
165           ''
166             for f in README* *.md LICENSE; do
167               test -f $f && install -Dm444 $f -t $out/share/doc/${args.pname}
168             done
169           ''
170         ]
171         ++ (lib.optional installManPages ''
172           if [ -d man ]; then
173             installManPage man/*.?
174           fi
175         '')
176         ++ [
177           "remove-references-to -t ${lib.getLib crystal} $out/bin/*"
178           "runHook postInstall"
179         ]
180       ));
182     doCheck = args.doCheck or true;
184     checkPhase =
185       args.checkPhase or (lib.concatStringsSep "\n" (
186         [
187           "runHook preCheck"
188         ]
189         ++ lib.optional (format == "make") "make \${checkTarget:-test} $checkFlags"
190         ++ lib.optional (format != "make") "crystal \${checkTarget:-spec} $checkFlags"
191         ++ [ "runHook postCheck" ]
192       ));
194     doInstallCheck = args.doInstallCheck or true;
196     installCheckPhase =
197       args.installCheckPhase or ''
198         for f in $out/bin/*; do
199           if [ $f == $out/bin/*.dwarf ]; then
200             continue
201           fi
202           $f --help > /dev/null
203         done
204       '';
206     meta = args.meta or { } // {
207       platforms = args.meta.platforms or crystal.meta.platforms;
208     };
209   }