This patch makes the build of gcov-tool configurable. It checks if ftw.h is available. For mingw build, it provides ftw functionality by using FindFirstFile/FindNextFile/FindClose API.
Tested with and without --disable-gcov-tool. Thanks, -Rong
2014-09-02 Rong Xu <x...@google.com> * gcc/Makefile.in: Make the build gcov-tool configurable. * gcc/configure.ac: Ditto. * gcc/configure: Ditto. * gcc/config.in: Ditto. * gcc/gcov-tool.c (unlink_gcda_file): Support win32 build. (unlink_profile_dir): Ditto. * libgcc/libgcov-util.c (read_gcda_file): Ditto. (read_file_handler): Ditto. (ftw_read_file): Ditto. (myftw): Ditto. (gcov_read_profile_dir): Ditto. (gcov_profile_normalize): Ditto. Index: gcc/Makefile.in =================================================================== --- gcc/Makefile.in (revision 214831) +++ gcc/Makefile.in (working copy) @@ -123,9 +123,13 @@ SUBDIRS =@subdirs@ build # Selection of languages to be made. CONFIG_LANGUAGES = @all_selected_languages@ -LANGUAGES = c gcov$(exeext) gcov-dump$(exeext) gcov-tool$(exeext) \ - $(CONFIG_LANGUAGES) +LANGUAGES = c gcov$(exeext) gcov-dump$(exeext) $(CONFIG_LANGUAGES) +disable_gcov_tool = @disable_gcov_tool@ +ifneq ($(disable_gcov_tool),yes) +LANGUAGES += gcov-tool$(exeext) +endif + # Default values for variables overridden in Makefile fragments. # CFLAGS is for the user to override to, e.g., do a cross build with -O2. # TCFLAGS is used for compilations with the GCC just built. Index: gcc/configure.ac =================================================================== --- gcc/configure.ac (revision 214831) +++ gcc/configure.ac (working copy) @@ -5650,6 +5650,26 @@ if test "${ENABLE_LIBQUADMATH_SUPPORT}" != "no" ; fi +# Check if gcov-tool can be built. +AC_ARG_ENABLE(gcov-tool, +[AS_HELP_STRING([--disable-gcov-tool], + [disable the build of gcov-tool])]) +if test x"$enable_gcov_tool" = x"no"; then + disable_gcov_tool=yes +else + AC_CHECK_HEADERS(ftw.h, [disable_gcov_tool=no], + [case $host_os in + win32 | cygwin* | mingw32*) + disable_gcov_tool=no + ;; + *) + disable_gcov_tool=yes + ;; + esac]) +fi +AC_SUBST(disable_gcov_tool) + + # Specify what hash style to use by default. AC_ARG_WITH([linker-hash-style], [AC_HELP_STRING([--with-linker-hash-style={sysv,gnu,both}], Index: gcc/configure =================================================================== --- gcc/configure (revision 214831) +++ gcc/configure (working copy) @@ -600,6 +600,7 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS LIBOBJS +disable_gcov_tool PICFLAG enable_host_shared enable_plugin @@ -932,6 +933,7 @@ enable_version_specific_runtime_libs enable_plugin enable_host_shared enable_libquadmath_support +enable_gcov_tool with_linker_hash_style ' ac_precious_vars='build_alias @@ -1655,6 +1657,7 @@ Optional Features: --enable-host-shared build host code as shared libraries --disable-libquadmath-support disable libquadmath support for Fortran + --disable-gcov-tool disable the build of gcov-tool Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -8353,7 +8356,7 @@ fi for ac_header in limits.h stddef.h string.h strings.h stdlib.h time.h iconv.h \ fcntl.h unistd.h sys/file.h sys/time.h sys/mman.h \ sys/resource.h sys/param.h sys/times.h sys/stat.h \ - direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h + direct.h malloc.h langinfo.h ldfcn.h locale.h wchar.h ftw.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_preproc "$LINENO" "$ac_header" "$as_ac_Header" @@ -18033,7 +18036,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18036 "configure" +#line 18039 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18139,7 +18142,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18142 "configure" +#line 18145 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -28116,6 +28119,33 @@ $as_echo "#define ENABLE_LIBQUADMATH_SUPPORT 1" >> fi +# Check if gcov-tool can be built. +# Check whether --enable-gcov-tool was given. +if test "${enable_gcov_tool+set}" = set; then : + enableval=$enable_gcov_tool; +fi + +if test x"$enable_gcov_tool" = x"no"; then + disable_gcov_tool=yes +else + ac_fn_c_check_header_preproc "$LINENO" "ftw.h" "ac_cv_header_ftw_h" +if test "x$ac_cv_header_ftw_h" = x""yes; then : + disable_gcov_tool=no +else + case $host_os in + win32 | cygwin* | mingw32*) + disable_gcov_tool=no + ;; + *) + disable_gcov_tool=yes + ;; + esac +fi + +fi + + + # Specify what hash style to use by default. # Check whether --with-linker-hash-style was given. Index: gcc/config.in =================================================================== --- gcc/config.in (revision 214831) +++ gcc/config.in (working copy) @@ -1046,6 +1046,12 @@ #endif +/* Define to 1 if you have the <ftw.h> header file. */ +#ifndef USED_FOR_TARGET +#undef HAVE_FTW_H +#endif + + /* Define to 1 if you have the `fwrite_unlocked' function. */ #ifndef USED_FOR_TARGET #undef HAVE_FWRITE_UNLOCKED @@ -1699,16 +1705,19 @@ #undef HAVE_WORKING_VFORK #endif -/* Define if isl is in use. */ -#ifndef USED_FOR_TARGET -#undef HAVE_isl -#endif /* Define if cloog is in use. */ #ifndef USED_FOR_TARGET #undef HAVE_cloog #endif + +/* Define if isl is in use. */ +#ifndef USED_FOR_TARGET +#undef HAVE_isl +#endif + + /* Define if F_SETLKW supported by fcntl. */ #ifndef USED_FOR_TARGET #undef HOST_HAS_F_SETLKW Index: gcc/gcov-tool.c =================================================================== --- gcc/gcov-tool.c (revision 214831) +++ gcc/gcov-tool.c (working copy) @@ -35,7 +35,9 @@ see the files COPYING3 and COPYING.RUNTIME respect #include <stdio.h> #include <sys/stat.h> #include <unistd.h> +#ifdef HAVE_FTW_H #include <ftw.h> +#endif #include <getopt.h> extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int); @@ -50,6 +52,7 @@ static bool verbose; /* Remove file NAME if it has a gcda suffix. */ +#ifdef HAVE_FTW_H static int unlink_gcda_file (const char *name, const struct stat *status ATTRIBUTE_UNUSED, @@ -68,15 +71,21 @@ unlink_gcda_file (const char *name, return ret; } +#endif /* Remove the gcda files in PATH recursively. */ static int unlink_profile_dir (const char *path) { +#ifdef HAVE_FTW_H return nftw(path, unlink_gcda_file, 64, FTW_DEPTH | FTW_PHYS); +#else + return 0; +#endif } + /* Output GCOV_INFO lists PROFILE to directory OUT. Note that we will remove all the gcda files in OUT. */ Index: libgcc/libgcov-util.c =================================================================== --- libgcc/libgcov-util.c (revision 214831) +++ libgcc/libgcov-util.c (working copy) @@ -52,7 +52,13 @@ void gcov_set_verbose (void) #include "obstack.h" #include <unistd.h> +#ifdef HAVE_FTW_H #include <ftw.h> +#else +#if defined(_WIN32) +#include <windows.h> +#endif +#endif static void tag_function (unsigned, unsigned); static void tag_blocks (unsigned, unsigned); @@ -281,13 +287,8 @@ read_gcda_file (const char *filename) } /* Read version. */ - version = gcov_read_unsigned (); if (version != GCOV_VERSION) - { - fnotice (stderr, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION); - gcov_close (); - return NULL; - } + warning (0, "%s:incorrect gcov version %d vs %d \n", filename, version, GCOV_VERSION); /* Instantiate a gcov_info object. */ curr_gcov_info = obj_info = (struct gcov_info *) xcalloc (sizeof (struct gcov_info) + @@ -380,22 +381,16 @@ read_gcda_file (const char *filename) return obj_info; } -/* This will be called by ftw(). It opens and read a gcda file FILENAME. - Return a non-zero value to stop the tree walk. */ +/* Handler to open and read a gcda file FILENAME. */ + static int -ftw_read_file (const char *filename, - const struct stat *status ATTRIBUTE_UNUSED, - int type) +read_file_handler (const char *filename) { int filename_len; int suffix_len; struct gcov_info *obj_info; - /* Only read regular files. */ - if (type != FTW_F) - return 0; - filename_len = strlen (filename); suffix_len = strlen (GCOV_DATA_SUFFIX); @@ -418,6 +413,71 @@ static int return 0; } +#ifdef HAVE_FTW_H +/* This will be called by ftw(). It opens and read a gcda file FILENAME. + Return a non-zero value to stop the tree walk. */ + +static int +ftw_read_file (const char *filename, + const struct stat *status ATTRIBUTE_UNUSED, + int type) +{ + /* Only read regular files. */ + if (type != FTW_F) + return 0; + return read_file_handler (filename); +} + +#else /* !HAVE_FTW_H */ + +#if defined(_WIN32) +/* Funtion to find all the gcda files recursively in DIR. */ +static void +myftw (char *dir, char* pattern, int (*handler)(const char *)) +{ + char buffer[MAX_PATH]; + WIN32_FIND_DATA filedata; + HANDLE ret; + + /* Process the subdirectories. */ + sprintf (buffer, "%s\\*", dir); + ret = FindFirstFile (buffer, &filedata); + if(ret != INVALID_HANDLE_VALUE) + { + do + { + if(filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + if (filedata.cFileName[0] == '.') + continue; + sprintf (buffer, "%s\\%s", dir, filedata.cFileName); + myftw (buffer, pattern, handler); + } + } while(FindNextFile (ret, &filedata)); + FindClose(ret); + } + + /* Find the matching files. */ + sprintf (buffer, "%s\\%s", dir, pattern); + ret = FindFirstFile (buffer, &filedata); + if(ret != INVALID_HANDLE_VALUE) + { + do + { + if(!(filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + /* Apply action. */ + (*handler) (buffer); + } + } while(FindNextFile (ret, &filedata)); + FindClose (ret); + } +} +#endif /* _WIN32 */ + +#endif /* HAVE_FTW_H */ + + /* Initializer for reading a profile dir. */ static inline void @@ -451,7 +511,14 @@ gcov_read_profile_dir (const char* dir_name, int r fnotice (stderr, "%s is not a directory\n", dir_name); return NULL; } +#ifdef HAVE_FTW_H ftw (".", ftw_read_file, 50); +#else +#if defined(_WIN32) + myftw (".", "*.gcda", read_file_handler); +#endif +#endif + ret = chdir (pwd); free (pwd); @@ -852,8 +919,10 @@ gcov_profile_normalize (struct gcov_info *profile, } scale_factor = (float)max_val / curr_max_val; +#if !defined(_WIN32) if (verbose) fnotice (stdout, "max_val is %lld\n", (long long) curr_max_val); +#endif return gcov_profile_scale (profile, scale_factor, 0, 0); }