Use zlib compression for the cached files

See <http://www.gustaebel.de/lars/ccache/>.
This commit is contained in:
Lars Gustäbel 2009-11-01 19:39:58 +01:00 committed by Joel Rosdahl
parent 8fd41240fe
commit 3d7e33e81e
10 changed files with 597 additions and 34 deletions

View File

@ -13,6 +13,7 @@ CFLAGS=$(CPPFLAGS) @CFLAGS@
LDFLAGS=@LDFLAGS@
EXEEXT=@EXEEXT@
LIBS= @LIBS@
OBJS= ccache.o mdfour.o hash.o execute.o util.o args.o stats.o \
cleanup.o snprintf.o unify.o
HEADERS = ccache.h mdfour.h
@ -22,7 +23,7 @@ all: ccache$(EXEEXT)
docs: ccache.1 web/ccache-man.html
ccache$(EXEEXT): $(OBJS) $(HEADERS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJS) $(LIBS)
ccache.1: ccache.yo
-yodl2man -o ccache.1 ccache.yo

View File

@ -210,7 +210,8 @@ If you set the environment variable
CCACHE_HARDLINK then ccache will attempt to use hard links from the
cache directory when creating the compiler output rather than using a
file copy\&. Using hard links is faster, but can confuse programs like
\&'make\&' that rely on modification times\&.
\&'make\&' that rely on modification times\&. Hard links are never made for
compressed cache files\&.
.IP
.IP "\fBCCACHE_RECACHE\fP"
This forces ccache to not use any cached
@ -267,6 +268,11 @@ systems like this you can use the CCACHE_EXTENSION option to override
the default\&. On HP-UX set this environment variable to "i" if you use
the aCC compiler\&.
.IP
.IP "\fBCCACHE_NOCOMPRESS\fP"
If you set the environment variable
CCACHE_NOCOMPRESS then there is no compression used on files that go
into the cache\&.
.IP
.PP
.SH "CACHE SIZE MANAGEMENT"
.PP
@ -279,6 +285,14 @@ When these limits are reached ccache will reduce the cache to 20%
below the numbers you specified in order to avoid doing the cache
clean operation too often\&.
.PP
.SH "CACHE COMPRESSION"
.PP
By default ccache will compress all files it puts into the cache
using the zlib compression\&. While this involves a negligible
performance slowdown, it significantly increases the number of files
that fit in the cache\&. You can turn off compression setting the
CCACHE_NOCOMPRESS environment variable\&.
.PP
.SH "HOW IT WORKS"
.PP
The basic idea is to detect when you are compiling exactly the same

View File

@ -199,7 +199,7 @@ static void to_cache(ARGS *args)
fd = open(tmp_stderr, O_RDONLY | O_BINARY);
if (fd != -1) {
if (strcmp(output_file, "/dev/null") == 0 ||
rename(tmp_hashname, output_file) == 0 || errno == ENOENT) {
move_file(tmp_hashname, output_file) == 0 || errno == ENOENT) {
if (cpp_stderr) {
/* we might have some stderr from cpp */
int fd2 = open(cpp_stderr, O_RDONLY | O_BINARY);
@ -231,14 +231,25 @@ static void to_cache(ARGS *args)
x_asprintf(&path_stderr, "%s.stderr", hashname);
if (stat(tmp_stderr, &st1) != 0 ||
stat(tmp_hashname, &st2) != 0 ||
rename(tmp_hashname, hashname) != 0 ||
rename(tmp_stderr, path_stderr) != 0) {
stat(tmp_hashname, &st2) != 0 ||
move_file(tmp_hashname, hashname) != 0 ||
move_file(tmp_stderr, path_stderr) != 0) {
cc_log("failed to rename tmp files - %s\n", strerror(errno));
stats_update(STATS_ERROR);
failed();
}
#if ENABLE_ZLIB
/* do an extra stat on the cache files for
the size statistics */
if (stat(path_stderr, &st1) != 0 ||
stat(hashname, &st2) != 0) {
cc_log("failed to stat cache files - %s\n", strerror(errno));
stats_update(STATS_ERROR);
failed();
}
#endif
cc_log("Placed %s into cache\n", output_file);
stats_tocache(file_size(&st1) + file_size(&st2));
@ -478,7 +489,13 @@ static void from_cache(int first)
}
/* the user might be disabling cache hits */
#ifndef ENABLE_ZLIB
/* if the cache file is compressed we must recache */
if ((first && getenv("CCACHE_RECACHE")) ||
test_if_compressed(hashname) == 1) {
#else
if (first && getenv("CCACHE_RECACHE")) {
#endif
close(fd_stderr);
unlink(stderr_file);
free(stderr_file);
@ -491,7 +508,9 @@ static void from_cache(int first)
ret = 0;
} else {
unlink(output_file);
if (getenv("CCACHE_HARDLINK")) {
/* only make a hardlink if the cache file is uncompressed */
if (getenv("CCACHE_HARDLINK") &&
test_if_compressed(hashname) == 0) {
ret = link(hashname, output_file);
} else {
ret = copy_file(hashname, output_file);

View File

@ -23,6 +23,10 @@
#include <pwd.h>
#endif
#ifdef ENABLE_ZLIB
#include <zlib.h>
#endif
#define STATUS_NOTFOUND 3
#define STATUS_FATAL 4
#define STATUS_NOCACHE 5
@ -36,6 +40,13 @@
#define DEFAULT_MAXSIZE (1000*1000)
#endif
/* file copy mode */
#ifdef ENABLE_ZLIB
#define COPY_UNCOMPRESSED 0
#define COPY_FROM_CACHE 1
#define COPY_TO_CACHE 2
#endif
enum stats {
STATS_NONE=0,
STATS_STDOUT,
@ -79,6 +90,8 @@ void fatal(const char *msg);
void copy_fd(int fd_in, int fd_out);
int copy_file(const char *src, const char *dest);
int move_file(const char *src, const char *dest);
int test_if_compressed(const char *filename);
int create_dir(const char *dir);
void x_asprintf(char **ptr, const char *format, ...);

View File

@ -169,6 +169,11 @@ will have problems with the intermediate filename extensions used in
this optimisation, in which case this option could allow ccache to be
used.
dit(bf(CCACHE_NOCOMPRESS)) If you set the environment variable
CCACHE_NOCOMPRESS then there is no compression used on files that go
into the cache. However, this setting has no effect on how files are
retrieved from the cache, compressed results will still be usable.
dit(bf(CCACHE_NOSTATS)) If you set the environment variable
CCACHE_NOSTATS then ccache will not update the statistics files on
each compile.
@ -181,7 +186,8 @@ dit(bf(CCACHE_HARDLINK)) If you set the environment variable
CCACHE_HARDLINK then ccache will attempt to use hard links from the
cache directory when creating the compiler output rather than using a
file copy. Using hard links is faster, but can confuse programs like
'make' that rely on modification times.
'make' that rely on modification times. Hard links are never made for
compressed cache files.
dit(bf(CCACHE_RECACHE)) This forces ccache to not use any cached
results, even if it finds them. New results are still cached, but
@ -241,6 +247,14 @@ When these limits are reached ccache will reduce the cache to 20%
below the numbers you specified in order to avoid doing the cache
clean operation too often.
manpagesection(CACHE COMPRESSION)
By default ccache will compress all files it puts into the cache
using the zlib compression. While this involves a negligible
performance slowdown, it significantly increases the number of files
that fit in the cache. You can turn off compression setting the
CCACHE_NOCOMPRESS environment variable.
manpagesection(HOW IT WORKS)
The basic idea is to detect when you are compiling exactly the same
@ -299,6 +313,8 @@ itemize(
cache. This tells the filesystem to inherit group ownership for new
directories. The command "chmod g+s `find $CCACHE_DIR -type d`" might
be useful for this.
it() Set bf(CCACHE_NOCOMPRESS) for all users, if there are users with
versions of ccache that do not support compression.
)
manpagesection(HISTORY)

View File

@ -105,6 +105,9 @@
/* Define _GNU_SOURCE so that we get all necessary prototypes */
#undef _GNU_SOURCE
/* Define to 1 if you like to have zlib compression for the ccache. */
#undef ENABLE_ZLIB
/* Define on UNIX to activate XPG/5 features. */
#if !defined(_XOPEN_SOURCE)
# define _XOPEN_SOURCE

298
configure vendored
View File

@ -836,6 +836,11 @@ if test -n "$ac_init_help"; then
cat <<\_ACEOF
Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-zlib enable zlib support for ccache compression
Some influential environment variables:
CC C compiler command
CFLAGS C compiler flags
@ -936,7 +941,7 @@ esac
else
echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
fi
cd "$ac_popdir"
cd $ac_popdir
done
fi
@ -1859,7 +1864,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -1917,7 +1923,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2033,7 +2040,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2087,7 +2095,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2132,7 +2141,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2176,7 +2186,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2614,7 +2625,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2686,7 +2698,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2740,7 +2753,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2811,7 +2825,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2865,7 +2880,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -2932,7 +2948,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3002,7 +3019,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3083,7 +3101,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3253,7 +3272,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3324,7 +3344,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3514,7 +3535,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3616,7 +3638,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3681,7 +3704,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
@ -3778,6 +3802,229 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_C99_VSNPRINTF 1
_ACEOF
fi
# Check whether --enable-zlib or --disable-zlib was given.
if test "${enable_zlib+set}" = set; then
enableval="$enable_zlib"
else
enable_zlib=yes
fi;
if test x"$enable_zlib" = x"yes"; then
if test "${ac_cv_header_zlib_h+set}" = set; then
echo "$as_me:$LINENO: checking for zlib.h" >&5
echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6
if test "${ac_cv_header_zlib_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
fi
echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
echo "${ECHO_T}$ac_cv_header_zlib_h" >&6
else
# Is the header compilable?
echo "$as_me:$LINENO: checking zlib.h usability" >&5
echo $ECHO_N "checking zlib.h usability... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
$ac_includes_default
#include <zlib.h>
_ACEOF
rm -f conftest.$ac_objext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest.$ac_objext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_header_compiler=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_compiler=no
fi
rm -f conftest.err conftest.$ac_objext conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
echo "${ECHO_T}$ac_header_compiler" >&6
# Is the header present?
echo "$as_me:$LINENO: checking zlib.h presence" >&5
echo $ECHO_N "checking zlib.h presence... $ECHO_C" >&6
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
#include <zlib.h>
_ACEOF
if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
(eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } >/dev/null; then
if test -s conftest.err; then
ac_cpp_err=$ac_c_preproc_warn_flag
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
else
ac_cpp_err=
fi
else
ac_cpp_err=yes
fi
if test -z "$ac_cpp_err"; then
ac_header_preproc=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_header_preproc=no
fi
rm -f conftest.err conftest.$ac_ext
echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
echo "${ECHO_T}$ac_header_preproc" >&6
# So? What about this header?
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
yes:no: )
{ echo "$as_me:$LINENO: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&5
echo "$as_me: WARNING: zlib.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
{ echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the compiler's result" >&5
echo "$as_me: WARNING: zlib.h: proceeding with the compiler's result" >&2;}
ac_header_preproc=yes
;;
no:yes:* )
{ echo "$as_me:$LINENO: WARNING: zlib.h: present but cannot be compiled" >&5
echo "$as_me: WARNING: zlib.h: present but cannot be compiled" >&2;}
{ echo "$as_me:$LINENO: WARNING: zlib.h: check for missing prerequisite headers?" >&5
echo "$as_me: WARNING: zlib.h: check for missing prerequisite headers?" >&2;}
{ echo "$as_me:$LINENO: WARNING: zlib.h: see the Autoconf documentation" >&5
echo "$as_me: WARNING: zlib.h: see the Autoconf documentation" >&2;}
{ echo "$as_me:$LINENO: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&5
echo "$as_me: WARNING: zlib.h: section \"Present But Cannot Be Compiled\"" >&2;}
{ echo "$as_me:$LINENO: WARNING: zlib.h: proceeding with the preprocessor's result" >&5
echo "$as_me: WARNING: zlib.h: proceeding with the preprocessor's result" >&2;}
{ echo "$as_me:$LINENO: WARNING: zlib.h: in the future, the compiler will take precedence" >&5
echo "$as_me: WARNING: zlib.h: in the future, the compiler will take precedence" >&2;}
(
cat <<\_ASBOX
## ------------------------------------------ ##
## Report this to the AC_PACKAGE_NAME lists. ##
## ------------------------------------------ ##
_ASBOX
) |
sed "s/^/$as_me: WARNING: /" >&2
;;
esac
echo "$as_me:$LINENO: checking for zlib.h" >&5
echo $ECHO_N "checking for zlib.h... $ECHO_C" >&6
if test "${ac_cv_header_zlib_h+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_cv_header_zlib_h=$ac_header_preproc
fi
echo "$as_me:$LINENO: result: $ac_cv_header_zlib_h" >&5
echo "${ECHO_T}$ac_cv_header_zlib_h" >&6
fi
if test $ac_cv_header_zlib_h = yes; then
echo "$as_me:$LINENO: checking for gzdopen in -lz" >&5
echo $ECHO_N "checking for gzdopen in -lz... $ECHO_C" >&6
if test "${ac_cv_lib_z_gzdopen+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lz $LIBS"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any gcc2 internal prototype to avoid an error. */
#ifdef __cplusplus
extern "C"
#endif
/* We use char because int might match the return type of a gcc2
builtin and then its argument prototype would still apply. */
char gzdopen ();
int
main ()
{
gzdopen ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
(eval $ac_link) 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag"
|| test ! -s conftest.err'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
(eval $ac_try) 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_z_gzdopen=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_z_gzdopen=no
fi
rm -f conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
echo "$as_me:$LINENO: result: $ac_cv_lib_z_gzdopen" >&5
echo "${ECHO_T}$ac_cv_lib_z_gzdopen" >&6
if test $ac_cv_lib_z_gzdopen = yes; then
LIBS="-lz $LIBS"; cat >>confdefs.h <<\_ACEOF
#define ENABLE_ZLIB 1
_ACEOF
fi
fi
fi
ac_config_files="$ac_config_files Makefile"
@ -4573,6 +4820,11 @@ esac
*) ac_INSTALL=$ac_top_builddir$INSTALL ;;
esac
if test x"$ac_file" != x-; then
{ echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
rm -f "$ac_file"
fi
# Let's still pretend it is `configure' which instantiates (i.e., don't
# use $as_me), people would be surprised to read:
# /* config.h. Generated by config.status. */
@ -4611,12 +4863,6 @@ echo "$as_me: error: cannot find input file: $f" >&2;}
fi;;
esac
done` || { (exit 1); exit 1; }
if test x"$ac_file" != x-; then
{ echo "$as_me:$LINENO: creating $ac_file" >&5
echo "$as_me: creating $ac_file" >&6;}
rm -f "$ac_file"
fi
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
sed "$ac_vpsub

View File

@ -76,5 +76,14 @@ if test x"$ccache_cv_HAVE_C99_VSNPRINTF" = x"yes"; then
AC_DEFINE(HAVE_C99_VSNPRINTF, 1, [ ])
fi
dnl Check for zlib.
AC_ARG_ENABLE([zlib],
AS_HELP_STRING([--enable-zlib], [enable zlib support for ccache compression]),,
[enable_zlib=yes])
if test x"$enable_zlib" = x"yes"; then
AC_CHECK_HEADER(zlib.h, AC_CHECK_LIB(z, gzdopen, LIBS="-lz $LIBS"; AC_DEFINE(ENABLE_ZLIB)))
fi
AC_CONFIG_FILES([Makefile])
AC_OUTPUT

68
manage-cache.sh Normal file
View File

@ -0,0 +1,68 @@
#!/bin/bash
#
# 2004-05-12 lars@gustaebel.de
CCACHE_DIR=${CCACHE_DIR:-$HOME/.ccache}
echo "Do you want to compress or decompress the ccache in $CCACHE_DIR?"
read -p "Type c or d: " mode
if [ "$mode" != "c" ] && [ "$mode" != "d" ]
then
exit 1
fi
is_compressed() {
test "$(head -c 2 $1)" = $'\x1f\x8b'
return $?
}
tmpfile=$(mktemp)
for dir in 0 1 2 3 4 5 6 7 8 9 a b c d e f
do
# process ccache subdir
echo -n "$dir "
# find cache files
find $CCACHE_DIR/$dir -type f -name '*-*' |
sort > $tmpfile
oldsize=$(cat $CCACHE_DIR/$dir/stats | cut -d ' ' -f 13)
newsize=0
while read file
do
# empty files will be ignored since compressing
# them makes them bigger
test $(stat -c %s $file) -eq 0 && continue
if [ $mode = c ]
then
if ! is_compressed $file
then
gzip $file
mv $file.gz $file
fi
else
if is_compressed $file
then
mv $file $file.gz
gzip -d $file.gz
fi
fi
# calculate new size statistic for this subdir
let newsize=$newsize+$(stat -c "%B*%b" $file)/1024
done < $tmpfile
# update statistic file
read -a numbers < $CCACHE_DIR/$dir/stats
numbers[12]=$newsize
echo "${numbers[*]} " > $CCACHE_DIR/$dir/stats
done
echo
# clean up
rm $tmpfile

174
util.c
View File

@ -44,6 +44,7 @@ void fatal(const char *msg)
exit(1);
}
#ifndef ENABLE_ZLIB
/* copy all data from one file descriptor to another */
void copy_fd(int fd_in, int fd_out)
{
@ -57,6 +58,11 @@ void copy_fd(int fd_in, int fd_out)
}
}
/* move a file using rename */
int move_file(const char *src, const char *dest) {
return rename(src, dest);
}
/* copy a file - used when hard links don't work
the copy is done via a temporary file and atomic rename
*/
@ -120,6 +126,174 @@ int copy_file(const char *src, const char *dest)
return 0;
}
#else /* ENABLE_ZLIB */
/* copy all data from one file descriptor to another
possibly decompressing it
*/
void copy_fd(int fd_in, int fd_out) {
char buf[10240];
int n;
gzFile gz_in;
gz_in = gzdopen(dup(fd_in), "rb");
if (!gz_in) {
fatal("Failed to copy fd");
}
while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
if (write(fd_out, buf, n) != n) {
fatal("Failed to copy fd");
}
}
}
static int _copy_file(const char *src, const char *dest, int mode) {
int fd_in, fd_out;
gzFile gz_in, gz_out = NULL;
char buf[10240];
int n, ret;
char *tmp_name;
mode_t mask;
struct stat st;
x_asprintf(&tmp_name, "%s.XXXXXX", dest);
if (getenv("CCACHE_NOCOMPRESS")) {
mode = COPY_UNCOMPRESSED;
}
/* open source file */
fd_in = open(src, O_RDONLY);
if (fd_in == -1) {
return -1;
}
gz_in = gzdopen(fd_in, "rb");
if (!gz_in) {
close(fd_in);
return -1;
}
/* open destination file */
fd_out = mkstemp(tmp_name);
if (fd_out == -1) {
gzclose(gz_in);
free(tmp_name);
return -1;
}
if (mode == COPY_TO_CACHE) {
/* The gzip file format occupies at least 20 bytes. So
it will always occupy an entire filesystem block,
even for empty files.
Since most stderr files will be empty, we turn off
compression in this case to save space.
*/
if (fstat(fd_in, &st) != 0) {
gzclose(gz_in);
close(fd_out);
free(tmp_name);
return -1;
}
if (file_size(&st) == 0) {
mode = COPY_UNCOMPRESSED;
}
}
if (mode == COPY_TO_CACHE) {
gz_out = gzdopen(dup(fd_out), "wb");
if (!gz_out) {
gzclose(gz_in);
close(fd_out);
free(tmp_name);
return -1;
}
}
while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
if (mode == COPY_TO_CACHE) {
ret = gzwrite(gz_out, buf, n);
} else {
ret = write(fd_out, buf, n);
}
if (ret != n) {
gzclose(gz_in);
if (gz_out) {
gzclose(gz_out);
}
close(fd_out);
unlink(tmp_name);
free(tmp_name);
return -1;
}
}
gzclose(gz_in);
if (gz_out) {
gzclose(gz_out);
}
/* get perms right on the tmp file */
mask = umask(0);
fchmod(fd_out, 0666 & ~mask);
umask(mask);
/* the close can fail on NFS if out of space */
if (close(fd_out) == -1) {
unlink(tmp_name);
free(tmp_name);
return -1;
}
unlink(dest);
if (rename(tmp_name, dest) == -1) {
unlink(tmp_name);
free(tmp_name);
return -1;
}
free(tmp_name);
return 0;
}
/* move a file to the cache, compressing it */
int move_file(const char *src, const char *dest) {
int ret;
ret = _copy_file(src, dest, COPY_TO_CACHE);
if (ret != -1) unlink(src);
return ret;
}
/* copy a file from the cache, decompressing it */
int copy_file(const char *src, const char *dest) {
return _copy_file(src, dest, COPY_FROM_CACHE);
}
#endif /* ENABLE_ZLIB */
/* test if a file is zlib compressed */
int test_if_compressed(const char *filename) {
FILE *f;
f = fopen(filename, "rb");
if (!f) {
return 0;
}
/* test if file starts with 1F8B, which is zlib's
* magic number */
if ((fgetc(f) != 0x1f) || (fgetc(f) != 0x8b)) {
fclose(f);
return 0;
}
fclose(f);
return 1;
}
/* make sure a directory exists */
int create_dir(const char *dir)