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 Compiling resource files: WRC) 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: More details.

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 Compiling resource files: WRC 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.