While Linux has one of the largest software catalogues on the planet,
there are still many software applications which are either only
available for Windows or are only possible to make on Windows. For
users, it means that they will miss out on some of their favourite
software (for example, Microsoft Office and a lot of games). For
developers it means losing a significant market to people who are using
Linux. While most of the software can be written for both the platforms
if you plan ahead, it becomes painfully difficult (and sometimes
impossible) when the software is already written. This is where Wine
comes to rescue.
For users, Wine provides a way of running Windows applications
without any modification on a Linux system. For developers, it provides a
way of making their applications work with Linux with maximum
compatibility.
Wine
Before we dive into the tutorial, let’s understand what Wine is. Wine
is not an emulator that emulates the Windows OS to run Windows
applications. It is a compatibility layer for Windows applications on
POSIX-compliant operating systems such as Linux, BSD and Mac OS X. It
translates Windows API calls into POSIX calls on-the-fly. Being just a
compatibility layer means that Wine runs applications at native
performance. That’s not all: since it doesn’t need Windows to function,
you won’t need a Windows licence to run Windows applications. In
addition to the Windows compatibility, Wine provides open source
implementations for some of the most sought-after APIs in the industry
(like DirectX, ActiveX, DDE etc).
Wine helps Windows developers to bring their software to Linux in the following ways…
Direct binary execution: This is achieved with the tool called ‘wine’
(part of the Wine distribution). In this process, application source
code is compiled on the Windows platform, and then the binary file is
taken to the Linux system and is run through Wine. When the application
is run with binary compatibility, it can use all existing .dll files.
This process is pretty straightforward, but is not able to unleash the
full power of the Wine subsystem. However, this is the only way to go if
you do not have the access to the source code. You can also wrap Wine
with your application to create an easy-to-use way to run it on the
Linux platform.
Recompiling the application with Winelib: In this method the source
code file is taken to the Linux box, where it is compiled against the
Winelib libraries using GCC. This way, the application will also be able
to catch up with UNIX API calls in order to leverage the full power of
UNIX. Winelib ships with a tool called Winemaker, which creates a GNU
standard autoconf-based makefile out of a VC++ project. Winemaker is a
Perl script that does all the dirty work involved in converting the
source code, making it UNIX specific, clearing up case issues and a lot
more.
Winelib
Winelib is a software development kit for building Windows
applications for Linux (and other POSIX operating systems). It includes
the Win32 API implementation providing the necessary libraries and
header files. It supports C/C++ and shares 100 per cent of its code with
Wine.
Winelib is capable of building GUI applications, console applications and dynamic- link libraries (DLLs).
One of the biggest benefits Winelib provides is the ability to make
calls to UNIX APIs directly from your Windows source code, resulting in
better integration than with the direct binary execution method.
In this tutorial we will be using Winelib to compile a Visual C++ application on the Linux platform.
Resources
Mandatory development tools: GCC, G++, Make etc
Git: It is used by the Wine project as the primary source control system
Optional: Access to Windows system with Microsoft Visual Studio 2008 installed
Step by Step
Wine Notepad running in chrooted environment
Step 01
Rules of engagement
The first step to any porting project is to make sure your code is
ready for the new platform. There are a few basic rules of thumb that
apply to any application which is supposed to be ported. These cover
some basic Windows and Linux operating environment differences. First,
differences between DOS and UNIX text files must be fixed. Otherwise you
may receive errors related to carriage returns and numerous other
similar errors.
Then there’s the case of filenames. As you will probably be aware,
kunal.c and Kunal.c are the same in a Windows environments, but not in
Linux. So, the filenames used in include statements might be different
from the original files you are actually referring to.
Include statements should avoid using ‘\’ – instead they should use
‘/’. ‘/’ is recognised in both the environments, but using ‘\’ may cause
errors in UNIX.
Makefiles should be changed accordingly to fit into the new environment. Makefiles are not generally cross-platform compatible.
Sprinkle your code with #ifdefs. This good old technique can be used
to isolate the platform- specific code in a very efficient manner.
#ifdef _WIN32
// Windows (x64 and x86)
#elif __unix__ // all unix
// Unix
#elif __posix__
// POSIX
#elif __linux__
// linux
#elif __APPLE__
// Mac OSX code
#endif
Step 02
Building Wine
There is a very good chance that the Wine shipping with your
favourite Linux distribution is outdated. That’s why we will build Wine
directly from the source. This will allow us to build Wine to our
liking.
NOTE: We are using Ubuntu 12.10 64-bit for this tutorial.
If you are using any other 64-bit distribution you will need the
respective package management command. If you are using Ubuntu 12.10
32-bit or any other 32-bit distribution, skip this – go directly to
installing build dependencies.
Creating chroot for Wine: Since Wine depends upon a lot of 32-bit
libraries, it is a good idea to build it in a chroot environment. A
chroot is a way of isolating applications from the rest of your
computer, by putting them in a jail. In this case we will set up a
chroot with the 32-bit binaries and libraries.
Install the chroot packages
$ sudo apt-get install dchroot debootstrap
Create a directory which will hold the root of the chroot environment
$ sudo mkdir /var/chroot
Create chroot configuration for the
current distribution
You’ll need to replace ‘Quantal’ with the name of the distro you are
using. You will also need to replace ‘kunal’ with the correct username.
NOTE: The distribution name should be a valid distribution, else
chroot environment will not be created. To find valid and supported
distribution names, look in the directory
/usr/share/debootstrap/scripts/.
Install the base system for your chroot
NOTE: You can replace the mirror with one of your liking, preferably
nearby. A list of mirrors is located at
https://launchpad.net/ubuntu/+archivemirrors. You will need to make sure
that the mirror you are selecting contains the distribution you are
chrooting.
Set up the Apt sources
We are now all set up to build Wine. # cd wine*
# ./configure
# make
# make install
Setting up the X-server
To make the GUI applications work from within the chrooted environment, you will need to set up the X-server:
On the system shell
$ xhost +
On the chrooted shell
# export DISPLAY=:0.0
You can now test the setup by running the following command
# wine notepad
Now you can use the chrooted environment for all your Wine-related activities.
Step 03
Porting Hello World Win32 application
In this step we will see what it takes to build a simple Hello World application in Linux using Wine.
The following example shows a message box with the text ‘Hello from Windows World!’.
hello.c
#include
int WINAPI WinMain(HINSTANCE
hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd )
{
MessageBox(NULL,TEXT(“Hello
from Windows
World!”),TEXT(“HelloMsg”),0);
return 0;
}
Winelib ships with nice GCC wrappers which are compatible with the
MinGW compiler. These wrappers are called winegcc and wineg++. This way
if you have an application that uses the MinGW compiler on Windows, you
can simply replace the gcc/g++/windres with winegcc/ wineg++/wrc .
To compile the application, we use the winegcc command:
# winegcc hello.c -o hello
Upon successful compilation, you will notice that it produces two files instead of just one. In this case…
hello.exe.so: This is the main binary of the application. But you
cannot execute this directly. It is a shared object file that must be
run using Wine. It is directly linked to the Wine library.
hello.exe: Although it looks like the main output of the source, it
is merely a script to launch the main application. You can modify
hello.exe to customise the launch parameters. You can even specify a
different version of Wine for use with the executable.
#!/bin/sh
appname=”hello.exe.so”
# determine the application
directory
appdir=''
case “$0” in
*/*)
# $0 contains a path, use it
appdir=`dirname “$0”`
;;
*)
# no directory in $0, search in
PATH
saved_ifs=$IFS
IFS=:
for d in $PATH
do
IFS=$saved_ifs
if [ -x “$d/$appname” ]; then appdir=”$d”; break; fi
done
;;
esac
# figure out the full app path
if [ -n “$appdir” ]; then
apppath=”$appdir/$appname”
WINEDLLPATH=”$appdir:$WINEDLLPATH”
export WINEDLLPATH
else
apppath=”$appname”
fi
# determine the WINELOADER
if [ ! -x “$WINELOADER” ]; then
WINELOADER=”wine”; fi
# and try to start the app
exec “$WINELOADER” “$apppath” “$@”
Visual Studio 2008 New Project dialog
Step 04
Porting a bigger project using Winemaker
Winegcc is helpful if your application consists of only one file, but
that isn’t usually the case. In most cases a Windows application
consists of multiple source files as well as resource files. Winelib
ships with a tool called Winemaker. It is capable of generating
UNIX-compatible makefiles from Windows project source code. Winemaker is
a very important tool in getting your first step (also the most
difficult one) ready. It does all the dirty work for you, from fixing up
files to creating a UNIX-compatible makefile. It is capable of fixing
most of the issues mentioned in step 1 ‘Rules of engagement’.
Winemaker provides the following options to help you out with porting
your code. These options customise the resultant makefile to suit your
needs.
–lower-uppercase: This option deals with the cases of filenames and puts them in order.
–dll: This option instructs Winelib to build a DLL (dynamic-link library) project instead of a GUI project.
–console: This option directs Winelib to build a console application.
–mfc: This directs Winelib to build an MFC (Microsoft Foundation
Class) library application. Please note that Wine does not ship with the
MFC library; you will have to build it on your own with Winelib.
–nobackup: Winelib keeps a backup of files which it changes. If you
already have this source code present somewhere else, you can use this
option to save a lot of time and disk space.
-Idir: Specifies to include file directories. This option accepts paths to files in absolute format.
-Ldir: Specifies library file directories.
-idll: Directs Winelib to import a library file through the spec file mechanism.
-llibrary: Instructs Winelib to import UNIX library files
In this step we will take the default application built by Microsoft
Visual Studio and try to compile it with Winemaker on Linux.
Creating the Win32 Application:
Open Microsoft Visual Studio 2008. Click File> New>Project…
From the New Project dialog box, select Visual C++>Win32. Then
select Win32 Project. Give an appropriate Name for the project, Location
and Solution Name. Then click OK. The Win32 Application Wizard will
open.
Click Next to continue. On the Application Settings page, select the
Application type as a Windows application. Leave the rest of the
settings as is. Click Finish to create the project.
The finished project will now open in Visual Studio. Solution Explorer will show all the files created for the project.
As you can see, this is a fully featured project with multiple header
files, source files and resource files. For this tutorial we need to
modify the project itself. We would rather focus on porting part of this
application.
Let’s run this application to see if everything is working perfectly.
Click Build>Build Solution to build the project, then click
Debug>Start Without Debugging.
Copy the LUDWin32Project directory to the chrooted folder, ie
/var/chroot/. Then perform the following steps to create a UNIX makefile
project using Winemaker:
cd into main project directory
# cd LUDWin32Project/ LUDWin32Project/
Run Winemaker to fix the source files and create UNIX makefiles:
# winemaker --lower-uppercase --nomfc .
Winemaker 0.8.3
Copyright 2000-2004 Francois Gouget for CodeWeavers
Copyright 2004 Dimitrie O. Paun
Copyright 2009-2012 Andr Hentschel Scanning the source directories... Projectfile found! You might want to try using it directly.
Fixing the source files...
LUDWin32Project.cpp
LUDWin32Project.rc
LUDWin32Project.h
Resource.h
stdafx.cpp
stdafx.h
targetver.h
Generating project files...
.
The above command fixes the case-related issues with the source code.
‘-nomfc’ indicates that we do not want to use the MFC library with this
project. As you can see in the out put above, it has located a project
file (vcproj), but we will skip it for this tutorial as Visual Studio
project files are not fully compatible with Winemaker.
Winemaker will fix the files and create .bak files for the modified
files. It will also create the makefile which we can run against the
standard GNU Make utility to build the application.
Makefile structure of a Winelib project:
Most of the time, the makefile generated with Winemaker will be a good
fit for your project. However, for some advanced and complex
applications, you might need to customise the makefile yourself. The
following explains the very basic structure of a Winelib project.
Makefile generated by Winemaker
SRCDIR = .
SUBDIRS =
DLLS =
LIBS =
EXES =
ludwin32project
### Common settings
CEXTRA = -mno-cygwin
CXXEXTRA = -mno-cygwin
### Global source lists
C_SRCS =
$(ludwin32project_C_SRCS)
CXX_SRCS =
$(ludwin32project_CXX_SRCS)
RC_SRCS =
$(ludwin32project_RC_SRCS)
### Tools
CC = winegcc
CXX = wineg++
RC = wrc
AR = ar
This is not a complete makefile, but the main options you should take
a look at. However, most of the options will be filled by Winemaker
itself.
Compile the project by issuing Make
As you can see, the correct compilers are used for respective files.
For example, wineg++ is used for .cpp files, wrc (Wine Resource
Compiler) is used for .rc files.
The ‘make’ command will produce ludwin32project.exe.so and
ludwin32project.exe. Run the ludwin32project.exe file to start the
ported application. Solution Explorer with LUDWin32Project open
Step 05
Conclusion
Wine is one of the key technologies which can help you go Windows
free. There are an enormous number of Windows applications that just
work on Wine without developer support – see the full list at the Wine HQ.
If your application is not on that list, you can use Winelib to port
your application natively to Linux. It will have the same performance as
any other native application. Winelib is very easy to use, especially
with a tool like winemaker which takes care of much of the standard
porting issues by itself. So, if you are a Windows developer avoiding
the Linux platform because you thought it was too much work, it’s time
to give Wine a try.
Hello Sameh, how are you?! Very nice and informative article. I am pretty new to using winelib and have been trying to build my MFC GUI source with winelib, but because they didn't ship mfc90u.dll.so files I couldn't do that. I understand b-se of mfc licence issue (microsoft huh :( ) There is very little info on 'winehq' about creating your own winedlls using .spec file and function prototypes, but mfc library is so huge with many functions. I tried to use winedump & winebuild to create .spec file but it come empty. Tried convert mfc.def to mfc.spec but no success. I have my purchased copy of licensed MSVS2008 so have mfc90 source code. I wonder could you help with compiling mfc and creating mfc90u.dll.so winelib dlls.Or post article about it. Thanks !!!
Hello Sameh, how are you?! Very nice and informative article. I am pretty new to using winelib and have been trying to build my MFC GUI source with winelib, but because they didn't ship mfc90u.dll.so files I couldn't do that. I understand b-se of mfc licence issue (microsoft huh :( ) There is very little info on 'winehq' about creating your own winedlls using .spec file and function prototypes, but mfc library is so huge with many functions. I tried to use winedump & winebuild to create .spec file but it come empty. Tried convert mfc.def to mfc.spec but no success. I have my purchased copy of licensed MSVS2008 so have mfc90 source code.
ReplyDeleteI wonder could you help with compiling mfc and creating mfc90u.dll.so winelib dlls.Or post article about it. Thanks !!!
Send me files and steps u followed with their output
ReplyDelete