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:
init WinMain rsrc resource.res
And here are the entries you will probably want to change:
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.
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.
Note: FIXME: You must now export functions from DLLs.
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.
Note: FIXME: This section is very outdated and does not correctly describe the current use of winebuild and spec files. In particular, with recent versions of winebuild most of the information that used to be in the spec files is now specified on the command line.
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.
Here is a more detailed description of the spec file's format.
# comment text
Anything after a '#' will be ignored as comments.
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.
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 preceded 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 preceded 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:
for a Win16 function returning a 16-bit value
for a Win16 function returning a 32-bit value
for a function using CPU register to pass arguments
for a Win16 interrupt handler routine
for a normal Win32 function
for a Win32 function using the C calling convention
for a Win32 function taking a variable number of arguments
ARGTYPE should be one of:
for a 16 bit word
a 32 bit value
for a linear pointer
for a linear pointer to a null-terminated string
for a 16 bit signed word
for a segmented pointer
for a segmented pointer to a null-terminated string
for a linear pointer to a null-terminated wide (16-bit Unicode) string
Only ptr, str, wstr 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.
Strings should almost always map to str, wide strings - wstr. As the general rule it depends on whether the parameter is IN, OUT or IN/OUT.
IN: str/wstr
OUT: ptr
IN/OUT: str/wstr
It is for debug messages. If the parameter is OUT it might not be initialized and thus it should not be printed as a string.
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.