Winelib User Guide Introduction Winelib is a development toolkit which allows you to compile your Windows applications on Unix. Most of Winelib's code consists of the Win32 API implementation. Fortunately this part is 100 percent shared with Wine. The remainder consists of Windows compatible headers and tools like the resource compiler (and even these are used when compiling Wine). Thanks to the above, Winelib supports most C and C++ 32bit source code, resource and message files, and can generate graphical or console applications as well as dynamic libraries. What is not supported is 16bit source code as the types it depends on (especially segmented pointers) are not supported by Unix compilers. Also missing are some of the more exotic features of Microsoft's compiler like native COM support and structured exception handling. So you may need to perform some modifications in your code when recompiling your application with Winelib. This guide is here to help you in this task. What you gain by recompiling your application with Winelib is the ability to make calls to Unix APIs, directly from your Windows source code. This allows for a better integration with the Unix environment than is allowed by runnning an unmodified Windows application running in Wine. Another benefit is that a Winelib application can relatively easily be recompiled on a non-Intel architecture and run there without the need for a slow software emulation of the processor. System requirements The requirements for Winelib are similar to those for Wine. Basically if you can run Wine on your computer then you can run Winelib. But the converse is not true. You can also build Winelib and Winelib applications on platforms not supported by Wine, typically platforms with a non i386 processor. But this is still pretty much an uncharted territory. It would be more reasonable to first target one of the more mundane i386-based platforms first. The main difference is that the compiler becomes much more important. It is highly recommended that you use gcc, g++, and the GNU binutils. The more recent your gcc compiler the better. For any serious amount of code you should not consider anything older than gcc 2.95.2. The latest gcc snapshots contain some useful bug fixes and much better support for anonymous structs and unions. This can help reduce the number of changes you have to do in your code but these are not stable releases of the compiler so you may not want to use them in production. Getting Started Winemaker introduction So what is needed to compile a Windows application with Winelib? Well, it really depends on the complexity of your application but here are some issues that are shared by all applications: the case of your files may be bad. For example they could be in all caps: HELLO.C. It's not very nice to work with and probably not what you intended. then the case of the filenames in your include statements may be wrong: maybe they include 'Windows.h' instead of 'windows.h'. your include statements may use '\' instead of '/'. '\' is not recognized by Unix compilers while '/' is recognized in both environments. you will need to perform the usual Dos to Unix text file conversion otherwise you'll get in trouble when the compiler considers that your '\' is not at the end of the line since it is followed by a pesky carriage return. you will have to write new makefiles. The best way to take care of all these issues is to use winemaker. Winemaker is a perl script which is designed to help you bootstrap the conversion of your Windows projects to Winelib. In order to do this it will go analyze your code, fixing the issues listed above and generate autoconf-based Makefiles. Let's suppose that Wine/Winelib has been installed in the /usr/local/wine directory, and that you are already in the top directory of your sources. Then converting your project to Winelib may be as simple as just running the three commands below: $ winemaker --lower-uppercase $ ./configure --with-wine=/usr/local/wine $ make But of course things are not always that simple which is why we have this guide at all. Step by step guide Let's retrace the steps above in more details. First if you can try to get the sources together with the executables/libraries that they build. In the current state of winemaker having these around can help it guess what it is that your project is trying to build. Later, when it is able to understand Visual C++ projects, and if you use them, this will no longer be necessary. Usually the executables and libraries are in a Release or Debug subdirectory of the directory where the sources are. So it's best if you can transfer the source files and either of these directories to Linux. Note that you don't need to transfer the .obj, .pch, .sbr and other files that also reside in these directories; especially as they tend to be quite big. Then go to the root directory where are your source files. Winemaker can deal with a whole directory hierarchy at once so you don't need to go into a leaf directory, quite the contrary. Winemaker will automatically generate makefiles in each directory where one is required, and will generate a global makefile so that you can rebuild all your executables and libraries with a single make command. Then make sure you have write access to your sources. It may sound obvious, but if you copied your source files from a CD-ROM or if they are in Source Safe on Windows, chances are that they will be read-only. But Winemaker needs write access so that it can fix them. You can arrange that by running chmod -R u+w .. Also you will want to make sure that you have a backup copy of your sources in case something went horribly wrong, or more likely, just for reference at a later point. If you use a version control system you're already covered. Then you'll run winemaker. Here are the options you will most likely want to use. These options specify how to deal with files, and directories, that have an 'incorrect' case. specifies they should only be renamed if their name is all uppercase. So files that have a mixed case, like 'Hello.c' would not be renamed. will rename any file. If neither is specified then no file or directory will be renamed, almost. As you will see later winemaker may still have to rename some files. Winemaker normally makes a backup of all the files in which it does more than the standard Dos to Unix conversion. But if you already have (handy) copies of these files elsewhere you may not need these so you should use this option. These option lets winemaker know what kind of target you are building. If you have the windows library in your source hierarchy then you should not need to specify . But if you have console executables then you will need to use the corresponding option. This option tells winemaker that you are building an MFC application/library. The specifies a Winelib library to import via the spec file mechanism. Contrast this with the which specifies a Unix library to link with. The other options work the same way they would with a C compiler. All are applied to all the targets found. When specifying a directory with either or , winemaker will prefix a relative path with $(TOPDIRECTORY)/ so that it is valid from any of the source directories. You can also use a variable in the path yourself if you wish (but don't forget to escape the '$'). For instance you could specify -I\$(WINELIB_INCLUDE_ROOT)/msvcrt. So your command may finally look like: winemaker --lower-uppercase -Imylib/include When you execute winemaker it will first rename files to bring their character case in line with your expectations and so that they can be processed by the makefiles. This later category implies that files with a non lowercase extension will be renamed so that the extension is in lowercase. So, for instance, HELLO.C will be renamed to HELLO.c. Also if a file or directory name contains a space or a dollar, then this character will be replaced with an underscore. This is because these characters cause problems with current versions of autoconf (2.13) and make (3.79). winemaker will then proceed to modify the source files so that they will compile more readily with Winelib. As it does so it may print warnings when it has to make a guess or identifies a construct that it cannot correct. Finally it will generate the autoconf-based makefiles. Once all this is done you can review the changes that winemaker did to your files by using diff -uw. For instance: diff -uw hello.c.bak hello.c Before you run make you must run the autoconf configure script. The goal of this step is to analyze your system and generate customized makefiles from the Makefile.in files. This is also when you have to tell where Winelib resides on your system. If wine is installed in a single directory or you have the Wine sources compiled somewhere then you can just run ./configure --with-wine=/usr/local/bin or ./configure --with-wine=~/wine respectively. This is a pretty simple step: just type make and voila, you should have all your executables and libraries. If this did not work out, then it means that you will have to read this guide further to: review the Makefile.in files to adjust the default compilation and link options set by winemaker. See the section for some hints. fix the portability issues in your sources. See for more details. Portability issues Anonymous unions/structs Anonymous structs and unions support depends heavily on the compiler. The best support is provided by gcc/g++ 2.96 and later. But these versions of gcc come from the development branch so you may want to hold off before using them in production. g++ 2.95 supports anonymous unions but not anonymous structs and gcc 2.95 supports neither. Older versions of gcc/g++ have no support for either. since it is anonymous unions that are the most frequent in the windows headers, you should at least try to use gcc/g++ 2.95. But you are stuck with a compiler that does not support anonymous structs/unions all is not lost. The Wine headers should detect this automatically and define NONAMELESSUNION / NONAMELESSSTRUCT. Then any anonymous union will be given a name u or u2, u3, etc. to avoid name clashes. You will then have to modify your code to include those names where appropriate. The name that Wine adds to anonymous unions should match that used by the Windows headers. So all you have to do to compile your modified code in Windows is to explicitly define the NONAMELESSUNION macro. Note that it would be wise to also explicitly define this macro on in your Unix makefile (Makefile.in) to make sure your code will compile even if the compiler does support anonymous unions. Things are not as nice when dealing with anonymous structs. Unfortunately the Windows headers make no provisions for compilers that do not support anonymous structs. So you will need to be more subtle when modifying your code if you still want it to compile in Windows. Here's a way to do it: #ifdef WINELIB #define ANONS .s #else #define ANONS #endif . . . { SYSTEM_INFO si; GetSystemInfo(&si); printf("Processor architecture=%d\n",si ANONS .wProcessorArchitecture); } You may put the #define directive directly in the source if only few files are impacted. Otherwise it's probably best to put it in one of your project's widely used headers. Fortunately usage of an anonymous struct is much rarer than usage of an anonymous union so these modifications should not be too much work. Unicode L"foo" generates 4-byte chars, use __TEXT (or _TEXT?), C library C library Winelib currently only supports on C library: that of your compiler. three solutions: native, mixed or msvcrt except we only have native right now, using the native C library -> different behavior: fopen, O_TEXT, unicode support, reimplement msvcrt Initialization problems Initialization problems occur when the application calls the Win32 API before Winelib has been initialized. How can this happen? Winelib is initialized by the application's main before it calls the regular WinMain. But, in C++, the constructors of static class variables are called before the main (by the module's initializer). So if such a constructor makes calls to the Win32 API, Winelib will not be initialized at the time of the call and you may get a crash. This problem is much more frequent in C++ because of these class constructors but could also, at least in theory, happen in C if you were to specify an initializer making calls to Winelib. But of course, now that you are aware of this problem you won't do it :-). Further compounding the problem is the fact that Linux's (GNU's?) current dynamic library loader does not call the module initializers in their dependency order. So even if Winelib were to have its own initializer there would be no garantee that it would be called before the initializer of the library containing this static variable. Finally even if the variable is in a library that your application links with, that library's initializer may be called before Winelib has been initialized. One such library is the MFC. The current workaround is to move all the application's code in a library and to use a small Winelib application to dynamically load this library. Tus the initialization sequence becomes: the wrapper application starts. its empty initializer is run. its main is run. Its first task is to initialize Winelib. it then loads the application's main library, plus all its dependent libraries. which triggers the execution of all these libraries initializers in some unknown order. But all is fine because Winelib has already been initialized anyway. finally the main function calls the WinMain of the application's library. This may sound complex by Winemaker makes it simple. Just specify or on the command line and it will adapt its makefiles to build the wrapper and the application library. VC's native COM support don't use it, guide on how to replace it with normal C++ code (yes, how???): extracting a .h and .lib from a COM dll Can '-fno-rtti' be of some use or even required? SEH how to modify the syntax so that it works both with gcc's macros and Wine's macros, is it even possible? Others -fpermissive and -fno-for-scope, maybe other options The Winelib development toolkit Winemaker Support for Visual C++ projects Unfortunately Winemaker does not support the Visual C++ project files, ...yet. Supporting Visual C++ project files (the .dsp and some .mak files for older versions of Visual C++) is definitely on the list of important Winemaker improvements as it will allow it to properly detect the defines to be used, any custom include path, the list of libraries to link with, and exactly which source files to use to build a specific target. All things that the current version of Winemaker has to guess or that you have to tell it as will become clear in the next section. When the time comes Winemaker, and its associated build system, will need some extensions to support: per file defines and include paths. Visual C++ projects allow the user to specify compiler options for each individual file being compiled. But this is probably not very frequent so it might not be that important. multiple configurations. Visual C++ projects usually have at least a 'Debug' and a 'Release' configuration which are compiled with different compiler options. How exactly we deal with these configurations remains to be determined. Winemaker's source analysis Winemaker can do its work even without a Windows makefile or a Visual Studio project to start from (it would not know what to do with a windows makefile anyway). This involves doing many educated guesses which may be wrong. But by and large it works. The purpose of this section is to describe in more details how winemaker proceeds so that you can better understand why it gets things wrong and how to fix it/avoid it. At the core winemaker does a recursive traversal of your source tree looking for targets (things to build) and source files. Let's start with the targets. First are executables and dlls. Each time it finds one of these in a directory, winemaker puts it in the list of things to build and will later generate a Makefile.in file in this directory. Note that Winemaker also knows about the commonly used Release and Debug directories, so it will attribute the executables and libraries found in these to their parent directory. When it finds an executable or a dll winemaker is happy because these give it more information than the other cases described below. If it does not find any executable or dll winemaker will look for files with a .mak extension. If they are not disguised Visual C++ projects (and currently even if they are), winemaker will assume that a target by that name should be built in this directory. But it will not know whether this target is an executable or a library. So it will assume it is of the default type, i.e. a graphical application, which you can override by using the and options. Finally winemaker will check to see if there is a file called makefile. If there is, then it will assume that there is exactly one target to build for this directory. But it will not know the name or type of this target. For the type it will do as in the above case. And for the name it will use the directory's name. Actually, if the directory starts with src winemaker will try to make use of the name of the parent directory instead. Once the target list for a directory has been established, winemaker will check whether it contains a mix of executables and libraries. If it is so, then winemaker will make it so that each executable is linked with all the libraries of that directory. If the previous two steps don't produce the expected results (or you think they will not) then you should put winemaker in interactive mode (see ). This will allow you to specify the target list (and more) for each directory. In each directory winemaker also looks for source files: C, C++ or resource files. If it also found targets to build in this directory it will then try to assign each source file to one of these targets based on their names. Source files that do not seem to match any specific target are put in a global list for this directory, see the EXTRA_xxx variables in the Makefile.in, and linked with each of the targets. The assumption here is that these source files contain common code which is shared by all the targets. If no targets were found in the directory where these files are located, then they are assigned to the parent's directory. So if a target is found in the parent directory it will also 'inherit' the source files found in its subdirectories. Finally winemaker also looks for more exotic files like .h headers, .inl files containing inline functions and a few others. These are not put in the regular source file lists since they are not compiled directly. But winemaker will still remember them so that they are processed when the time comes to fix the source files. Fixing the source files is done as soon as winemaker has finished its recursive directory traversal. The two main tasks in this step are fixing the CRLF issues and verifying the case of the include statements. Winemaker makes a backup of each source file (in such a way that symbolic links are preserved), then reads it fixing the CRLF issues and the other issues as it goes. Once it has finished working on a file it checks whether it has done any non CRLF-related modification and deletes the backup file if it did not (or if you used ). Checking the case of the include statements (of any form, including files referenced by resource files), is done in the context of that source file's project. This way winemaker can use the proper include path when looking for the file that is included. If winemaker fails to find a file in any of the directories of the include path, it will rename it to lowercase on the basis that it is most likely a system header and that all system headers names are lowercase (this can be overriden by using ). Finally winemaker generates the Makefile.in files and other support files (wrapper files, spec files, configure.in, Make.rules.in). From the above description you can guess at the items that winemaker may get wrong in this phase: macro definitions, include path, library path, list of libraries to import. You can deal with these issues by using winemaker's , , and options if they are homogeneous enough between all your targets. Otherwise you may want to use winemaker's interactive mode so that you can specify different settings for each project / target. For instance, one of the problems you are likely to encounter is that of the STRICT macro. Some programs will not compile if STRICT is not turned on, and others will not compile if it is. Fortunately all the files in a given source tree use the same setting so that all you have to do is add -DSTRICT on winemaker's command line or in the Makefile.in file(s). Finally the most likely reasons for missing or duplicate symbols are: The target is not being linked with the right set of libraries. You can avoid this by using winemaker's and options or adding these libraries to the Makefile.in file. Maybe you have multiple targets in a single directory and winemaker guessed wrong when trying to match the source files with the targets. The only way to fix this kind of problem is to edit the Makefile.in file manually. Winemaker assumes you have organized your source files hierarchically. If a target uses source files that are in a sibling directory, e.g. if you link with ../hello/world.o then you will get missing symbols. Again the only solution is to manually edit the Makefile.in file. The interactive mode what is it, when to use it, how to use it The Makefile.in files The Makefile.in is your makefile. More precisely it is the template from which the actual makefile will be generated by the configure script. It also relies on the Make.rules file for most of the actual logic. This way it only contains a relatively simple description of what needs to be built, not the complex logic of how things are actually built. So this is the file to modify if you want to customize things. Here's a detailed description of its content: ### Generic autoconf variables TOPSRCDIR = @top_srcdir@ TOPOBJDIR = . SRCDIR = @srcdir@ VPATH = @srcdir@ The above is part of the standard autoconf boiler-plate. These variables make it possible to have per-architecture directories for compiled files and other similar goodies (But note that this kind of functionality has not been tested with winemaker generated Makefile.in files yet). SUBDIRS = DLLS = EXES = hello This is where the targets for this directory are listed. The names are pretty self-explanatory. SUBDIRS is usually only present in the top-level makefile. For libraries you should put the full Unix name, e.g. libfoo.so. ### Global settings DEFINES = -DSTRICT INCLUDE_PATH = LIBRARY_PATH = LIBRARIES = This section contains the global compilation settings: they apply to all the targets in this makefile. The LIBRARIES variable allows you to specify additional Unix libraries to link with. Note that you would normally not specify Winelib libraries there. To link with a Winelib library, one uses the 'import' statement of the spec files. The exception is when you have not explicitly exported the functions of a Winelib library. One library you are likely to find here is mfc (note, the '-l' is omitted). The other variable names should be self-explanatory. You can also use three additional variables that are usually not present in the file: CEXTRA, CXXEXTRA and WRCEXTRA which allow you to specify additional flags for, respectively, the C compiler, the C++ compiler and the resource compiler. Finally note that all these variable contain the option's name except IMPORTS. So you should put -DSTRICT in DEFINES but winmm in IMPORTS. Then come one section per target, each describing the various components that target is made of. ### hello sources and settings hello_C_SRCS = hello.c hello_CXX_SRCS = hello_RC_SRCS = hello_SPEC_SRCS = hello.spec Each section will start with a comment indicating the name of the target. Then come a series of variables prefixed with the name of that target. Note that the name of the prefix may be slightly different from that of the target because of restrictions on the variable names. The above variables list the sources that are used togenerate the target. Note that there should only be one resource file in RC_SRCS, and that SPEC_SRCS will always contain a single spec file. hello_LIBRARY_PATH = hello_LIBRARIES = hello_DEPENDS = The above variables specify how to link the target. Note that they add to the global settings we saw at the beginning of this file. DEPENDS, when present, specifies a list of other targets that this target depends on. Winemaker will automatically fill this field, and the LIBRARIES field, when an executable and a library are built in the same directory. The reason why winemaker also links with libraries in the Unix sense in the case above is because functions will not be properly exported. Once you have exported all the functions in the library's spec file you should remove them from the LIBRARIES field. hello_OBJS = $(hello_C_SRCS:.c=.o) \ $(hello_CXX_SRCS:.cpp=.o) \ $(EXTRA_OBJS) The above just builds a list of all the object files that correspond to this target. This list is later used for the link command. ### Global source lists C_SRCS = $(hello_C_SRCS) CXX_SRCS = $(hello_CXX_SRCS) RC_SRCS = $(hello_RC_SRCS) SPEC_SRCS = $(hello_SPEC_SRCS) This section builds 'summary' lists of source files. These lists are used by the Make.rules file. ### Generic autoconf targets all: $(DLLS) $(EXES:%=%.so) @MAKE_RULES@ install:: for i in $(EXES); do $(INSTALL_PROGRAM) $$i $(bindir); done for i in $(EXES:%=%.so) $(DLLS); do $(INSTALL_LIBRARY) $$i $(libdir); done uninstall:: for i in $(EXES); do $(RM) $(bindir)/$$i;done for i in $(EXES:%=%.so) $(DLLS); do $(RM) $(libdir)/$$i;done The above first defines the default target for this makefile. Here it consists in trying to build all the targets. Then it includes the Make.rules file which contains the build logic, and provides a few more standard targets to install / uninstall the targets. ### Target specific build rules $(hello_SPEC_SRCS:.spec=.tmp.o): $(hello_OBJS) $(LDCOMBINE) $(hello_OBJS) -o $@ -$(STRIP) $(STRIPFLAGS) $@ $(hello_SPEC_SRCS:.spec=.spec.c): $(hello_SPEC_SRCS:.spec) $(hello_SPEC_SRCS:.spec=.tmp.o) $(hello_RC_SRCS:.rc=.res) $(WINEBUILD) -fPIC $(hello_LIBRARY_PATH) $(WINE_LIBRARY_PATH) -sym $(hello_SPEC_SRCS:.spec=.tmp.o) -o $@ -spec $(hello_SPEC_SRCS) hello.so: $(hello_SPEC_SRCS:.spec=.spec.o) $(hello_OBJS) $(hello_DEP ENDS) $(LDSHARED) $(LDDLLFLAGS) -o $@ $(hello_OBJS) $(hello_SPEC_SRCS:.spec=.spec.o) $(hello_LIBRARY_PATH) $(hello_LIBRARIES:%=-l%) $(DLL_LINK) $(LIBS) test -e hello || $(LN_S) $(WINE) hello Then come additional directives to link the executables and libraries. These are pretty much standard and you should not need to modify them. The Make.rules.in file What's in the Make.rules.in... The configure.in file What's in the configure.in... Compiling resource files: WRC To compile resources you should use the Wine Resource Compiler, wrc for short, which produces a binary .res file. This resource file is then used by winebuild when compiling the spec file (see ). Again the makefiles generated by winemaker take care of this for you. But if you were to write your own makefile you would put something like the following: WRC=$(WINE_DIR)/tools/wrc/wrc WINELIB_FLAGS = -I$(WINE_DIR)/include -DWINELIB -D_REENTRANT WRCFLAGS = -r -L .SUFFIXES: .rc .res .rc.res: $(WRC) $(WRCFLAGS) $(WINELIB_FLAGS) -o $@ $< There are two issues you are likely to encounter with resource files. The first problem is with the C library headers. WRC does not know where these headers are located. So if an RC file, of a file it includes, references such a header you will get a 'file not found' error from wrc. Here are a few ways to deal with this: The solution traditionally used by the Winelib headers is to enclose the offending include statement in an #ifndef RC_INVOKED statement where RC_INVOKED is a macro name which is automatically defined by wrc. Alternately you can add one or more directive to your wrc command so that it finds you system files. For instance you may add -I/usr/include -I/usr/lib/gcc-lib/i386-linux/2.95.2/include to cater to both C and C++ headers. But this supposes that you know where these header files reside which decreases the portability of your makefiles to other platforms (unless you automatically detect all the necessary directories in the autoconf script). Or you could use the C/C++ compiler to perform the preprocessing. To do so, simply modify your makefile as follows: .rc.res: $(CC) $(CC_OPTS) -DRC_INVOKED -E -x c $< | $(WRC) -N $(WRCFLAGS) $(WINELIB_FLAGS) -o $@ The second problem is that the headers may contain constructs that WRC fails to understand. A typical example is a function which return a 'const' type. WRC expects a function to be two identifiers followed by an opening parenthesis. With the const this is three identifiers followed by a parenthesis and thus WRC is confused (note: WRC should in fact ignore all this like the windows resource compiler does). The current work-around is to enclose offending statement(s) in an #ifndef RC_INVOKED. Compiling message files: WMC how does one use it??? The Spec file Introduction In Windows the program's life starts either when its main is called, for console applications, or when its WinMain is called, for windows applications in the 'windows' subsystem. On Unix it is always main that is called. Furthermore in Winelib it has some special tasks to accomplish, such as initializing Winelib, that a normal main does not have to do. Furthermore windows applications and libraries contain some information which are necessary to make APIs such as GetProcAddress work. So it is necessary to duplicate these data structures in the Unix world to make these same APIs work with Winelib applications and libraries. The spec file is there to solve the semantic gap described above. It provides the main function that initializes Winelib and calls the module's WinMain / DllMain, and it contains information about each API exported from a Dll so that the appropriate tables can be generated. A typical spec file will look something like this: name hello type win32 mode guiexe init WinMain rsrc resource.res import winmm.dll And here are the entries you will probably want to change: name This is the name of the Win32 module. Usually this is the same as that of the application or library (but without the 'lib' and the '.so'). mode init mode defines whether what you are building is a library, dll, a console application, cuiexe or a regular graphical application guiexe. Then init defines what is the entry point of that module. For a library this is customarily set to DllMain, for a console application this is main and for a graphical application this is WinMain. import Add an 'import' statement for each library that this executable depends on. If you don't, these libraries will not get initialized in which case they may very well not work (e.g. winmm). rsrc This item specifies the name of the compiled resource file to link with your module. If your resource file is called hello.rc then the wrc compilation step (see ) will generate a file called hello.res. This is the name you must provide here. Note that because of this you cannot compile the spec file before you have compiled the resource file. So you should put a rule like the following in your makefile: hello.spec.c: hello.res If your project does not have a resource file then you must omit this entry altogether. @ This entry is not shown above because it is not always necessary. In fact it is only necessary to export functions when you plan to dynamically load the library with LoadLibrary and then do a GetProcAddress on these functions. This is not necessary if you just plan on linking with the library and calling the functions normally. For more details about this see: . Compiling it Compiling a spec file is a two step process. It is first converted into a C file by winebuild, and then compiled into an object file using your regular C compiler. This is all taken care of by the winemaker generated makefiles of course. But here's what it would like if you had to do it by hand: WINEBUILD=$(WINE_DIR)/tools/winebuild .SUFFIXES: .spec .spec.c .spec.o .spec.spec.c: $(WINEBUILD) -fPIC -o $@ -spec $< .spec.c.spec.o: $(CC) -c -o $*.spec.o $< Nothing really complex there. Just don't forget the .SUFFIXES statement, and beware of the tab if you copy this straight to your Makefile. More details (Extracted from tools/winebuild/README) Here is a more detailed description of the spec file's format. # comment text Anything after a '#' will be ignored as comments. name NAME type win16|win32 <--- the |'s mean it's one or the other These two fields are mandatory. name defines the name of your module and type whether it is a Win16 or Win32 module. Note that for Winelib you should only be using Win32 modules. file WINFILENAME This field is optional. It gives the name of the Windows file that is replaced by the builtin. <name>.DLL is assumed if none is given. This is important for kernel, which lives in the Windows file KRNL386.EXE. heap SIZE This field is optional and specific to Win16 modules. It defines the size of the module local heap. The default is no local heap. mode dll|cuiexe|guiexe This field is optional. It specifies specifies whether it is the spec file for a dll or the main exe. This is only valid for Win32 spec files. init FUNCTION This field is optional and specific to Win32 modules. It specifies a function which will be called when the dll is loaded or the executable started. import DLL This field can be present zero or more times. Each instance names a dll that this module depends on (only for Win32 modules at the present). rsrc RES_FILE This field is optional. If present it specifies the name of the .res file containing the compiled resources. See for details on compiling a resource file. ORDINAL VARTYPE EXPORTNAME (DATA [DATA [DATA [...]]]) 2 byte Variable(-1 0xff 0 0) This field can be present zero or more times. Each instance defines data storage at the ordinal specified. You may store items as bytes, 16-bit words, or 32-bit words. ORDINAL is replaced by the ordinal number corresponding to the variable. VARTYPE should be byte, word or long for 8, 16, or 32 bits respectively. EXPORTNAME will be the name available for dynamic linking. DATA can be a decimal number or a hex number preceeded by "0x". The example defines the variable Variable at ordinal 2 and containing 4 bytes. ORDINAL equate EXPORTNAME DATA This field can be present zero or more times. Each instance defines an ordinal as an absolute value. ORDINAL is replaced by the ordinal number corresponding to the variable. EXPORTNAME will be the name available for dynamic linking. DATA can be a decimal number or a hex number preceeded by "0x". ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME 100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word word word word ptr) WIN_CreateWindow 101 pascal GetFocus() WIN_GetFocus() This field can be present zero or more times. Each instance defines a function entry point. The prototype defined by EXPORTNAME ([ARGTYPE [ARGTYPE [...]]]) specifies the name available for dynamic linking and the format of the arguments. "ORDINAL" is replaced by the ordinal number corresponding to the function, or @ for automatic ordinal allocation (Win32 only). FUNCTYPE should be one of: pascal16 for a Win16 function returning a 16-bit value pascal for a Win16 function returning a 32-bit value register for a function using CPU register to pass arguments interrupt for a Win16 interrupt handler routine stdcall for a normal Win32 function cdecl for a Win32 function using the C calling convention varargs for a Win32 function taking a variable number of arguments ARGTYPE should be one of: word for a 16 bit word long a 32 bit value ptr for a linear pointer str for a linear pointer to a null-terminated string s_word for a 16 bit signed word segptr for a segmented pointer segstr for a segmented pointer to a null-terminated string Only ptr, str and long are valid for Win32 functions. HANDLERNAME is the name of the actual Wine function that will process the request in 32-bit mode. The two examples define an entry point for the CreateWindow and GetFocus calls respectively. The ordinals used are just examples. To declare a function using a variable number of arguments in Win16, specify the function as taking no arguments. The arguments are then available with CURRENT_STACK16->args. In Win32, specify the function as varargs and declare it with a '...' parameter in the C file. See the wsprintf* functions in user.spec and user32.spec for an example. ORDINAL stub EXPORTNAME This field can be present zero or more times. Each instance defines a stub function. It makes the ordinal available for dynamic linking, but will terminate execution with an error message if the function is ever called. ORDINAL extern EXPORTNAME SYMBOLNAME This field can be present zero or more times. Each instance defines an entry that simply maps to a Wine symbol (variable or function); EXPORTNAME will point to the symbol SYMBOLNAME that must be defined in C code. This type only works with Win32. ORDINAL forward EXPORTNAME SYMBOLNAME This field can be present zero or more times. Each instance defines an entry that is forwarded to another entry point (kind of a symbolic link). EXPORTNAME will forward to the entry point SYMBOLNAME that must be of the form DLL.Function. This type only works with Win32. Linking it all together To link an executable you need to link together: your object files, the spec file, any Windows libraries that your application depends on, gdi32 for instance, and any additional library that you use. All the libraries you link with should be available as '.so' libraries. If one of them is available only in '.dll' form then consult . It is also when attempting to link your executable that you will discover whether you have missing symbols or not in your custom libraries. On Windows when you build a library, the linker will immediately tell you if a symbol it is supposed to export is undefined. In Unix, and in Winelib, this is not the case. The symbol will silently be marked as undefined and it is only when you try to produce an executable that the linker will verify all the symbols are accounted for. So before declaring victory when first converting a library to Winelib, you should first try to link it to an executable (but you would have done that to test it anyway, right?). At this point you may discover some undefined symbols that you thought were implemented by the library. Then, you to the library sources and fix it. But you may also discover that the missing symbols are defined in, say, gdi32. This is because you did not link the said library with gdi32. One way to fix it is to link this executable, and any other that also uses your library, with gdi32. But it is better to go back to your library's makefile and explicitly link it with gdi32. As you will quickly notice, this has unfortunately not been (completely) done for Winelib's own libraries. So if an application must link with ole32, you will also need to link with advapi32, rpcrt4 and others even if you don't use them directly. This can be annoying and hopefully will be fixed soon (feel free to submit a patch). Dealing with the MFC Introduction To use the MFC in a Winelib application you will first have to recompile the MFC with Winelib. In theory it should be possible to write a wrapper for the Windows MFC as described in . But in practice it does not seem to be a realistic approach for the MFC: the huge number of APIs makes writing the wrapper a big task in itself. furthermore the MFC contain a huge number of APIs which are tricky to deal with when making a wrapper. even once you have written the wrapper you will need to modify the MFC headers so that the compiler does not choke on them. a big part of the MFC code is actually in your application in the form of macros. This means even more of the MFC headers have to actually work to in order for you to be able to compile an MFC based application. This is why this guide includes a section dedicated to helping you compile the MFC with Winelib. Legal issues (Extracted from the HOWTO-Winelib written by Wilbur Dale <wilbur.dale@lumin.nl>) The purpose of this section is to make you aware of potential legal problems. Be sure to read your licenses and to consult your lawyers. In any case you should not consider the remainder of this section to be authoritative since it has not been written by a lawyer. Well, let's try to have a look at the situation anyway. During the compilation of your program, you will be combining code from several sources: your code, Winelib code, Microsoft MFC code, and possibly code from other vendor sources. As a result, you must ensure that the licenses of all code sources are obeyed. What you are allowed and not allowed to do can vary depending on how you compile your program and if you will be distributing it. For example, if you are releasing your code under the GPL, you cannot link your code to MFC code because the GPL requires that you provide ALL sources to your users. The MFC license forbids you from distributing the MFC source so you cannot both distribute your program and comply with the GPL license. On the other hand, if your code is released under the LGPL, you cannot statically link your program to the MFC and distribute it, but you can dynamically link your LGPL code and the MFC library and distribute it. Wine/Winelib is distributed under an X11-like license. It places few restrictions on the use and distribution of Wine/Winelib code. I doubt the Wine license will cause you any problems. On the other hand, MFC is distributed under a very restrictive license and the restrictions vary from version to version and between service packs. There are basically three aspects you must be aware of when using the MFC. First you must legally get MFC source code on your computer. The MFC source code comes as a part of Visual Studio. The license for Visual Studio implies it is a single product that can not be broken up into its components. So the cleanest way to get MFC on your system is to buy Visual Studio and install it on a dual boot Linux box. Then you must check that you are allowed to recompile MFC on a non-Microsoft operating system! This varies with the version of MFC. The MFC license from Visual Studio 6.0 reads in part:
1.1 General License Grant. Microsoft grants to you as an individual, a personal, nonexclusive license to make and use copies of the SOFTWARE PRODUCT for the sole purposes of designing, developing, and testing your software product(s) that are designed to operate in conjunction with any Microsoft operating system product. [Other unrelated stuff deleted.]
So it appears you cannot even compile MFC for Winelib using this license. Fortunately the Visual Studio 6.0 service pack 3 license reads (the Visual Studio 5.0 license is similar):
1.1 General License Grant. Microsoft grants to you as an individual, a personal, nonexclusive license to make and use copies of the SOFTWARE PRODUCT for the purpose of designing, developing, and testing your software product(s). [Other unrelated stuff deleted]
So under this license it appears you can compile MFC for Winelib. Finally you must check whether you have the right to distribute an MFC library. Check the relevant section of the license on redistributables and your redistribution rights. The license seems to specify that you only have the right to distribute binaries of the MFC library if it has no debug information and if you distribute it with an application that provides significant added functionality to the MFC library.
Compiling the MFC Things to disable, why we have to disable them (lack of Wine support), where things don't compile, why, how to solve it, what to put in the Makefile, maybe try to point to a place with a ready-made makefile... Using the MFC Specific winemaker options, the configure options, the initialization problem...
Dealing with binary only dlls Introduction describe the problem, use an example and reuse it in the following sections... Writing the spec file give an example... How to deal with C++ APIs names are mangled, how to demangle them, how to call them Writing the wrapper give an example Packaging your Winelib application Selecting which libraries to deliver, how to avoid interference with other Winelib applications, how to play nice with other Winelib applications