1{ lib
2, stdenv
3, fetchFromGitHub
4, substituteAll
5, binutils
6, asciidoctor
7, cmake
8, perl
9, zstd
10, bashInteractive
11, xcodebuild
12, makeWrapper
13, nix-update-script
14}:
15
16stdenv.mkDerivation (finalAttrs: {
17 pname = "ccache";
18 version = "4.8.3";
19
20 src = fetchFromGitHub {
21 owner = "ccache";
22 repo = "ccache";
23 rev = "refs/tags/v${finalAttrs.version}";
24 sha256 = "sha256-fcstTjwwOh5SAe6+VT5MpBaD+AEFoQtHop99dOMr7/A=";
25 };
26
27 outputs = [ "out" "man" ];
28
29 patches = [
30 # When building for Darwin, test/run uses dwarfdump, whereas on
31 # Linux it uses objdump. We don't have dwarfdump packaged for
32 # Darwin, so this patch updates the test to also use objdump on
33 # Darwin.
34 # Additionally, when cross compiling, the correct target prefix
35 # needs to be set.
36 (substituteAll {
37 src = ./fix-objdump-path.patch;
38 objdump = "${binutils.bintools}/bin/${binutils.targetPrefix}objdump";
39 })
40 ];
41
42 nativeBuildInputs = [ asciidoctor cmake perl ];
43 buildInputs = [ zstd ];
44
45 cmakeFlags = [
46 # Build system does not autodetect redis library presence.
47 # Requires explicit flag.
48 "-DREDIS_STORAGE_BACKEND=OFF"
49 ];
50
51 doCheck = true;
52 nativeCheckInputs = [
53 # test/run requires the compgen function which is available in
54 # bashInteractive, but not bash.
55 bashInteractive
56 ] ++ lib.optional stdenv.isDarwin xcodebuild;
57
58 checkPhase =
59 let
60 badTests = [
61 "test.trim_dir" # flaky on hydra (possibly filesystem-specific?)
62 ] ++ lib.optionals stdenv.isDarwin [
63 "test.basedir"
64 "test.fileclone" # flaky on hydra (possibly filesystem-specific?)
65 "test.multi_arch"
66 "test.nocpp2"
67 ];
68 in
69 ''
70 runHook preCheck
71 export HOME=$(mktemp -d)
72 ctest --output-on-failure -E '^(${lib.concatStringsSep "|" badTests})$'
73 runHook postCheck
74 '';
75
76 passthru = {
77 # A derivation that provides gcc and g++ commands, but that
78 # will end up calling ccache for the given cacheDir
79 links = { unwrappedCC, extraConfig }: stdenv.mkDerivation {
80 pname = "ccache-links";
81 inherit (finalAttrs) version;
82 passthru = {
83 isClang = unwrappedCC.isClang or false;
84 isGNU = unwrappedCC.isGNU or false;
85 isCcache = true;
86 };
87 inherit (unwrappedCC) lib;
88 nativeBuildInputs = [ makeWrapper ];
89 # Unwrapped clang does not have a targetPrefix because it is multi-target
90 # target is decided with argv0.
91 buildCommand = let
92 targetPrefix = if unwrappedCC.isClang or false
93 then
94 ""
95 else
96 (lib.optionalString (unwrappedCC ? targetConfig && unwrappedCC.targetConfig != null && unwrappedCC.targetConfig != "") "${unwrappedCC.targetConfig}-");
97 in ''
98 mkdir -p $out/bin
99
100 wrap() {
101 local cname="${targetPrefix}$1"
102 if [ -x "${unwrappedCC}/bin/$cname" ]; then
103 makeWrapper ${finalAttrs.finalPackage}/bin/ccache $out/bin/$cname \
104 --run ${lib.escapeShellArg extraConfig} \
105 --add-flags ${unwrappedCC}/bin/$cname
106 fi
107 }
108
109 wrap cc
110 wrap c++
111 wrap gcc
112 wrap g++
113 wrap clang
114 wrap clang++
115
116 for executable in $(ls ${unwrappedCC}/bin); do
117 if [ ! -x "$out/bin/$executable" ]; then
118 ln -s ${unwrappedCC}/bin/$executable $out/bin/$executable
119 fi
120 done
121 for file in $(ls ${unwrappedCC} | grep -vw bin); do
122 ln -s ${unwrappedCC}/$file $out/$file
123 done
124 '';
125 };
126
127 updateScript = nix-update-script { };
128 };
129
130 meta = with lib; {
131 description = "Compiler cache for fast recompilation of C/C++ code";
132 homepage = "https://ccache.dev";
133 downloadPage = "https://ccache.dev/download.html";
134 changelog = "https://ccache.dev/releasenotes.html#_ccache_${
135 builtins.replaceStrings [ "." ] [ "_" ] finalAttrs.version
136 }";
137 license = licenses.gpl3Plus;
138 mainProgram = "ccache";
139 maintainers = with maintainers; [ kira-bruneau r-burns ];
140 platforms = platforms.unix;
141 };
142})