使用 wineg++/winelib 编译 C++ 程序的问题
Problems compiling C++ programs with wineg++/winelib
我在使用 wineg++
编译 C++ 程序时遇到问题。为了说明我的问题,我写了两个测试程序。
msgbox.cpp
#include <algorithm>
#include <iterator>
#include <cstdio>
#include <windows.h>
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
char buf[30], *pos = buf;
int xs[] = {1,3,2,4,3,5,4,6,5,7,6,8,7,9};
std::sort( std::begin(xs), std::end(xs) );
for (int x : xs) {
pos += std::sprintf(pos, "%d ", x);
}
MessageBox(0, buf, "Hello", 0);
return 0;
}
frame.cpp
#include "../win32xx/include/wxx_wincore.h"
#include "../win32xx/include/wxx_frame.h"
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
CWinApp winApp;
CFrame frame;
CWnd view;
frame.SetView(view);
frame.Create();
winApp.Run();
}
第二个程序使用 Win32++ 库,我怎么推荐都不为过。
两个程序都可以编译,运行 使用交叉编译器就好了:
okuu% x86_64-w64-mingw32-g++ msgbox.cpp -o msgbox.exe
okuu% wine ./msgbox.exe
okuu% x86_64-w64-mingw32-g++ frame.cpp -o frame.exe -lgdi32 -lcomctl32 -static
okuu% wine ./frame.exe
okuu% rm *exe*
但我想使用 winelib
以便我可以同时使用 Windows API 和 Unix 库。这是我首先尝试的:
okuu% wineg++ msgbox.cpp -o msgbox.exe
okuu% ./msgbox.exe
okuu% wineg++ frame.cpp -o frame.exe -mwindows
In file included from ../win32xx/include/wxx_appcore.h:57:0,
from ../win32xx/include/wxx_wincore.h:96,
from frame.cpp:1:
../win32xx/include/wxx_appcore0.h:120:12: fatal error: process.h: No such file or directory
#include <process.h>
^~~~~~~~~~~
compilation terminated.
winegcc: g++ failed
然后我读了 wineg++
的手册页,上面写着:
-mno-cygwin
Use Wine implementation of MSVCRT, instead of linking against the host system libc. This is necessary for the vast majority of Win32 applications, as they typically depend on various features of MSVCRT. This switch is also used by the MinGW compiler to link against MSVCRT on Windows, instead of linking against Cygwin libc. Sharing the syntax with MinGW makes it very easy to write Makefiles that work under Wine, MinGW+MSYS, or MinGW+Cygwin.
所以我再次尝试使用 -mno-cygwin
,并收到一条以以下内容开头的 2000 行错误消息:
okuu% wineg++ frame.cpp -o frame.exe -mwindows -mno-cygwin
In file included from /usr/include/c++/7.2.1/cstdlib:75:0,
from /usr/include/c++/7.2.1/bits/stl_algo.h:59,
from /usr/include/c++/7.2.1/algorithm:62,
from ../win32xx/include/wxx_appcore0.h:110,
from ../win32xx/include/wxx_appcore.h:57,
from ../win32xx/include/wxx_wincore.h:96,
from frame.cpp:1:
/usr/include/stdlib.h:310:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *fptr; /* Front pointer. */
^~~~~~~
wint_t
/usr/include/stdlib.h:311:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *rptr; /* Rear pointer. */
^~~~~~~
wint_t
/usr/include/stdlib.h:312:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *state; /* Array of state values. */
^~~~~~~
wint_t
/usr/include/stdlib.h:316:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *end_ptr; /* Pointer behind state table. */
^~~~~~~
wint_t
/usr/include/stdlib.h:320:8: error: ‘int32_t’ has not been declared
int32_t *__restrict __result) __THROW __nonnull ((1, 2));
^~~~~~~
所以看起来C99 的固定大小整数类型不可用。这似乎很容易解决:
frame.cpp
#include <stdint.h>
#include "../win32xx/include/wxx_wincore.h"
#include "../win32xx/include/wxx_frame.h"
// etc. etc. etc.
我又试了一次,但收到了一条不同的 2000 行错误消息,其开头为:
okuu% wineg++ frame.cpp -o frame.exe -mwindows -mno-cygwin
In file included from /usr/include/c++/7.2.1/cwchar:44:0,
from /usr/include/c++/7.2.1/bits/postypes.h:40,
from /usr/include/c++/7.2.1/bits/char_traits.h:40,
from /usr/include/c++/7.2.1/string:40,
from ../win32xx/include/wxx_appcore0.h:111,
from ../win32xx/include/wxx_appcore.h:57,
from ../win32xx/include/wxx_wincore.h:96,
from frame.cpp:2:
/usr/local/include/wine/msvcrt/wchar.h:398:23: error: conflicting declaration of C function ‘size_t mbstowcs(wchar_t*, const char*, size_t)’
size_t __cdecl mbstowcs(wchar_t*,const char*,size_t);
^~~~~~~~
此时我 运行 没有主意了。这是我目前的理解:
- 我系统的 libc 和 Wine 的 MSVCRT 有冲突的定义。 (这可能是预料之中的。)
- 我系统的 libc++ 是硬连线的,可以与我系统的 libc 一起工作。
- Wine 带有 MSVCRT,但没有 C++ 标准库实现。
根据我目前掌握的信息,合理的做法是寻找与 Wine 的 MSVCRT 兼容的 C++ 标准库实现,但我不知道有一个。这里有人知道吗?
我能想到的唯一解决方案是坚持使用系统 libc 并编写自己的 process.h
。该文件应该 #include
具有 Win32++ 需要的函数的标准 header 文件,或者提供这些函数自己的实现。如果 Win32++ 在没有特定函数的情况下无法编译,但您的程序实际上并不依赖于该函数,则该函数的实现可以简单地 return 0 或另一个假值。
如果系统 libc 有一个 Win32++ 要求的 header 文件,但该文件没有声明 Win32++ 期望的所有函数,您将不得不编写一个 header 文件,例如作为定义这些函数的 win32xx-compat.h
和 #include
它在任何 Win32++ header.
之前
我在使用 wineg++
编译 C++ 程序时遇到问题。为了说明我的问题,我写了两个测试程序。
msgbox.cpp
#include <algorithm>
#include <iterator>
#include <cstdio>
#include <windows.h>
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
char buf[30], *pos = buf;
int xs[] = {1,3,2,4,3,5,4,6,5,7,6,8,7,9};
std::sort( std::begin(xs), std::end(xs) );
for (int x : xs) {
pos += std::sprintf(pos, "%d ", x);
}
MessageBox(0, buf, "Hello", 0);
return 0;
}
frame.cpp
#include "../win32xx/include/wxx_wincore.h"
#include "../win32xx/include/wxx_frame.h"
int APIENTRY WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
CWinApp winApp;
CFrame frame;
CWnd view;
frame.SetView(view);
frame.Create();
winApp.Run();
}
第二个程序使用 Win32++ 库,我怎么推荐都不为过。
两个程序都可以编译,运行 使用交叉编译器就好了:
okuu% x86_64-w64-mingw32-g++ msgbox.cpp -o msgbox.exe
okuu% wine ./msgbox.exe
okuu% x86_64-w64-mingw32-g++ frame.cpp -o frame.exe -lgdi32 -lcomctl32 -static
okuu% wine ./frame.exe
okuu% rm *exe*
但我想使用 winelib
以便我可以同时使用 Windows API 和 Unix 库。这是我首先尝试的:
okuu% wineg++ msgbox.cpp -o msgbox.exe
okuu% ./msgbox.exe
okuu% wineg++ frame.cpp -o frame.exe -mwindows
In file included from ../win32xx/include/wxx_appcore.h:57:0,
from ../win32xx/include/wxx_wincore.h:96,
from frame.cpp:1:
../win32xx/include/wxx_appcore0.h:120:12: fatal error: process.h: No such file or directory
#include <process.h>
^~~~~~~~~~~
compilation terminated.
winegcc: g++ failed
然后我读了 wineg++
的手册页,上面写着:
-mno-cygwin
Use Wine implementation of MSVCRT, instead of linking against the host system libc. This is necessary for the vast majority of Win32 applications, as they typically depend on various features of MSVCRT. This switch is also used by the MinGW compiler to link against MSVCRT on Windows, instead of linking against Cygwin libc. Sharing the syntax with MinGW makes it very easy to write Makefiles that work under Wine, MinGW+MSYS, or MinGW+Cygwin.
所以我再次尝试使用 -mno-cygwin
,并收到一条以以下内容开头的 2000 行错误消息:
okuu% wineg++ frame.cpp -o frame.exe -mwindows -mno-cygwin
In file included from /usr/include/c++/7.2.1/cstdlib:75:0,
from /usr/include/c++/7.2.1/bits/stl_algo.h:59,
from /usr/include/c++/7.2.1/algorithm:62,
from ../win32xx/include/wxx_appcore0.h:110,
from ../win32xx/include/wxx_appcore.h:57,
from ../win32xx/include/wxx_wincore.h:96,
from frame.cpp:1:
/usr/include/stdlib.h:310:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *fptr; /* Front pointer. */
^~~~~~~
wint_t
/usr/include/stdlib.h:311:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *rptr; /* Rear pointer. */
^~~~~~~
wint_t
/usr/include/stdlib.h:312:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *state; /* Array of state values. */
^~~~~~~
wint_t
/usr/include/stdlib.h:316:5: error: ‘int32_t’ does not name a type; did you mean ‘wint_t’?
int32_t *end_ptr; /* Pointer behind state table. */
^~~~~~~
wint_t
/usr/include/stdlib.h:320:8: error: ‘int32_t’ has not been declared
int32_t *__restrict __result) __THROW __nonnull ((1, 2));
^~~~~~~
所以看起来C99 的固定大小整数类型不可用。这似乎很容易解决:
frame.cpp
#include <stdint.h>
#include "../win32xx/include/wxx_wincore.h"
#include "../win32xx/include/wxx_frame.h"
// etc. etc. etc.
我又试了一次,但收到了一条不同的 2000 行错误消息,其开头为:
okuu% wineg++ frame.cpp -o frame.exe -mwindows -mno-cygwin
In file included from /usr/include/c++/7.2.1/cwchar:44:0,
from /usr/include/c++/7.2.1/bits/postypes.h:40,
from /usr/include/c++/7.2.1/bits/char_traits.h:40,
from /usr/include/c++/7.2.1/string:40,
from ../win32xx/include/wxx_appcore0.h:111,
from ../win32xx/include/wxx_appcore.h:57,
from ../win32xx/include/wxx_wincore.h:96,
from frame.cpp:2:
/usr/local/include/wine/msvcrt/wchar.h:398:23: error: conflicting declaration of C function ‘size_t mbstowcs(wchar_t*, const char*, size_t)’
size_t __cdecl mbstowcs(wchar_t*,const char*,size_t);
^~~~~~~~
此时我 运行 没有主意了。这是我目前的理解:
- 我系统的 libc 和 Wine 的 MSVCRT 有冲突的定义。 (这可能是预料之中的。)
- 我系统的 libc++ 是硬连线的,可以与我系统的 libc 一起工作。
- Wine 带有 MSVCRT,但没有 C++ 标准库实现。
根据我目前掌握的信息,合理的做法是寻找与 Wine 的 MSVCRT 兼容的 C++ 标准库实现,但我不知道有一个。这里有人知道吗?
我能想到的唯一解决方案是坚持使用系统 libc 并编写自己的 process.h
。该文件应该 #include
具有 Win32++ 需要的函数的标准 header 文件,或者提供这些函数自己的实现。如果 Win32++ 在没有特定函数的情况下无法编译,但您的程序实际上并不依赖于该函数,则该函数的实现可以简单地 return 0 或另一个假值。
如果系统 libc 有一个 Win32++ 要求的 header 文件,但该文件没有声明 Win32++ 期望的所有函数,您将不得不编写一个 header 文件,例如作为定义这些函数的 win32xx-compat.h
和 #include
它在任何 Win32++ header.