Building my first Windows application in Wine [Draft]

Why am I doing this? To determine if Windows’ HTML Help API function HtmlHelp() allows an incorrect pzrURL parameter where backslashes rather than forward slashes are used after the :: delimiter, e.g.:

  • C:\Program Files\My App\Helpfile.chm::\Html\Overview\Topic.htm (incorrect) vs
  • C:\Program Files\My App\Helpfile.chm::/Html/Overview/Topic.htm (correct)

(TODO: write a separate blog article about it.)

Basic steps

(Note: I did not have Wine installed to system paths…)

  1. Save the sample Windows application source code, e.g., as hello.cpp
  2. Make sure wineg++ and winemaker are in the path.
  3. Use winemaker . to generate a Makefile
  4. Edit Makefile: Add appropriate compiler flags, include paths and library paths, etc.
  5. Run make. Fix problems as they arise.
  6. Test by running hello_world.exe (sh wrapper) directly, or by running ~/wine-dirs/wine-build/wine hello_world.exe.so.

Actually doing it

Fetch the source code

Scroll down to “Example > Code”, copy and paste the code listing, and save it as hello.cpp (original name: GT_HelloWorldWin32.cpp).

Prepare Makefile

First, generate an initial Makefile with the command winemaker .

Then, edit Makefile and modify the variables under ### Common settings:

  1. Set DEFINES to -D_UNICODE -DUNICODE -DWIN32 -D_WINDOWS (per instruction in the header of GT_HelloWorldWin32.cpp)

  2. Set INCLUDE_PATH to -I$(HOME)/wine-dirs/wine-source/include -I$(HOME)/wine-dirs/wine-build/include (Some Wine include files are generated during build time. Also, note that tilde expansion does not work here, so $(HOME) rather than ~.)

  3. Set DLL_PATH to -L$(HOME)/wine-dirs/wine-build/dlls

  4. Set LIBRARY_PATH to -L$(HOME)/wine-dirs/wine-build/libs/wine

Deal with compilation errors

In file included from hello.cpp:7:0:
../wine-source/include/tchar.h:27:2: error: #error You must use msvcrt when building in Unicode/MBCS mode
 #error You must use msvcrt when building in Unicode/MBCS mode
  ^

But how do I use “use msvcrt”?

-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.

So, yay! The -mno-cygwin flag does work according to winegcc’s man page.

Reporting the bug upstream

See https://bugs.winehq.org/show_bug.cgi?id=39904

More errors

In file included from ../wine-source/include/windows.h:40:0,
                 from hello.cpp:4:
hello.cpp: In function 'int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)':
../wine-source/include/winuser.h:737:58: error: cast from 'LPWSTR {aka wchar_t*}' to 'WORD {aka short unsigned int}' loses precision [-fpermissive]
 #define MAKEINTRESOURCEW(i) (LPWSTR)((ULONG_PTR)((WORD)(i)))
                                                          ^

Add -fpermissive to CXXEXTRA to fix this.

References

Unsorted but useful: