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_TYPE;
typedef enum
{
SPEC_MODE_DLL,
SPEC_MODE_NATIVE,
SPEC_MODE_GUIEXE,
SPEC_MODE_CUIEXE
} SPEC_MODE;
typedef struct
{
int n_values;
@ -99,7 +91,6 @@ typedef struct
char *owner_name; /* name of the 32-bit dll owning this one */
char *init_func; /* initialization routine */
SPEC_TYPE type; /* type of dll (Win16/Win32) */
SPEC_MODE mode; /* dll mode (dll/exe/etc.) */
int base; /* ordinal base */
int limit; /* ordinal limit */
int stack_size; /* exe stack size */
@ -108,6 +99,10 @@ typedef struct
int alloc_entry_points; /* number of allocated entry points */
int nb_names; /* number of entry points with names */
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 **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */

View file

@ -26,10 +26,13 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "build.h"
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 */
switch (spec->mode)
if (!(spec->characteristics & IMAGE_FILE_DLL))
{
case SPEC_MODE_DLL:
case SPEC_MODE_NATIVE:
break;
case SPEC_MODE_GUIEXE:
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, "GetModuleHandleA", spec );
/* fall through */
case SPEC_MODE_CUIEXE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
break;
switch (spec->subsystem)
{
case IMAGE_SUBSYSTEM_WINDOWS_GUI:
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, "GetModuleHandleA", spec );
/* fall through */
case IMAGE_SUBSYSTEM_WINDOWS_CUI:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
break;
}
}
if (nb_delayed)
{

View file

@ -29,11 +29,14 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#ifdef HAVE_GETOPT_H
# include <getopt.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "build.h"
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" );
}
/* 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 */
static void cleanup(void)
{
@ -121,11 +146,11 @@ static const char usage_str[] =
" -K FLAGS Compiler flags (only -KPIC is supported)\n"
" -l --library=LIB Import the specified library\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"
" -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"
" -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"
" -w --warnings Turn on warnings\n"
"\nMode options:\n"
@ -145,6 +170,7 @@ enum long_options_values
LONG_OPT_DEBUG,
LONG_OPT_RELAY16,
LONG_OPT_RELAY32,
LONG_OPT_SUBSYSTEM,
LONG_OPT_VERSION
};
@ -158,8 +184,8 @@ static const struct option long_options[] =
{ "debug", 0, 0, LONG_OPT_DEBUG },
{ "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "subsystem",1, 0, LONG_OPT_SUBSYSTEM },
{ "version", 0, 0, LONG_OPT_VERSION },
{ "spec", 1, 0, LONG_OPT_DLL }, /* for backwards compatibility */
/* aliases for short options */
{ "source-dir", 1, 0, 'C' },
{ "delay-lib", 1, 0, 'd' },
@ -171,8 +197,6 @@ static const struct option long_options[] =
{ "kill-at", 0, 0, 'k' },
{ "library", 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' },
{ "dll-name", 1, 0, 'N' },
{ "output", 1, 0, 'o' },
@ -268,12 +292,6 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case 'l':
add_import_dll( optarg, 0 );
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':
if (unlink( optarg ) == -1 && errno != ENOENT)
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 );
strcpy( spec->file_name, p );
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;
case LONG_OPT_DEBUG:
set_exec_mode( MODE_DEBUG );
@ -317,6 +335,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_RELAY32:
set_exec_mode( MODE_RELAY32 );
break;
case LONG_OPT_SUBSYSTEM:
set_subsystem( optarg, spec );
break;
case LONG_OPT_VERSION:
printf( "winebuild version " PACKAGE_VERSION "\n" );
exit(0);
@ -385,6 +406,7 @@ int main(int argc, char **argv)
switch(exec_mode)
{
case MODE_DLL:
spec->characteristics |= IMAGE_FILE_DLL;
load_resources( argv, spec );
if (!parse_input_file( spec )) break;
switch (spec->type)

View file

@ -484,7 +484,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
{
int exports_size = 0;
int nr_exports, nr_imports;
int characteristics, subsystem;
DWORD page_size;
const char *init_func = spec->init_func;
@ -593,10 +592,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, "extern void _fini();\n" );
#endif
characteristics = subsystem = 0;
switch(spec->mode)
if (spec->characteristics & IMAGE_FILE_DLL)
{
case SPEC_MODE_DLL:
if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
else
@ -617,9 +614,10 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
"}\n",
DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
init_func = "__wine_dll_main";
characteristics = IMAGE_FILE_DLL;
break;
case SPEC_MODE_NATIVE:
}
else switch(spec->subsystem)
{
case IMAGE_SUBSYSTEM_NATIVE:
if (init_func)
fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func );
else
@ -640,9 +638,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
"}\n",
init_func, init_func );
init_func = "__wine_driver_entry";
subsystem = IMAGE_SUBSYSTEM_NATIVE;
break;
case SPEC_MODE_GUIEXE:
case IMAGE_SUBSYSTEM_WINDOWS_GUI:
if (!init_func) init_func = "WinMain";
fprintf( outfile,
"\ntypedef struct {\n"
@ -684,9 +681,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
" ExitProcess( ret );\n"
"}\n\n", init_func, init_func );
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break;
case SPEC_MODE_CUIEXE:
case IMAGE_SUBSYSTEM_WINDOWS_CUI:
if (init_func)
fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func );
else
@ -713,7 +709,6 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
" ExitProcess( ret );\n"
"}\n\n" );
init_func = "__wine_exe_main";
subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
break;
}
@ -775,7 +770,7 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
#endif
fprintf( outfile, " 0, 0, 0, 0,\n" );
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, " 0, 0,\n" ); /* Major/MinorLinkerVersion */
@ -787,12 +782,13 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */
fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */
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, " _end,\n" ); /* SizeOfImage */
fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */
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, " %d, %ld,\n", /* SizeOfStackReserve/Commit */
(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 );
fputc( ' ', stderr );
}
else fprintf( stderr, "winebuild: " );
vfprintf( stderr, msg, valist );
va_end( valist );
exit(1);
@ -241,7 +242,6 @@ DLLSPEC *alloc_dll_spec(void)
spec->owner_name = NULL;
spec->init_func = NULL;
spec->type = SPEC_WIN32;
spec->mode = SPEC_MODE_DLL;
spec->base = MAX_ORDINALS;
spec->limit = 0;
spec->stack_size = 0;
@ -250,6 +250,10 @@ DLLSPEC *alloc_dll_spec(void)
spec->alloc_entry_points = 0;
spec->nb_names = 0;
spec->nb_resources = 0;
spec->characteristics = 0;
spec->subsystem = 0;
spec->subsystem_major = 4;
spec->subsystem_minor = 0;
spec->entry_points = NULL;
spec->names = 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
what you want winebuild to generate.
.TP
.BI \--dll=\ filename
.BI \--dll= filename
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
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
other dlls.
.TP
.BI \--exe=\ name
.BI \--exe= name
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,
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
.I input files.
.TP
.BI \--def=\ file.spec
.BI \--def= file.spec
Build a .def file from a spec file. This is used when building dlls
with a PE (Win32) compiler.
.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
meaningful in \fB--dll\fR mode.
.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
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
@ -172,6 +155,26 @@ and will automatically be handled correctly (though the
.B \-r
option will also work for Win32 files).
.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
Display the program version and exit.
.TP

View file

@ -498,7 +498,8 @@ static void build(struct options* opts)
{
strarray_add(spec_args, "--exe");
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++ )