Add support for .exe's with exported functions.

This commit is contained in:
Dimitrie O. Paun 2005-03-08 16:55:26 +00:00 committed by Alexandre Julliard
parent 484ef02aab
commit c02dd0a902
9 changed files with 66 additions and 53 deletions

View File

@ -131,10 +131,10 @@ LINTS = $(C_SRCS:.c=.ln)
$(WINDRES) -i $< -o $@ $(WINDRES) -i $< -o $@
.spec.spec.c: .spec.spec.c:
$(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $< $(WINEBUILD) $(DEFS) --dll -o $@ --main-module $(MODULE) --export $<
.spec.spec.def: .spec.spec.def:
$(WINEBUILD) -w $(DEFS) -o $@ --def $< $(WINEBUILD) -w $(DEFS) --def -o $@ --export $<
.idl.h: .idl.h:
$(WIDL) $(IDLFLAGS) -h -H $@ $< $(WIDL) $(IDLFLAGS) -h -H $@ $<

View File

@ -56,7 +56,7 @@ crosstest:: $(SUBDIRS:%=%/__crosstest__)
# Rule to explicitly generate the .spec.c for debugging # Rule to explicitly generate the .spec.c for debugging
$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD) $(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD)
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%) $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --export $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%)
# Rules for auto documentation # Rules for auto documentation

View File

@ -71,7 +71,7 @@ EXTRASUBDIRS = \
# Special rules for 16-bit resource and spec files # Special rules for 16-bit resource and spec files
gdi.exe.spec.c: gdi.exe.spec version16.res gdi.exe.spec.c: gdi.exe.spec version16.res
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/gdi.exe.spec $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --export $(SRCDIR)/gdi.exe.spec
version16.res: version16.rc version16.res: version16.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc

View File

@ -106,7 +106,7 @@ relay16asm.s: $(WINEBUILD)
# Special rules for 16-bit resource and spec files # Special rules for 16-bit resource and spec files
krnl386.exe.spec.c: krnl386.exe.spec version16.res krnl386.exe.spec.c: krnl386.exe.spec version16.res
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/krnl386.exe.spec $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --export $(SRCDIR)/krnl386.exe.spec
version16.res: version16.rc version16.res: version16.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc

View File

@ -77,7 +77,7 @@ version16.res: version16.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
shell.spec.c: shell.spec version16.res shell.spec.c: shell.spec version16.res
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/shell.spec $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --main-module $(MODULE) --res version16.res --export $(SRCDIR)/shell.spec
authors.c: $(TOPSRCDIR)/AUTHORS authors.c: $(TOPSRCDIR)/AUTHORS
(LC_ALL=C; export LC_ALL; echo 'const char * const SHELL_Authors[] = {' && \ (LC_ALL=C; export LC_ALL; echo 'const char * const SHELL_Authors[] = {' && \

View File

@ -161,13 +161,13 @@ EXTRASUBDIRS = \
# Special rules for 16-bit resource and spec files # Special rules for 16-bit resource and spec files
user.exe.spec.c: user.exe.spec resources/version16.res user.exe.spec.c: user.exe.spec resources/version16.res
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res resources/version16.res --dll $(SRCDIR)/user.exe.spec $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --heap 65520 --main-module $(MODULE) --res resources/version16.res --export $(SRCDIR)/user.exe.spec
display.drv.spec.c: display.drv.spec resources/display.res display.drv.spec.c: display.drv.spec resources/display.res
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/display.res --dll $(SRCDIR)/display.drv.spec $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --main-module $(MODULE) --res resources/display.res --export $(SRCDIR)/display.drv.spec
mouse.drv.spec.c: mouse.drv.spec resources/mouse.res mouse.drv.spec.c: mouse.drv.spec resources/mouse.res
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/mouse.res --dll $(SRCDIR)/mouse.drv.spec $(WINEBUILD) $(DEFS) $(DLLFLAGS) --dll -o $@ --main-module $(MODULE) --res resources/mouse.res --export $(SRCDIR)/mouse.drv.spec
resources/display.res: resources/display.rc resources/display.res: resources/display.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/resources/display.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/resources/display.rc

View File

@ -98,7 +98,6 @@ static void set_dll_file_name( const char *name, DLLSPEC *spec )
{ {
if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0; if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0;
} }
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
} }
/* set the dll subsystem */ /* set the dll subsystem */
@ -144,6 +143,7 @@ static const char usage_str[] =
" -C --source-dir=DIR Look for source files in DIR\n" " -C --source-dir=DIR Look for source files in DIR\n"
" -d --delay-lib=LIB Import the specified library in delayed mode\n" " -d --delay-lib=LIB Import the specified library in delayed mode\n"
" -D SYM Ignored for C flags compatibility\n" " -D SYM Ignored for C flags compatibility\n"
" -E --export=FILE Export the symbols defined in the .spec or .def file\n"
" -e --entry=FUNC Set the DLL entry point function (default: DllMain)\n" " -e --entry=FUNC Set the DLL entry point function (default: DllMain)\n"
" -f FLAGS Compiler flags (only -fPIC is supported)\n" " -f FLAGS Compiler flags (only -fPIC is supported)\n"
" -F --filename=DLLFILE Set the DLL filename (default: from input file name)\n" " -F --filename=DLLFILE Set the DLL filename (default: from input file name)\n"
@ -165,9 +165,9 @@ static const char usage_str[] =
" --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"
" --dll=FILE Build a .c file from a .spec or .def file\n" " --dll Build a .c file from a .spec or .def file\n"
" --def=FILE.SPEC Build a .def file from a spec file\n" " --def Build a .def file from a .spec file\n"
" --exe=NAME Build a .c file for the named executable\n" " --exe Build a .c file for an executable\n"
" --debug [FILES] Build a .c file with the debug channels declarations\n" " --debug [FILES] Build a .c file with the debug channels declarations\n"
" --relay16 Build the 16-bit relay assembly routines\n" " --relay16 Build the 16-bit relay assembly routines\n"
" --relay32 Build the 32-bit relay assembly routines\n\n" " --relay32 Build the 32-bit relay assembly routines\n\n"
@ -187,13 +187,13 @@ enum long_options_values
LONG_OPT_VERSION LONG_OPT_VERSION
}; };
static const char short_options[] = "C:D:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w"; static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w";
static const struct option long_options[] = static const struct option long_options[] =
{ {
{ "dll", 1, 0, LONG_OPT_DLL }, { "dll", 0, 0, LONG_OPT_DLL },
{ "def", 1, 0, LONG_OPT_DEF }, { "def", 0, 0, LONG_OPT_DEF },
{ "exe", 1, 0, LONG_OPT_EXE }, { "exe", 0, 0, LONG_OPT_EXE },
{ "debug", 0, 0, LONG_OPT_DEBUG }, { "debug", 0, 0, LONG_OPT_DEBUG },
{ "ld-cmd", 1, 0, LONG_OPT_LDCMD }, { "ld-cmd", 1, 0, LONG_OPT_LDCMD },
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD }, { "nm-cmd", 1, 0, LONG_OPT_NMCMD },
@ -204,6 +204,7 @@ static const struct option long_options[] =
/* 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' },
{ "export", 1, 0, 'E' },
{ "entry", 1, 0, 'e' }, { "entry", 1, 0, 'e' },
{ "filename", 1, 0, 'F' }, { "filename", 1, 0, 'F' },
{ "help", 0, 0, 'h' }, { "help", 0, 0, 'h' },
@ -248,6 +249,10 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case 'D': case 'D':
/* ignored */ /* ignored */
break; break;
case 'E':
spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec );
break;
case 'F': case 'F':
spec->file_name = xstrdup( optarg ); spec->file_name = xstrdup( optarg );
break; break;
@ -324,21 +329,12 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
break; break;
case LONG_OPT_DLL: case LONG_OPT_DLL:
set_exec_mode( MODE_DLL ); set_exec_mode( MODE_DLL );
spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec );
break; break;
case LONG_OPT_DEF: case LONG_OPT_DEF:
set_exec_mode( MODE_DEF ); set_exec_mode( MODE_DEF );
spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec );
break; break;
case LONG_OPT_EXE: case LONG_OPT_EXE:
set_exec_mode( MODE_EXE ); set_exec_mode( MODE_EXE );
if ((p = strrchr( optarg, '/' ))) p++;
else p = optarg;
spec->file_name = xmalloc( strlen(p) + 5 );
strcpy( spec->file_name, p );
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" );
if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
break; break;
case LONG_OPT_DEBUG: case LONG_OPT_DEBUG:
@ -367,6 +363,10 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
break; break;
} }
} }
if (spec->file_name && !strchr( spec->file_name, '.' ))
strcat( spec->file_name, exec_mode == MODE_EXE ? ".exe" : ".dll" );
return &argv[optind]; return &argv[optind];
} }
@ -405,12 +405,14 @@ static int parse_input_file( DLLSPEC *spec )
{ {
FILE *input_file = open_input_file( NULL, spec_file_name ); FILE *input_file = open_input_file( NULL, spec_file_name );
char *extension = strrchr( spec_file_name, '.' ); char *extension = strrchr( spec_file_name, '.' );
int result;
if (extension && !strcmp( extension, ".def" )) if (extension && !strcmp( extension, ".def" ))
return parse_def_file( input_file, spec ); result = parse_def_file( input_file, spec );
else else
return parse_spec_file( input_file, spec ); result = parse_spec_file( input_file, spec );
close_input_file( input_file ); close_input_file( input_file );
return result;
} }
@ -435,6 +437,7 @@ int main(int argc, char **argv)
case MODE_DLL: case MODE_DLL:
spec->characteristics |= IMAGE_FILE_DLL; spec->characteristics |= IMAGE_FILE_DLL;
load_resources( argv, spec ); load_resources( argv, spec );
if (!spec_file_name) fatal_error( "missing .spec file\n" );
if (!parse_input_file( spec )) break; if (!parse_input_file( spec )) break;
switch (spec->type) switch (spec->type)
{ {
@ -452,13 +455,16 @@ int main(int argc, char **argv)
break; break;
case MODE_EXE: case MODE_EXE:
if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
if (!spec->file_name) fatal_error( "executable must be named via the -F option\n" );
load_resources( argv, spec ); load_resources( argv, spec );
if (spec_file_name && !parse_input_file( spec )) break;
read_undef_symbols( argv ); read_undef_symbols( argv );
BuildSpec32File( output_file, spec ); BuildSpec32File( output_file, spec );
break; break;
case MODE_DEF: case MODE_DEF:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!spec_file_name) fatal_error( "missing .spec file\n" );
if (!parse_input_file( spec )) break; if (!parse_input_file( spec )) break;
BuildDef32File( output_file, spec ); BuildDef32File( output_file, spec );
break; break;

View File

@ -19,13 +19,12 @@ 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
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 .spec/.def file
must be compiled and linked to the other object files to build a is specified via the -E option. The resulting C file must be compiled
working Wine dll. and linked to the other object files to build a working Wine dll.
.br In this mode, the
In that mode, the
.I input files .I input files
should be the list of all object files that will be linked into the should be the list of all object files that will be linked into the
final dll, to allow final dll, to allow
@ -33,18 +32,20 @@ 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
Build a C file for the named executable. This is basically the same as Build a C file for an 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/.def file as input,
since an executable doesn't export functions. The resulting C file since an executable need not export functions. Some executables however
must be compiled and linked to the other object files to build a do export functions, and for those a .spec/.def file can be specified via
working Wine executable, and all the other object files must be listed the -E option. The executable is named from the .spec/.def file name if
as present, or explicitly through the -F option. The resulting C file must be
compiled and linked to the other object files to build a working Wine
executable, and all the other object files must be listed as
.I input files. .I input files.
.TP .TP
.BI \--def= file.spec .BI \--def
Build a .def file from a spec file. This is used when building dlls Build a .def file from a spec file. The .spec file is specified via the
with a PE (Win32) compiler. -E option. This is used when building dlls with a PE (Win32) compiler.
.TP .TP
.B \--debug .B \--debug
Build a C file containing the definitions for debugging channels. In Build a C file containing the definitions for debugging channels. In
@ -83,6 +84,11 @@ is not defined, the standard C
.B main .B main
is used instead). This is only valid for Win32 modules. is used instead). This is only valid for Win32 modules.
.TP .TP
.BI \-E,\ --export= filename
Specify a .spec file (see \fBSPEC FILE SYNTAX\fR for details),
or a standard Windows .def file that defines the exports
of the DLL or executable that is being built.
.TP
.BI \-f\ flags .BI \-f\ flags
Ignored for compatibility with the C compiler. Ignored for compatibility with the C compiler.
.TP .TP
@ -431,4 +437,5 @@ development headquarters, at
.UE .UE
.SH "SEE ALSO" .SH "SEE ALSO"
.BR wine (1), .BR wine (1),
.BR winegcc (1),
.BR wrc (1). .BR wrc (1).

View File

@ -339,7 +339,7 @@ static const char* compile_to_object(struct options* opts, const char* file, con
struct options copts; struct options copts;
char* base_name; char* base_name;
/* make a copy we so don't change any of the initial stuff */ /* make a copy so we don't change any of the initial stuff */
/* a shallow copy is exactly what we want in this case */ /* a shallow copy is exactly what we want in this case */
base_name = get_basename(file); base_name = get_basename(file);
copts = *opts; copts = *opts;
@ -429,10 +429,8 @@ static void build(struct options* opts)
{ {
case file_def: case file_def:
case file_spec: case file_spec:
if (!opts->shared)
error("Spec file %s not supported in non-shared mode", file);
if (spec_file) if (spec_file)
error("Only one spec file can be specified in shared mode"); error("Only one spec file can be specified.");
spec_file = file; spec_file = file;
break; break;
case file_rc: case file_rc:
@ -513,17 +511,19 @@ static void build(struct options* opts)
strarray_add(spec_args, "--ld-cmd"); strarray_add(spec_args, "--ld-cmd");
strarray_add(spec_args, LD); strarray_add(spec_args, LD);
strarray_addall(spec_args, strarray_fromstring(DLLFLAGS, " ")); strarray_addall(spec_args, strarray_fromstring(DLLFLAGS, " "));
strarray_add(spec_args, opts->shared ? "--dll" : "--exe");
strarray_add(spec_args, "-o"); strarray_add(spec_args, "-o");
strarray_add(spec_args, spec_c_name); strarray_add(spec_args, spec_c_name);
if (opts->shared) if (spec_file)
{ {
strarray_add(spec_args, "--dll"); strarray_add(spec_args, "-E");
strarray_add(spec_args, spec_file); strarray_add(spec_args, spec_file);
} }
else
if (!opts->shared)
{ {
strarray_add(spec_args, "--exe"); strarray_add(spec_args, "-F");
strarray_add(spec_args, output_name); strarray_add(spec_args, strmake("%s.exe", output_name));
strarray_add(spec_args, "--subsystem"); strarray_add(spec_args, "--subsystem");
strarray_add(spec_args, opts->gui_app ? "windows" : "console"); strarray_add(spec_args, opts->gui_app ? "windows" : "console");
} }