https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94570

            Bug ID: 94570
           Summary: -fprofile-dir is broken on Cygwin
           Product: gcc
           Version: 9.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: gcov-profile
          Assignee: unassigned at gcc dot gnu.org
          Reporter: john at selbie dot com
                CC: marxin at gcc dot gnu.org
  Target Milestone: ---

The following bug is unique to gcc and g++ running on Cygwin.  I can repro this
on both gcc 9.2 and 9.3.

Using almost any source file, execute the following to start the first phase of
a profile guided optimization on Cygwin with a target directory to store .gcda
files:

$ g++ anyprogram.cpp -o anyprogram -fprofile-generate -fprofile-dir=profiledata

Then run the compiled code to start the program:

$ ./anyprogram.exe

After the program completes, the following output is revealed to show that the
coverage code couldn't save the gcda file:

profiling:profiledata/#home#jselbie\anyprogram.gcda:Skip

The .gcda file is not crated.

You can even see the mangled string it in the resulting binary:

$ strings anyprogram.exe | grep jselbie
profiledata/#home#jselbie\anyprogram.gcda


I see two possible issues that's causing this.

First, the anyprogram.gcda string is getting appended with a back slash instead
of a forward slash

A quick cursory glace of GCC sources would suggest the issue is in
\gcc\coverage.c. Looking at the code for coverage_init inside gcc/converage.c
reveals the following:

          if (profile_data_prefix)
        {
#if HAVE_DOS_BASED_FILE_SYSTEM
     const char *separator = "\\";
    #else
     const char *separator = "/";
    #endif
     filename = concat (getpwd (), separator, filename, NULL);
     filename = mangle_path (filename);
     len = strlen (filename);
    }


Another cursory search of gcc sources suggest HAVE_DOS_BASED_FILE_SYSTEM is
defined by this preprocessor stuff:

#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined
(__CYGWIN__)
#  ifndef HAVE_DOS_BASED_FILE_SYSTEM
#    define HAVE_DOS_BASED_FILE_SYSTEM 1
#  endif

Because HAVE_DOS_BASED_FILE_SYSTEM is getting defined for Cygwin, then
coverage_init is going to use a backslash separator as well. Whether CYGWIN
should be considered a DOS based file system or a special exception needs to be
made in coverage_init, well, I'm not sure.

The second issue is with the way the path gets mangled with # chars.  That's
not consistent with the Linux build (at least with g++ 7.5 that I have going).


The workaround for now is to skip using the -fprofile-dir flag and allow
default save behavior for the gcda flag.

Reply via email to