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);
 }

Reply via email to