Commit 5173234e authored by Alexandre Julliard's avatar Alexandre Julliard

Now that we have to be able to run the assembler from winebuild, added

an option to generate a .spec.o file in a single step. Added --save-temps and --verbose options for easier debugging.
parent 7d7da60d
......@@ -177,6 +177,7 @@ extern void close_input_file( FILE *file );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
const char *label, int constant );
extern int remove_stdcall_decoration( char *name );
extern void assemble_file( const char *src_file, const char *obj_file );
extern DLLSPEC *alloc_dll_spec(void);
extern void free_dll_spec( DLLSPEC *spec );
extern int has_stubs( const DLLSPEC *spec );
......@@ -233,6 +234,8 @@ extern int nb_lib_paths;
extern int nb_errors;
extern int display_warnings;
extern int kill_at;
extern int verbose;
extern int save_temps;
extern char *input_file_name;
extern char *spec_file_name;
......
......@@ -505,12 +505,9 @@ static void check_undefined_exports( DLLSPEC *spec )
/* create a .o file that references all the undefined symbols we want to resolve */
static char *create_undef_symbols_file( DLLSPEC *spec )
{
char *cmd, *as_file, *obj_file;
char *as_file, *obj_file;
unsigned int i;
FILE *f;
int err;
if (!as_command) as_command = xstrdup("as");
as_file = get_temp_file_name( output_file_name, ".s" );
if (!(f = fopen( as_file, "w" ))) fatal_error( "Cannot create %s\n", as_file );
......@@ -528,11 +525,7 @@ static char *create_undef_symbols_file( DLLSPEC *spec )
fclose( f );
obj_file = get_temp_file_name( output_file_name, ".o" );
cmd = xmalloc( strlen(as_command) + strlen(obj_file) + strlen(as_file) + 6 );
sprintf( cmd, "%s -o %s %s", as_command, obj_file, as_file );
err = system( cmd );
if (err) fatal_error( "%s failed with status %d\n", as_command, err );
free( cmd );
assemble_file( as_file, obj_file );
return obj_file;
}
......@@ -553,6 +546,7 @@ static const char *ldcombine_files( DLLSPEC *spec, char **argv )
p += sprintf( cmd, "%s -r -o %s %s", ld_command, ld_tmp_file, undef_file );
for (i = 0; argv[i]; i++)
p += sprintf( p, " %s", argv[i] );
if (verbose) fprintf( stderr, "%s\n", cmd );
err = system( cmd );
if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
free( cmd );
......
......@@ -46,6 +46,8 @@ int nb_lib_paths = 0;
int nb_errors = 0;
int display_warnings = 0;
int kill_at = 0;
int verbose = 0;
int save_temps = 0;
#ifdef __i386__
enum target_cpu target_cpu = CPU_x86;
......@@ -77,6 +79,7 @@ char **lib_path = NULL;
char *input_file_name = NULL;
char *spec_file_name = NULL;
const char *output_file_name = NULL;
static const char *output_file_source_name;
char *as_command = NULL;
char *ld_command = NULL;
......@@ -266,9 +269,11 @@ static const char usage_str[] =
" -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"
" --save-temps Do not delete the generated intermediate files\n"
" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n"
" --target=TARGET Specify target CPU and platform for cross-compiling\n"
" -u, --undefined=SYMBOL Add an undefined reference to SYMBOL when linking\n"
" -v, --verbose Display the programs invoked\n"
" --version Print the version and exit\n"
" -w, --warnings Turn on warnings\n"
"\nMode options:\n"
......@@ -291,12 +296,13 @@ enum long_options_values
LONG_OPT_NMCMD,
LONG_OPT_RELAY16,
LONG_OPT_RELAY32,
LONG_OPT_SAVE_TEMPS,
LONG_OPT_SUBSYSTEM,
LONG_OPT_TARGET,
LONG_OPT_VERSION
};
static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:u:w";
static const char short_options[] = "C:D:E:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:u:vw";
static const struct option long_options[] =
{
......@@ -309,6 +315,7 @@ static const struct option long_options[] =
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD },
{ "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "save-temps",0, 0, LONG_OPT_SAVE_TEMPS },
{ "subsystem",1, 0, LONG_OPT_SUBSYSTEM },
{ "target", 1, 0, LONG_OPT_TARGET },
{ "version", 0, 0, LONG_OPT_VERSION },
......@@ -329,6 +336,7 @@ static const struct option long_options[] =
{ "output", 1, 0, 'o' },
{ "res", 1, 0, 'r' },
{ "undefined", 1, 0, 'u' },
{ "verbose", 0, 0, 'v' },
{ "warnings", 0, 0, 'w' },
{ NULL, 0, 0, 0 }
};
......@@ -424,12 +432,25 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
add_import_dll( optarg, NULL );
break;
case 'o':
if (unlink( optarg ) == -1 && errno != ENOENT)
fatal_error( "Unable to create output file '%s'\n", optarg );
if (!(output_file = fopen( optarg, "w" )))
fatal_error( "Unable to create output file '%s'\n", optarg );
output_file_name = xstrdup(optarg);
atexit( cleanup ); /* make sure we remove the output file on exit */
{
char *ext = strrchr( optarg, '.' );
if (unlink( optarg ) == -1 && errno != ENOENT)
fatal_error( "Unable to create output file '%s'\n", optarg );
if (ext && !strcmp( ext, ".o" ))
{
output_file_source_name = get_temp_file_name( optarg, ".s" );
if (!(output_file = fopen( output_file_source_name, "w" )))
fatal_error( "Unable to create output file '%s'\n", optarg );
}
else
{
if (!(output_file = fopen( optarg, "w" )))
fatal_error( "Unable to create output file '%s'\n", optarg );
}
output_file_name = xstrdup(optarg);
atexit( cleanup ); /* make sure we remove the output file on exit */
}
break;
case 'r':
res_files = xrealloc( res_files, (nb_res_files+1) * sizeof(*res_files) );
......@@ -438,6 +459,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case 'u':
add_extra_ld_symbol( optarg );
break;
case 'v':
verbose++;
break;
case 'w':
display_warnings = 1;
break;
......@@ -469,6 +493,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_RELAY32:
set_exec_mode( MODE_RELAY32 );
break;
case LONG_OPT_SAVE_TEMPS:
save_temps = 1;
break;
case LONG_OPT_SUBSYSTEM:
set_subsystem( optarg, spec );
break;
......@@ -624,6 +651,7 @@ int main(int argc, char **argv)
if (output_file_name)
{
fclose( output_file );
if (output_file_source_name) assemble_file( output_file_source_name, output_file_name );
output_file_name = NULL;
}
return 0;
......
......@@ -166,22 +166,27 @@ void warning( const char *msg, ... )
char *get_temp_file_name( const char *prefix, const char *suffix )
{
char *name;
const char *ext;
int fd;
assert( nb_tmp_files < MAX_TMP_FILES );
if (!nb_tmp_files) atexit( cleanup_tmp_files );
if (!nb_tmp_files && !save_temps) atexit( cleanup_tmp_files );
if (!prefix || !prefix[0]) prefix = "winebuild.tmp";
if (!prefix || !prefix[0]) prefix = "winebuild";
if (!suffix) suffix = "";
name = xmalloc( strlen(prefix) + strlen(suffix) + sizeof("/tmp/.XXXXXX") );
sprintf( name, "%s.XXXXXX%s", prefix, suffix );
if (!(ext = strchr( prefix, '.' ))) ext = prefix + strlen(prefix);
name = xmalloc( sizeof("/tmp/") + (ext - prefix) + sizeof(".XXXXXX") + strlen(suffix) );
strcpy( name, "/tmp/" );
memcpy( name + 5, prefix, ext - prefix );
strcpy( name + 5 + (ext - prefix), ".XXXXXX" );
strcat( name, suffix );
/* first try without the /tmp/ prefix */
if ((fd = mkstemps( name + 5, strlen(suffix) )) != -1)
name += 5;
else if ((fd = mkstemps( name, strlen(suffix) )) == -1)
fatal_error( "could not generate a temp file\n" );
if ((fd = mkstemps( name, strlen(suffix) ) == -1))
{
sprintf( name, "/tmp/%s.XXXXXX%s", prefix, suffix );
if ((fd = mkstemps( name, strlen(suffix) ) == -1))
fatal_error( "could not generate a temp file\n" );
}
close( fd );
tmp_files[nb_tmp_files++] = name;
return name;
......@@ -276,6 +281,26 @@ int remove_stdcall_decoration( char *name )
/*******************************************************************
* assemble_file
*
* Run a file through the assembler.
*/
void assemble_file( const char *src_file, const char *obj_file )
{
char *cmd;
int err;
if (!as_command) as_command = xstrdup("as");
cmd = xmalloc( strlen(as_command) + strlen(obj_file) + strlen(src_file) + 6 );
sprintf( cmd, "%s -o %s %s", as_command, obj_file, src_file );
if (verbose) fprintf( stderr, "%s\n", cmd );
err = system( cmd );
if (err) fatal_error( "%s failed with status %d\n", as_command, err );
free( cmd );
}
/*******************************************************************
* alloc_dll_spec
*
* Create a new dll spec file descriptor
......
.\" -*- nroff -*-
.TH WINEBUILD 1 "March 2003" "@PACKAGE_STRING@" "Wine dll builder"
.TH WINEBUILD 1 "September 2005" "@PACKAGE_STRING@" "Wine dll builder"
.SH NAME
winebuild \- Wine dll builder
.SH SYNOPSIS
......@@ -20,11 +20,11 @@ You have to specify exactly one of the following options, depending on
what you want winebuild to generate.
.TP
.BI \--dll
Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for
details), or from a standard Windows .def file. The .spec/.def file
is specified via the -E option. The resulting C file must be compiled
and linked to the other object files to build a working Wine dll.
In this mode, the
Build an assembly file from a .spec file (see \fBSPEC FILE SYNTAX\fR
for details), or from a standard Windows .def file. The
.spec/.def file is specified via the -E option. The resulting file
must be assembled and linked to the other object files to build a
working Wine dll. In this mode, the
.I input files
should be the list of all object files that will be linked into the
final dll, to allow
......@@ -33,13 +33,13 @@ to get the list of all undefined symbols that need to be imported from
other dlls.
.TP
.BI \--exe
Build a C file for an executable. This is basically the same as
Build an assembly file for an executable. This is basically the same as
the --dll mode except that it doesn't require a .spec/.def file as input,
since an executable need not export functions. Some executables however
do export functions, and for those a .spec/.def file can be specified via
the -E option. The executable is named from the .spec/.def file name if
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
present, or explicitly through the -F option. The resulting file must be
assembled 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.
.TP
......@@ -160,11 +160,14 @@ Specify the command to use to get the list of undefined symbols; the
default is \fBnm\fR.
.TP
.BI \-o,\ --output= file
Set the name of the output file (default is standard output).
Set the name of the output file (default is standard output). If the
output file name end in \fB.o\fR, the text output is sent to a
temporary file that is then assembled to produce the specified .o
file.
.TP
.BI \-r,\ --res= rsrc.res
Load resources from the specified binary resource file. The
\fIrsrc.res\fR can be produced from a source resource file with
\fIrsrc.res\fR file can be produced from a source resource file with
.BR wrc(1)
(or with a Windows resource compiler).
.br
......@@ -175,6 +178,9 @@ and will automatically be handled correctly (though the
.B \-r
option will also work for Win32 files).
.TP
.B --save-temps
Do not delete the various temporary files that \fBwinebuild\fR generates.
.TP
.BI --subsystem= subsystem[:major[.minor]]
Set the subsystem of the executable, which can be one of the following:
.br
......@@ -205,6 +211,10 @@ Add \fIsymbol\fR to the list of undefined symbols when invoking the
linker. This makes it possible to force a specific module of a static
library to be included when resolving imports.
.TP
.B \-v, --verbose
Display the various subcommands being invoked by
.B winebuild.
.TP
.B \--version
Display the program version and exit.
.TP
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment