1{ config, pkgs, lib, ... }:
2
3with lib;
4let
5 cfg = config.programs.ccache;
6in {
7 options.programs.ccache = {
8 # host configuration
9 enable = mkEnableOption (lib.mdDoc "CCache");
10 cacheDir = mkOption {
11 type = types.path;
12 description = lib.mdDoc "CCache directory";
13 default = "/var/cache/ccache";
14 };
15 # target configuration
16 packageNames = mkOption {
17 type = types.listOf types.str;
18 description = lib.mdDoc "Nix top-level packages to be compiled using CCache";
19 default = [];
20 example = [ "wxGTK32" "ffmpeg" "libav_all" ];
21 };
22 };
23
24 config = mkMerge [
25 # host configuration
26 (mkIf cfg.enable {
27 systemd.tmpfiles.rules = [ "d ${cfg.cacheDir} 0770 root nixbld -" ];
28
29 # "nix-ccache --show-stats" and "nix-ccache --clear"
30 security.wrappers.nix-ccache = {
31 owner = "root";
32 group = "nixbld";
33 setuid = false;
34 setgid = true;
35 source = pkgs.writeScript "nix-ccache.pl" ''
36 #!${pkgs.perl}/bin/perl
37
38 %ENV=( CCACHE_DIR => '${cfg.cacheDir}' );
39 sub untaint {
40 my $v = shift;
41 return '-C' if $v eq '-C' || $v eq '--clear';
42 return '-V' if $v eq '-V' || $v eq '--version';
43 return '-s' if $v eq '-s' || $v eq '--show-stats';
44 return '-z' if $v eq '-z' || $v eq '--zero-stats';
45 exec('${pkgs.ccache}/bin/ccache', '-h');
46 }
47 exec('${pkgs.ccache}/bin/ccache', map { untaint $_ } @ARGV);
48 '';
49 };
50 })
51
52 # target configuration
53 (mkIf (cfg.packageNames != []) {
54 nixpkgs.overlays = [
55 (self: super: genAttrs cfg.packageNames (pn: super.${pn}.override { stdenv = builtins.trace "with ccache: ${pn}" self.ccacheStdenv; }))
56
57 (self: super: {
58 ccacheWrapper = super.ccacheWrapper.override {
59 extraConfig = ''
60 export CCACHE_COMPRESS=1
61 export CCACHE_DIR="${cfg.cacheDir}"
62 export CCACHE_UMASK=007
63 if [ ! -d "$CCACHE_DIR" ]; then
64 echo "====="
65 echo "Directory '$CCACHE_DIR' does not exist"
66 echo "Please create it with:"
67 echo " sudo mkdir -m0770 '$CCACHE_DIR'"
68 echo " sudo chown root:nixbld '$CCACHE_DIR'"
69 echo "====="
70 exit 1
71 fi
72 if [ ! -w "$CCACHE_DIR" ]; then
73 echo "====="
74 echo "Directory '$CCACHE_DIR' is not accessible for user $(whoami)"
75 echo "Please verify its access permissions"
76 echo "====="
77 exit 1
78 fi
79 '';
80 };
81 })
82 ];
83 })
84 ];
85}