mkstemp() and fdopen() in Cygwin 1.7.28
When compiling with g++
4.8.2 on Cygwin, I logged the expansion of macros in three cases:
$ g++ -std=c++11 -E -Dd foo.cpp > foo.log.c++11
$ g++ -ansi -E -Dd foo.cpp > foo.log.ansi
$ g++ -E -Dd foo.cpp > foo.log.noFlag
Comparing the logs was useful. There were "holes" in the -std=c++11
and -ansi
cases, while a block containing the mkstemp()
declaration shows up in the "flagless" case. This let me zero in on the parts of the headers that were processed differently.
In the file /usr/include/stdlib.h
, declarations of mkstemp()
and some other functions are rejected if __STRICT_ANSI__
is defined — such as when we use the compile-time flags -ansi
and -std=c++11
.
Likewise, in the file /usr/include/stdio.h
, declarations of fdopen()
will get skipped for the same reason.
The C++ headers <cstdlib>
and <cstdio>
both include the stdlib.h
and stdio.h
headers and leave declaration of those two functions (among others) up to those two headers. So if we use -ansi
and/or -std=c++11
then those two functions will not be declared and we get the compile errors.
The solution that seems to work for the toy code samples is to undefine __STRICT_ANSI__
before compiling:
$ g++ -std=c++11 -U__STRICT_ANSI__ foo.cpp
It's not clear what the side effects of this will be, but from googling, it seems like this is a common problem and a common fix applied by other developers who need to target Cygwin.
Cygwin has a Linux-like set of Feature Test Macros. However, on Linux with C++, _GNU_SOURCE
is defined unconditionally, essentially negating all such guards. On Cygwin, we do not do this, meaning you actually have to respect the meaning of the various flags on C++ as well.
As noted, using any -std=c++*
flag will define __STRICT_ANSI__
, which is recognized by the macros. Undefining that on the command line is incorrect. Instead, either define the correct documented flag(s) for the functions you wish to use (in this case, -D_POSIX_C_SOURCE=200809L
should cover both), or use -std=gnu++*
flags instead (which, btw, do not define _GNU_SOURCE
) to not declare ANSI compliance.