The idea of using middleware test suites to test Wine has come up before, I'm sure, but while looking for real world uses of overlapped I/O to named pipes for my named pipe conformance test, I noticed a good candidate.
ACE is a set of object-oriented wrappers around operating system primitives, See http://www.cs.wustl.edu/~schmidt/ACE.html I think it's cruft (hey, it's c++ :-), but in spite of that, it is the basis of a whole lot of software, some very, very good. Ace has a largish set of regression tests which, being tests of a fairly thin OS abstraction layer, would be an almost perfect match for Wine's needs. See http://cvs.doc.wustl.edu/ace-cvs.cgi/ACE_wrappers/tests/README?rev=4.25 for more info about their regression tests.
Can someone with a beefy machine and time on their hands give this a shot under Wine? Presumably you'd build everything with msvc, then run the tests under Wine.
Warning: ACE is huge, and will hurt your head if you're not prepared. Wear sunglasses or something :-) - Dan
On February 25, 2003 02:08 pm, Dan Kegel wrote:
ACE is a set of object-oriented wrappers around operating system primitives, See http://www.cs.wustl.edu/~schmidt/ACE.html
A perfect test for my winegcc/wineg++ stuff, and for our C++ Winelib support! I've tried a little bit, it breaks badly because we use lots of macros in the msvcrt headers and the code expects functions (which, unlike macros, respect scope). I've signaled this problem before, and I've send a patch for include/msvcrt/io.h transforming those macros into inline functions, but a lot more is left to do.
That is to say, all things from include/msvcrt/* of the form:
#define isascii __isascii
must become:
static inline int isascii(int c) { return __isascii(c); }
Any takers? :)
Dimitrie O. Paun wrote:
A perfect test for my winegcc/wineg++ stuff, and for our C++ Winelib support! I've tried a little bit, it breaks badly because we use lots of macros in the msvcrt headers and the code expects functions (which, unlike macros, respect scope). I've signaled this problem before, and I've send a patch for include/msvcrt/io.h transforming those macros into inline functions, but a lot more is left to do.
That is to say, all things from include/msvcrt/* of the form:
#define isascii __isascii
must become:
static inline int isascii(int c) { return __isascii(c); }
Any takers? :)
I believe someone will be submitting a patch soon :-)
But note: varargs functions cannot be inline, it seems. Thus the defines
#define cprintf _cprintf #define cscanf _cscanf
in conio.h cannot be handled this way. BTW, although MSVC4.0 used #define's to do this kind of aliasing, MSVC6.0 uses some other scheme; both cprintf and _cprintf have real prototypes in conio.h there.
Anyone know what the right thing to do there is? - Dan
On March 21, 2003 02:14 pm, Dan Kegel wrote:
But note: varargs functions cannot be inline, it seems. Thus the defines
#define cprintf _cprintf #define cscanf _cscanf
in conio.h cannot be handled this way. BTW, although MSVC4.0 used #define's to do this kind of aliasing, MSVC6.0 uses some other scheme; both cprintf and _cprintf have real prototypes in conio.h there.
Anyone know what the right thing to do there is?
Yes, I know about the problem. Apparently MSVC has some oldnames lib, so they go through the linker to do the aliasing:
http://www.winehq.com/hypermail/wine-devel/2003/01/0446.html
So the right solution if for us to do the same. I don't have MSVC, but if I understand it correctly, we'll have to create an oldnames.dll that has the right forwards. Alexandre?
"Dimitrie O. Paun" dpaun@rogers.com writes:
Yes, I know about the problem. Apparently MSVC has some oldnames lib, so they go through the linker to do the aliasing:
http://www.winehq.com/hypermail/wine-devel/2003/01/0446.html
So the right solution if for us to do the same. I don't have MSVC, but if I understand it correctly, we'll have to create an oldnames.dll that has the right forwards. Alexandre?
It's actually not a dll, only an import library. We don't have a way of implementing that with our import mechanism yet; though we could probably make it a static library at the cost of an extra jump for each function.
On March 22, 2003 01:13 pm, Alexandre Julliard wrote:
It's actually not a dll, only an import library. We don't have a way of implementing that with our import mechanism yet; though we could probably make it a static library at the cost of an extra jump for each function.
Well, I don't think that's a problem -- we need it only for the varargs functions, the inlines work just as well for the vast majority of functions. But if import libs are planned in the near future, what about just adding a forward in the msvcrt.dll for the varargs functions, as a temporary bandaid?
"Dimitrie O. Paun" dpaun@rogers.com writes:
Well, I don't think that's a problem -- we need it only for the varargs functions, the inlines work just as well for the vast majority of functions. But if import libs are planned in the near future, what about just adding a forward in the msvcrt.dll for the varargs functions, as a temporary bandaid?
This won't work, the forwarding needs to be done at link time, not at run time. Sure you can add the entry points to msvcrt, but then it won't be compatible with the native one. It seems to me the defines are fine as a bandaid too; do we have a real life case where the varargs functions are a problem?
On March 23, 2003 07:51 pm, Alexandre Julliard wrote:
This won't work, the forwarding needs to be done at link time, not at run time. Sure you can add the entry points to msvcrt, but then it won't be compatible with the native one.
I understand it would be preferable to do the forwarding at link time, but why it will not work if we do it at run time? Yes, our msvcrt will have 3-4 additional entry points, but will they break anything in real life? All Win32 binaries already refer to the other symbols, no?
It seems to me the defines are fine as a bandaid too; do we have a real life case where the varargs functions are a problem?
The ACE thing, for one.
"Dimitrie O. Paun" dpaun@rogers.com writes:
I understand it would be preferable to do the forwarding at link time, but why it will not work if we do it at run time? Yes, our msvcrt will have 3-4 additional entry points, but will they break anything in real life? All Win32 binaries already refer to the other symbols, no?
Well, it means Winelib apps won't be compatible with native msvcrt anymore. That's a bit annoying since many people run with native msvcrt, and they would then need to add special configuration entries for the Winelib apps.
On March 23, 2003 10:44 pm, Alexandre Julliard wrote:
Well, it means Winelib apps won't be compatible with native msvcrt anymore. That's a bit annoying since many people run with native msvcrt, and they would then need to add special configuration entries for the Winelib apps.
Ah, now I see. Well, that sucks. So maybe we should create a libs/oldnames? For i386, can't we just create (inline( a symbol X (similar to they way __ASM_GLOBAL_FUNC() works) that does "jmp _X", so we can avoid the lib?
"Dimitrie O. Paun" dpaun@rogers.com writes:
Ah, now I see. Well, that sucks. So maybe we should create a libs/oldnames? For i386, can't we just create (inline( a symbol X (similar to they way __ASM_GLOBAL_FUNC() works) that does "jmp _X", so we can avoid the lib?
Actually it may be possible to use the alias attribute under gcc, something along these lines:
Index: include/msvcrt/process.h =================================================================== RCS file: /opt/cvs-commit/wine/include/msvcrt/process.h,v retrieving revision 1.8 diff -u -r1.8 process.h --- include/msvcrt/process.h 22 Mar 2003 21:15:41 -0000 1.8 +++ include/msvcrt/process.h 24 Mar 2003 22:49:40 -0000 @@ -123,22 +123,35 @@
static inline int cwait(int *status, int pid, int action) { return _cwait(status, pid, action); } static inline int getpid(void) { return _getpid(); } -#define execl _execl -#define execle _execle -#define execlp _execlp -#define execlpe _execlpe static inline int execv(const char* name, char* const* argv) { return _execv(name, argv); } static inline int execve(const char* name, char* const* argv, const char* const* envv) { return _execve(name, argv, envv); } static inline int execvp(const char* name, char* const* argv) { return _execvp(name, argv); } static inline int execvpe(const char* name, char* const* argv, const char* const* envv) { return _execvpe(name, argv, envv); } -#define spawnl _spawnl -#define spawnle _spawnle -#define spawnlp _spawnlp -#define spawnlpe _spawnlpe static inline int spawnv(int flags, const char* name, const char* const* argv) { return _spawnv(flags, name, argv); } static inline int spawnve(int flags, const char* name, const char* const* argv, const char* const* envv) { return _spawnve(flags, name, argv, envv); } static inline int spawnvp(int flags, const char* name, const char* const* argv) { return _spawnvp(flags, name, argv); } static inline int spawnvpe(int flags, const char* name, const char* const* argv, const char* const* envv) { return _spawnvpe(flags, name, argv, envv); } + +#ifdef __GNUC__ +extern int execl(const char*,const char*,...) __attribute__((alias("_execl"))); +extern int execle(const char*,const char*,...) __attribute__((alias("_execle"))); +extern int execlp(const char*,const char*,...) __attribute__((alias("_execlp"))); +extern int execlpe(const char*,const char*,...) __attribute__((alias("_execlpe"))); +extern int spawnl(int,const char*,const char*,...) __attribute__((alias("_spawnl"))); +extern int spawnle(int,const char*,const char*,...) __attribute__((alias("_spawnle"))); +extern int spawnlp(int,const char*,const char*,...) __attribute__((alias("_spawnlp"))); +extern int spawnlpe(int,const char*,const char*,...) __attribute__((alias("_spawnlpe"))); +#else +#define execl _execl +#define execle _execle +#define execlp _execlp +#define execlpe _execlpe +#define spawnl _spawnl +#define spawnle _spawnle +#define spawnlp _spawnlp +#define spawnlpe _spawnlpe +#endif /* __GNUC__ */ + #endif /* USE_MSVCRT_PREFIX */
#endif /* __WINE_PROCESS_H */
On March 24, 2003 06:00 pm, Alexandre Julliard wrote:
Actually it may be possible to use the alias attribute under gcc, something along these lines:
Cool. Maybe we can do a similar thing for the rest of varargs funcs. The rest we can keep inline, right? I hope gcc optimizes them to be equivalent to an alias...
Now I have another problem. ACE needs to link with msvcrt (I forget now why), but it also makes use of C++ standard lib. Needless to say, this doesn't work quite right:
In file included from /usr/include/c++/3.2/bits/fpos.h:45, from /usr/include/c++/3.2/iosfwd:46, from /usr/include/c++/3.2/ios:44, from /usr/include/c++/3.2/ostream:45, from /usr/include/c++/3.2/iostream:45, from /home/dimi/dev/wine/ACE_wrappers/ace/streams.h:61, from /home/dimi/dev/wine/ACE_wrappers/ace/OS.h:2452, from Basic_Types.cpp:1: /usr/include/c++/3.2/cwchar:142: `fwide' not declared /usr/include/c++/3.2/cwchar:149: `mbsinit' not declared /usr/include/c++/3.2/cwchar:157: `vfwscanf' not declared /usr/include/c++/3.2/cwchar:159: `vswscanf' not declared /usr/include/c++/3.2/cwchar:161: `vwscanf' not declared /usr/include/c++/3.2/cwchar:176: `wcstof' not declared /usr/include/c++/3.2/cwchar:182: `wmemcmp' not declared /usr/include/c++/3.2/cwchar:183: `wmemcpy' not declared /usr/include/c++/3.2/cwchar:184: `wmemmove' not declared /usr/include/c++/3.2/cwchar:185: `wmemset' not declared /usr/include/c++/3.2/cwchar:213: `wmemchr' not declared
That is, the glibc implementation of the C++ lib makes use of functions that don't seem to be available in msvcrt, like fwide. How should we proceed?
"Dimitrie O. Paun" dpaun@rogers.com writes:
That is, the glibc implementation of the C++ lib makes use of functions that don't seem to be available in msvcrt, like fwide. How should we proceed?
I don't see much hope of mixing the glibc C++ library with msvcrt. You either need to use a Windows C++ library, or use glibc.
On 25 Mar 2003, Alexandre Julliard wrote:
I don't see much hope of mixing the glibc C++ library with msvcrt. You either need to use a Windows C++ library, or use glibc.
I hear you. But that presents a problem. I guess a lot of Windows programs use C++, and thus some of the standard library. If we are to allow them to work with Winelib, it seems to me we to do something similar to the msvcrt. Now that we are LGPL, why not get the GNU C++ implementation, adapt it to work with our msvcrt, and ship it with Wine, just like we do with msvcrt. I'm not even sure how much work that is, but would that be acceptable as a future project?
"Dimitrie O. Paun" dimi@intelliware.ca writes:
I hear you. But that presents a problem. I guess a lot of Windows programs use C++, and thus some of the standard library. If we are to allow them to work with Winelib, it seems to me we to do something similar to the msvcrt. Now that we are LGPL, why not get the GNU C++ implementation, adapt it to work with our msvcrt, and ship it with Wine, just like we do with msvcrt. I'm not even sure how much work that is, but would that be acceptable as a future project?
I don't think we want to maintain our own version of the GNU C++ library. The right approach IMO would be to port it to Windows (if it hasn't been done already) and submit patches back to the main libstd++ tree. Then we can tell people to build the Windows version under Winelib.
On March 25, 2003 07:43 pm, Alexandre Julliard wrote:
I don't think we want to maintain our own version of the GNU C++ library. The right approach IMO would be to port it to Windows (if it hasn't been done already) and submit patches back to the main libstd++ tree. Then we can tell people to build the Windows version under Winelib.
Right. Hands were writing on their own. What I meant was to include a (hopefully unmodified) copy of the libstdc++, and itegrate it in our build process. This way, C++ apps have the runtime available, just like C apps do. I'm downloading the lib as I write, and I'll look at what it takes to compile it under Winelib, but I don't think it's fair to subject C++ apps to a complicated build process just to get the runtime going, which everybody assumes it's just 'there'.