Replaced the --mode winebuild option by a --subsystem option for

better compatibility with the PE binutils.
This commit is contained in:
Alexandre Julliard 2004-03-25 00:40:52 +00:00
parent 39c961aad6
commit 4cf091ab09
7 changed files with 93 additions and 69 deletions

View File

@ -50,14 +50,6 @@ typedef enum
SPEC_WIN32 SPEC_WIN32
} SPEC_TYPE; } SPEC_TYPE;
typedef enum
{
SPEC_MODE_DLL,
SPEC_MODE_NATIVE,
SPEC_MODE_GUIEXE,
SPEC_MODE_CUIEXE
} SPEC_MODE;
typedef struct typedef struct
{ {
int n_values; int n_values;
@ -99,7 +91,6 @@ typedef struct
char *owner_name; /* name of the 32-bit dll owning this one */ char *owner_name; /* name of the 32-bit dll owning this one */
char *init_func; /* initialization routine */ char *init_func; /* initialization routine */
SPEC_TYPE type; /* type of dll (Win16/Win32) */ SPEC_TYPE type; /* type of dll (Win16/Win32) */
SPEC_MODE mode; /* dll mode (dll/exe/etc.) */
int base; /* ordinal base */ int base; /* ordinal base */
int limit; /* ordinal limit */ int limit; /* ordinal limit */
int stack_size; /* exe stack size */ int stack_size; /* exe stack size */
@ -108,6 +99,10 @@ typedef struct
int alloc_entry_points; /* number of allocated entry points */ int alloc_entry_points; /* number of allocated entry points */
int nb_names; /* number of entry points with names */ int nb_names; /* number of entry points with names */
int nb_resources; /* number of resources */ int nb_resources; /* number of resources */
int characteristics; /* characteristics for the PE header */
int subsystem; /* subsystem id */
int subsystem_major; /* subsystem version major number */
int subsystem_minor; /* subsystem version minor number */
ORDDEF *entry_points; /* dll entry points */ ORDDEF *entry_points; /* dll entry points */
ORDDEF **names; /* array of entry point names (points into entry_points) */ ORDDEF **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */ ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */

View File

@ -26,10 +26,13 @@
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
# include <unistd.h> # include <unistd.h>
#endif #endif
#include "windef.h"
#include "winbase.h"
#include "build.h" #include "build.h"
struct import struct import
@ -443,19 +446,19 @@ static void add_extra_undef_symbols( const DLLSPEC *spec )
} }
/* add symbols that will be contained in the spec file itself */ /* add symbols that will be contained in the spec file itself */
switch (spec->mode) if (!(spec->characteristics & IMAGE_FILE_DLL))
{ {
case SPEC_MODE_DLL: switch (spec->subsystem)
case SPEC_MODE_NATIVE: {
break; case IMAGE_SUBSYSTEM_WINDOWS_GUI:
case SPEC_MODE_GUIEXE: kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec ); kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec ); kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec ); /* fall through */
/* fall through */ case IMAGE_SUBSYSTEM_WINDOWS_CUI:
case SPEC_MODE_CUIEXE: kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec ); break;
break; }
} }
if (nb_delayed) if (nb_delayed)
{ {

View File

@ -29,11 +29,14 @@
#include <stdio.h> #include <stdio.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <stdarg.h>
#include <ctype.h> #include <ctype.h>
#ifdef HAVE_GETOPT_H #ifdef HAVE_GETOPT_H
# include <getopt.h> # include <getopt.h>
#endif #endif
#include "windef.h"
#include "winbase.h"
#include "build.h" #include "build.h"
int UsePIC = 0; int UsePIC = 0;
@ -94,6 +97,28 @@ static void set_dll_file_name( const char *name, DLLSPEC *spec )
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" ); if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
} }
/* set the dll subsystem */
static void set_subsystem( const char *subsystem, DLLSPEC *spec )
{
char *major, *minor, *str = xstrdup( subsystem );
if ((major = strchr( str, ':' ))) *major++ = 0;
if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
if (major)
{
if ((minor = strchr( major, '.' )))
{
*minor++ = 0;
spec->subsystem_minor = atoi( minor );
}
spec->subsystem_major = atoi( major );
}
free( str );
}
/* cleanup on program exit */ /* cleanup on program exit */
static void cleanup(void) static void cleanup(void)
{ {
@ -121,11 +146,11 @@ static const char usage_str[] =
" -K FLAGS Compiler flags (only -KPIC is supported)\n" " -K FLAGS Compiler flags (only -KPIC is supported)\n"
" -l --library=LIB Import the specified library\n" " -l --library=LIB Import the specified library\n"
" -L --library-path=DIR Look for imports libraries in DIR\n" " -L --library-path=DIR Look for imports libraries in DIR\n"
" -m --mode=MODE Set the binary mode (cui|gui|cuiw|guiw|native)\n"
" -M --main-module=MODULE Set the name of the main module for a Win16 dll\n" " -M --main-module=MODULE Set the name of the main module for a Win16 dll\n"
" -N --dll-name=DLLNAME Set the DLL name (default: from input file name)\n" " -N --dll-name=DLLNAME Set the DLL name (default: from input file name)\n"
" -o --output=NAME Set the output file name (default: stdout)\n" " -o --output=NAME Set the output file name (default: stdout)\n"
" -r --res=RSRC.RES Load resources from RSRC.RES\n" " -r --res=RSRC.RES Load resources from RSRC.RES\n"
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n"
" --version Print the version and exit\n" " --version Print the version and exit\n"
" -w --warnings Turn on warnings\n" " -w --warnings Turn on warnings\n"
"\nMode options:\n" "\nMode options:\n"
@ -145,6 +170,7 @@ enum long_options_values
LONG_OPT_DEBUG, LONG_OPT_DEBUG,
LONG_OPT_RELAY16, LONG_OPT_RELAY16,
LONG_OPT_RELAY32, LONG_OPT_RELAY32,
LONG_OPT_SUBSYSTEM,
LONG_OPT_VERSION LONG_OPT_VERSION
}; };
@ -158,8 +184,8 @@ static const struct option long_options[] =
{ "debug", 0, 0, LONG_OPT_DEBUG }, { "debug", 0, 0, LONG_OPT_DEBUG },
{ "relay16", 0, 0, LONG_OPT_RELAY16 }, { "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "relay32", 0, 0, LONG_OPT_RELAY32 }, { "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "subsystem",1, 0, LONG_OPT_SUBSYSTEM },
{ "version", 0, 0, LONG_OPT_VERSION }, { "version", 0, 0, LONG_OPT_VERSION },
{ "spec", 1, 0, LONG_OPT_DLL }, /* for backwards compatibility */
/* aliases for short options */ /* aliases for short options */
{ "source-dir", 1, 0, 'C' }, { "source-dir", 1, 0, 'C' },
{ "delay-lib", 1, 0, 'd' }, { "delay-lib", 1, 0, 'd' },
@ -171,8 +197,6 @@ static const struct option long_options[] =
{ "kill-at", 0, 0, 'k' }, { "kill-at", 0, 0, 'k' },
{ "library", 1, 0, 'l' }, { "library", 1, 0, 'l' },
{ "library-path", 1, 0, 'L' }, { "library-path", 1, 0, 'L' },
{ "mode", 1, 0, 'm' },
{ "exe-mode", 1, 0, 'm' }, /* for backwards compatibility */
{ "main-module", 1, 0, 'M' }, { "main-module", 1, 0, 'M' },
{ "dll-name", 1, 0, 'N' }, { "dll-name", 1, 0, 'N' },
{ "output", 1, 0, 'o' }, { "output", 1, 0, 'o' },
@ -268,12 +292,6 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case 'l': case 'l':
add_import_dll( optarg, 0 ); add_import_dll( optarg, 0 );
break; break;
case 'm':
if (!strcmp( optarg, "gui" )) spec->mode = SPEC_MODE_GUIEXE;
else if (!strcmp( optarg, "cui" )) spec->mode = SPEC_MODE_CUIEXE;
else if (!strcmp( optarg, "native" )) spec->mode = SPEC_MODE_NATIVE;
else usage(1);
break;
case 'o': case 'o':
if (unlink( optarg ) == -1 && errno != ENOENT) if (unlink( optarg ) == -1 && errno != ENOENT)
fatal_error( "Unable to create output file '%s'\n", optarg ); fatal_error( "Unable to create output file '%s'\n", optarg );
@ -306,7 +324,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
spec->file_name = xmalloc( strlen(p) + 5 ); spec->file_name = xmalloc( strlen(p) + 5 );
strcpy( spec->file_name, p ); strcpy( spec->file_name, p );
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" ); if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" );
if (spec->mode == SPEC_MODE_DLL) spec->mode = SPEC_MODE_GUIEXE; if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break; break;
case LONG_OPT_DEBUG: case LONG_OPT_DEBUG:
set_exec_mode( MODE_DEBUG ); set_exec_mode( MODE_DEBUG );
@ -317,6 +335,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_RELAY32: case LONG_OPT_RELAY32:
set_exec_mode( MODE_RELAY32 ); set_exec_mode( MODE_RELAY32 );
break; break;
case LONG_OPT_SUBSYSTEM:
set_subsystem( optarg, spec );
break;
case LONG_OPT_VERSION: case LONG_OPT_VERSION:
printf( "winebuild version " PACKAGE_VERSION "\n" ); printf( "winebuild version " PACKAGE_VERSION "\n" );
exit(0); exit(0);
@ -385,6 +406,7 @@ int main(int argc, char **argv)
switch(exec_mode) switch(exec_mode)
{ {
case MODE_DLL: case MODE_DLL:
spec->characteristics |= IMAGE_FILE_DLL;
load_resources( argv, spec ); load_resources( argv, spec );
if (!parse_input_file( spec )) break; if (!parse_input_file( spec )) break;
switch (spec->type) switch (spec->type)

View File

@ -484,7 +484,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
{ {
int exports_size = 0; int exports_size = 0;
int nr_exports, nr_imports; int nr_exports, nr_imports;
int characteristics, subsystem;
DWORD page_size; DWORD page_size;
const char *init_func = spec->init_func; const char *init_func = spec->init_func;
@ -593,10 +592,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, "extern void _fini();\n" ); fprintf( outfile, "extern void _fini();\n" );
#endif #endif
characteristics = subsystem = 0; if (spec->characteristics & IMAGE_FILE_DLL)
switch(spec->mode)
{ {
case SPEC_MODE_DLL:
if (init_func) if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func ); fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
else else
@ -617,9 +614,10 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
"}\n", "}\n",
DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH ); DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
init_func = "__wine_dll_main"; init_func = "__wine_dll_main";
characteristics = IMAGE_FILE_DLL; }
break; else switch(spec->subsystem)
case SPEC_MODE_NATIVE: {
case IMAGE_SUBSYSTEM_NATIVE:
if (init_func) if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func ); fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func );
else else
@ -640,9 +638,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
"}\n", "}\n",
init_func, init_func ); init_func, init_func );
init_func = "__wine_driver_entry"; init_func = "__wine_driver_entry";
subsystem = IMAGE_SUBSYSTEM_NATIVE;
break; break;
case SPEC_MODE_GUIEXE: case IMAGE_SUBSYSTEM_WINDOWS_GUI:
if (!init_func) init_func = "WinMain"; if (!init_func) init_func = "WinMain";
fprintf( outfile, fprintf( outfile,
"\ntypedef struct {\n" "\ntypedef struct {\n"
@ -684,9 +681,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
" ExitProcess( ret );\n" " ExitProcess( ret );\n"
"}\n\n", init_func, init_func ); "}\n\n", init_func, init_func );
init_func = "__wine_exe_main"; init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break; break;
case SPEC_MODE_CUIEXE: case IMAGE_SUBSYSTEM_WINDOWS_CUI:
if (init_func) if (init_func)
fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func ); fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func );
else else
@ -713,7 +709,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
" ExitProcess( ret );\n" " ExitProcess( ret );\n"
"}\n\n" ); "}\n\n" );
init_func = "__wine_exe_main"; init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break; break;
} }
@ -775,7 +770,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
#endif #endif
fprintf( outfile, " 0, 0, 0, 0,\n" ); fprintf( outfile, " 0, 0, 0, 0,\n" );
fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */ fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
fprintf( outfile, " 0x%04x },\n", characteristics ); /* Characteristics */ fprintf( outfile, " 0x%04x },\n", spec->characteristics ); /* Characteristics */
fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */ fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */
@ -787,12 +782,13 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */ fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */
fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */ fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */
fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */
fprintf( outfile, " 4, 0,\n" ); /* Major/MinorSubsystemVersion */ fprintf( outfile, " %d,\n", spec->subsystem_major ); /* MajorSubsystemVersion */
fprintf( outfile, " %d,\n", spec->subsystem_minor ); /* MinorSubsystemVersion */
fprintf( outfile, " 0,\n" ); /* Win32VersionValue */ fprintf( outfile, " 0,\n" ); /* Win32VersionValue */
fprintf( outfile, " _end,\n" ); /* SizeOfImage */ fprintf( outfile, " _end,\n" ); /* SizeOfImage */
fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */ fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */
fprintf( outfile, " 0,\n" ); /* CheckSum */ fprintf( outfile, " 0,\n" ); /* CheckSum */
fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */ fprintf( outfile, " 0x%04x,\n", spec->subsystem );/* Subsystem */
fprintf( outfile, " 0,\n" ); /* DllCharacteristics */ fprintf( outfile, " 0,\n" ); /* DllCharacteristics */
fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */ fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */
(spec->stack_size ? spec->stack_size : 1024) * 1024, page_size ); (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );

View File

@ -82,6 +82,7 @@ void fatal_error( const char *msg, ... )
fprintf( stderr, "%d:", current_line ); fprintf( stderr, "%d:", current_line );
fputc( ' ', stderr ); fputc( ' ', stderr );
} }
else fprintf( stderr, "winebuild: " );
vfprintf( stderr, msg, valist ); vfprintf( stderr, msg, valist );
va_end( valist ); va_end( valist );
exit(1); exit(1);
@ -241,7 +242,6 @@ DLLSPEC *alloc_dll_spec(void)
spec->owner_name = NULL; spec->owner_name = NULL;
spec->init_func = NULL; spec->init_func = NULL;
spec->type = SPEC_WIN32; spec->type = SPEC_WIN32;
spec->mode = SPEC_MODE_DLL;
spec->base = MAX_ORDINALS; spec->base = MAX_ORDINALS;
spec->limit = 0; spec->limit = 0;
spec->stack_size = 0; spec->stack_size = 0;
@ -250,6 +250,10 @@ DLLSPEC *alloc_dll_spec(void)
spec->alloc_entry_points = 0; spec->alloc_entry_points = 0;
spec->nb_names = 0; spec->nb_names = 0;
spec->nb_resources = 0; spec->nb_resources = 0;
spec->characteristics = 0;
spec->subsystem = 0;
spec->subsystem_major = 4;
spec->subsystem_minor = 0;
spec->entry_points = NULL; spec->entry_points = NULL;
spec->names = NULL; spec->names = NULL;
spec->ordinals = NULL; spec->ordinals = NULL;

View File

@ -19,7 +19,7 @@ option can be specified, as described in the \fBOPTIONS\fR section.
You have to specify exactly one of the following options, depending on You have to specify exactly one of the following options, depending on
what you want winebuild to generate. what you want winebuild to generate.
.TP .TP
.BI \--dll=\ filename .BI \--dll= filename
Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for
details), or from a standard Windows .def file. The resulting C file details), or from a standard Windows .def file. The resulting C file
must be compiled and linked to the other object files to build a must be compiled and linked to the other object files to build a
@ -33,7 +33,7 @@ final dll, to allow
to get the list of all undefined symbols that need to be imported from to get the list of all undefined symbols that need to be imported from
other dlls. other dlls.
.TP .TP
.BI \--exe=\ name .BI \--exe= name
Build a C file for the named executable. This is basically the same as Build a C file for the named executable. This is basically the same as
the --dll mode except that it doesn't require a .spec file as input, the --dll mode except that it doesn't require a .spec file as input,
since an executable doesn't export functions. The resulting C file since an executable doesn't export functions. The resulting C file
@ -42,7 +42,7 @@ working Wine executable, and all the other object files must be listed
as as
.I input files. .I input files.
.TP .TP
.BI \--def=\ file.spec .BI \--def= file.spec
Build a .def file from a spec file. This is used when building dlls Build a .def file from a spec file. This is used when building dlls
with a PE (Win32) compiler. with a PE (Win32) compiler.
.TP .TP
@ -133,23 +133,6 @@ Specify that we are building a 16-bit dll, that will ultimately be
linked together with the 32-bit dll specified in \fImodule\fR. Only linked together with the 32-bit dll specified in \fImodule\fR. Only
meaningful in \fB--dll\fR mode. meaningful in \fB--dll\fR mode.
.TP .TP
.BI \-m,\ --mode= mode
Set the executable or dll mode, which can be one of the following:
.br
.B cui
for a command line executable,
.br
.B gui
for a graphical executable,
.br
.B native
for a native-mode dll.
.br
The entry point of a command line executable is a normal C \fBmain\fR
function. A \fBwmain\fR function can be used instead if you need the
argument array to use Unicode strings. A graphical executable has a
\fBWinMain\fR entry point.
.TP
.BI \-N,\ --dll-name= dllname .BI \-N,\ --dll-name= dllname
Set the internal name of the module. It is only used in Win16 Set the internal name of the module. It is only used in Win16
modules. The default is to use the base name of the spec file (without modules. The default is to use the base name of the spec file (without
@ -172,6 +155,26 @@ and will automatically be handled correctly (though the
.B \-r .B \-r
option will also work for Win32 files). option will also work for Win32 files).
.TP .TP
.BI --subsystem= subsystem[:major[.minor]]
Set the subsystem of the executable, which can be one of the following:
.br
.B console
for a command line executable,
.br
.B windows
for a graphical executable,
.br
.B native
for a native-mode dll.
.br
The entry point of a command line executable is a normal C \fBmain\fR
function. A \fBwmain\fR function can be used instead if you need the
argument array to use Unicode strings. A graphical executable has a
\fBWinMain\fR entry point.
.br
Optionally a major and minor subsystem version can also be specified;
the default subsystem version is 4.0.
.TP
.B \--version .B \--version
Display the program version and exit. Display the program version and exit.
.TP .TP

View File

@ -498,7 +498,8 @@ static void build(struct options* opts)
{ {
strarray_add(spec_args, "--exe"); strarray_add(spec_args, "--exe");
strarray_add(spec_args, output_name); strarray_add(spec_args, output_name);
strarray_add(spec_args, opts->gui_app ? "-mgui" : "-mcui"); strarray_add(spec_args, "--subsystem");
strarray_add(spec_args, opts->gui_app ? "windows" : "console");
} }
for ( j = 0; j < lib_dirs->size; j++ ) for ( j = 0; j < lib_dirs->size; j++ )