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.