Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build failure on Win32 with gcc 4.7.2/4.8.1 from www.mingw.org #14494

Open
p5pRT opened this issue Feb 11, 2015 · 3 comments
Open

Build failure on Win32 with gcc 4.7.2/4.8.1 from www.mingw.org #14494

p5pRT opened this issue Feb 11, 2015 · 3 comments

Comments

@p5pRT
Copy link

p5pRT commented Feb 11, 2015

Migrated from rt.perl.org#123794 (status was 'open')

Searchable as RT123794$

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2015

From @steve-m-hay

In commit 0bcc29e I've just silenced some compiler warnings from
these compilers caused by #defines of fstat and stat in both
sys/stat.h and perl's win32/win32iop.h. They no longer complain about
these symbols being redefined, but the fact that they are #undef'd and
then re-#def'd still causes problems, including a build failure in C++
mode.

In a normal C build with the default configuration, doio.c now has
this warning, and likewise for some other fstat/stat calls in the same
file​:

..\doio.c​: In function 'S_openn_cleanup'​:
..\doio.c​:651​:2​: warning​: passing argument 2 of 'win32_fstat' from
incompatible pointer type [enabled by default]
In file included from ./win32.h​:643​:0,
  from ..\perl.h​:3065,
  from ..\doio.c​:27​:
./win32iop.h​:69​:18​: note​: expected 'struct _stat64i32 *' but argument
is of type 'struct stat *'

In a C++ mode build that becomes an error​:

..\doio.c​: In function 'bool S_openn_cleanup(GV*, IO*, PerlIOl**,
char*, const char*, PerlIOl**, PerlIOl**, int, char, int, bool, const
char*)'​:
..\doio.c​:651​:6​: error​: cannot convert 'stat*' to '_stat64i32*' for
argument '2' to 'int win32_fstat(int, _stat64i32*)'

The problem is that the #undef/#define of stat (the stat() function!)
in perl's win32/win32iop.h interferes with these compilers' #define of
stat (the struct stat!) in sys/stat.h

doio.c includes perl.h, which includes the config.h (line 28), then
sys/stat.h (line1088), then dosish.h (line 2797), then win32.h (line
3065), and then intrpvar.h. The latter occurs on line 5542 rather than
5427 since the miniperl build does not have MULTIPLICITY defined since
the config.h for the miniperl build is the canned config.h, which is
set up for a minimal configuration. That canned config.h also does not
have USE_LARGE_FILES defined, so dosish.h gives us​:

#define Stat_t struct stat

These compilers' sys/stat.h give us​:

#ifndef _STAT_DEFINED
[...]
#if defined(_USE_32BIT_TIME_T)
#define _fstat _fstat32
#define _fstati64 _fstat32i64
#define _stat _stat32
#define _stati64 _stat32i64

#else /* !_USE_32BIT_TIME_T */
#define _fstat _fstat64i32
#define _fstati64 _fstat64
#define _stat _stat64i32
#define _stati64 _stat64

#endif /* _USE_32BIT_TIME_T */
#define _STAT_DEFINED

#endif /* _STAT_DEFINED */

#if !defined(_NO_OLDNAMES) && !defined(__STRICT_ANSI__)
#define stat _stat
#define fstat _fstat
#endif /* !defined(_NO_OLDNAMES) && !defined(__STRICT_ANSI__) */

None of _STAT_DEFINED, USE_32BIT_TIME_T, _NO_OLDNAMES or
__STRICT_ANSI__ are defined, so the upshot is that Stat_t, and hence
struct stat, is struct _stat64132, so we therefore have this
declaration of win32_fstat from win32iop.h, included from win32.h​:

DllExport int win32_fstat(int fd, struct _stat64i32 *sbufptr);

but the same file also then does this​:

#if defined(UNDER_CE) || defined(__MINGW32__)
# undef fstat
#endif
#define fstat(fd,bufptr) win32_fstat(fd,bufptr)
#if defined(UNDER_CE) || defined(__MINGW32__)
# undef stat
#endif
#define stat(pth,bufptr) win32_stat(pth,bufptr)

and that last #undef/#define of stat messes with sys/stat.h's #define
of stat such that 'struct stat' is no longer mapped to 'struct
_stat64i32', but is instead left as a simple 'struct stat'.

Therefore, when we reach the #include of intrpvar.h nearing the end of
perl.h we end up with

struct stat PL_statbuf;

rather than the intended

struct _stat64i32 PL_statbuf

which then causes the compiler warning/error shown earlier about a
struct stat being passed to a function which expects a struct
_stat64i32.

I'm not sure how best to fix this.

I'm wondering if _USE_32BIT_TIME_T should actually be defined, as it
is for MSVC60/MSVC70 builds, but that wouldn't fix the problem anyway​:
sys/stat.h would then give us struct stat == struct _stat32, which
win32iop.h would still wipe out.

I've also experimented with defining _NO_OLDNAMES and/or
__STRICT_ANSI__ but all hell breaks loose compiling every .c file with
those options!

The only workaround that I have at the moment is the slightly gross
hack of forcing the re-inclusion of sys/stat.h (including needing to
undefine its "include guard" define) just after win32iop.h has messed
with its definition of stat​:

Inline Patch
diff --git a/win32/win32iop.h b/win32/win32iop.h
index 842bc07..0cf9b59 100644
--- a/win32/win32iop.h
+++ b/win32/win32iop.h
@@ -296,6 +296,10 @@ END_EXTERN_C
 #  undef stat
 #endif
 #define stat(pth,bufptr)       win32_stat(pth,bufptr)
+#ifdef __MINGW32__
+#undef _STAT_H_
+#include <sys/stat.h>
+#endif
 #define longpath(pth)          win32_longpath(pth)
 #define ansipath(pth)          win32_ansipath(pth)
 #ifdef UNDER_CE

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2015

From @bulk88

On Wed Feb 11 00​:58​:44 2015, shay wrote​:

In commit 0bcc29e I've just silenced some compiler warnings from
these compilers caused by #defines of fstat and stat in both
sys/stat.h and perl's win32/win32iop.h. They no longer complain about
these symbols being redefined, but the fact that they are #undef'd and
then re-#def'd still causes problems, including a build failure in C++
mode.

In a normal C build with the default configuration, doio.c now has
this warning, and likewise for some other fstat/stat calls in the same
file​:

..\doio.c​: In function 'S_openn_cleanup'​:
..\doio.c​:651​:2​: warning​: passing argument 2 of 'win32_fstat' from
incompatible pointer type [enabled by default]
In file included from ./win32.h​:643​:0,
from ..\perl.h​:3065,
from ..\doio.c​:27​:
./win32iop.h​:69​:18​: note​: expected 'struct _stat64i32 *' but argument
is of type 'struct stat *'

I dont have time to respond ATM, but I think https://rt-archive.perl.org/perl5/Ticket/Display.html?id=121448 is slightly related.

--
bulk88 ~ bulk88 at hotmail.com

@p5pRT
Copy link
Author

p5pRT commented Feb 11, 2015

The RT System itself - Status changed from 'new' to 'open'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants