winegcc: Add support for building PE executables using Mingw.

This commit is contained in:
Alexandre Julliard 2009-05-30 15:24:07 +02:00
parent bcc1379bda
commit 6f74b45a81
7 changed files with 163 additions and 58 deletions

View file

@ -35,8 +35,8 @@ $(MODULE).so: $(MAINSPEC) $(ALL_OBJS) Makefile.in
# Rules for .dll files
$(MODULE): $(RCOBJS) $(OBJS) $(SPEC_DEF) Makefile.in
$(DLLWRAP) -k --def $(SPEC_DEF) -o $@ $(RCOBJS) $(OBJS) $(DLL_LDPATH) $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(LIBWINE) $(ALL_LIBS)
$(MODULE): $(MAINSPEC) $(RCOBJS) $(OBJS) Makefile.in
$(WINEGCC) -shared $(SRCDIR)/$(MAINSPEC) $(OBJS) $(RCOBJS) $(EXTRADLLFLAGS) -o $@ $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(ALL_LIBS)
# Rules for import libraries

View file

@ -38,7 +38,7 @@ $(MODULE).so: $(OBJS) $(RC_SRCS:.rc=.res) Makefile.in
# Rules for .exe main module
$(MODULE): $(OBJS) $(RCOBJS) Makefile.in
$(CC) $(APPMODE) $(OBJS) $(RCOBJS) -o $@ -L$(DLLDIR) $(IMPORTS:%=-L$(DLLDIR)/%) $(ALL_LIBS)
$(WINEGCC) $(APPMODE) $(OBJS) $(RCOBJS) -o $@ $(LIBPORT) $(ALL_LIBS)
# Rules for building test list

View file

@ -11,7 +11,7 @@
DLLFLAGS = @DLLFLAGS@
DEFS = $(EXTRADEFS)
ALL_LIBS = $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(EXTRALIBS) $(LIBPORT) $(LDFLAGS) $(LIBS)
ALL_LIBS = $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(EXTRALIBS) -lwine $(LIBPORT) $(LDFLAGS) $(LIBS)
RUNTESTFLAGS= -q -P wine -T $(TOPOBJDIR)
INSTALLDIRS = $(DESTDIR)$(bindir) $(DESTDIR)$(dlldir) $(DESTDIR)$(mandir)/man$(prog_manext)
@ -27,7 +27,7 @@ $(MODULE).so: $(OBJS) $(RC_SRCS:.rc=.res) Makefile.in
# Rules for .exe main module
$(MODULE): $(OBJS) $(RCOBJS) Makefile.in
$(CC) $(APPMODE) $(OBJS) $(RCOBJS) -o $@ -L$(DLLDIR) $(IMPORTS:%=-L$(DLLDIR)/%) $(DELAYIMPORTS:%=-L$(DLLDIR)/%) $(LIBWINE) $(ALL_LIBS)
$(WINEGCC) $(APPMODE) $(OBJS) $(RCOBJS) -o $@ $(ALL_LIBS) $(DELAYIMPORTS:%=-Wb,-d%)
# Rules for testing

View file

@ -50,7 +50,7 @@ winetest-dist.exe.so: $(OBJS) dist.res Makefile.in
$(WINEGCC) $(APPMODE) $(OBJS) dist.res -o $@ -L$(DLLDIR) $(DELAYIMPORTS:%=-Wb,-d%) $(ALL_LIBS)
winetest-dist.exe: $(OBJS) dist.res.o Makefile.in
$(CC) $(APPMODE) $(OBJS) dist.res.o -o $@ -L$(DLLDIR) $(IMPORTS:%=-L$(DLLDIR)/%) $(ALL_LIBS)
$(WINEGCC) $(APPMODE) $(OBJS) dist.res.o -o $@ -L$(DLLDIR) $(DELAYIMPORTS:%=-Wb,-d%) $(ALL_LIBS)
-upx -9 -qqq $@
dist.res: winetest.rc tests.rc build.nfo winetest.ico $(TESTBINS)

View file

@ -258,36 +258,38 @@ static char* try_lib_path(const char* dir, const char* pre,
return 0;
}
static file_type guess_lib_type(const char* dir, const char* library, char** file)
static file_type guess_lib_type(enum target_platform platform, const char* dir,
const char* library, char** file)
{
/* Unix shared object */
if ((*file = try_lib_path(dir, "lib", library, ".so", file_so)))
return file_so;
/* Mach-O (Darwin/Mac OS X) Dynamic Library behaves mostly like .so */
if ((*file = try_lib_path(dir, "lib", library, ".dylib", file_so)))
return file_so;
if (platform != PLATFORM_WINDOWS)
{
/* Unix shared object */
if ((*file = try_lib_path(dir, "lib", library, ".so", file_so)))
return file_so;
/* Windows DLL */
if ((*file = try_lib_path(dir, "lib", library, ".def", file_def)))
return file_dll;
if ((*file = try_lib_path(dir, "", library, ".def", file_def)))
return file_dll;
/* Mach-O (Darwin/Mac OS X) Dynamic Library behaves mostly like .so */
if ((*file = try_lib_path(dir, "lib", library, ".dylib", file_so)))
return file_so;
/* Unix static archives */
/* Windows DLL */
if ((*file = try_lib_path(dir, "lib", library, ".def", file_def)))
return file_dll;
}
/* static archives */
if ((*file = try_lib_path(dir, "lib", library, ".a", file_arh)))
return file_arh;
return file_na;
}
file_type get_lib_type(strarray* path, const char* library, char** file)
file_type get_lib_type(enum target_platform platform, strarray* path, const char* library, char** file)
{
unsigned int i;
for (i = 0; i < path->size; i++)
{
file_type type = guess_lib_type(path->base[i], library, file);
file_type type = guess_lib_type(platform, path->base[i], library, file);
if (type != file_na) return type;
}
return file_na;

View file

@ -31,6 +31,16 @@
# endif
#endif
enum target_cpu
{
CPU_x86, CPU_x86_64, CPU_SPARC, CPU_ALPHA, CPU_POWERPC
};
enum target_platform
{
PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_SOLARIS, PLATFORM_WINDOWS
};
void error(const char* s, ...) DECLSPEC_NORETURN;
void* xmalloc(size_t size);
@ -62,7 +72,7 @@ typedef enum {
char* get_basename(const char* file);
void create_file(const char* name, int mode, const char* fmt, ...);
file_type get_file_type(const char* filename);
file_type get_lib_type(strarray* path, const char* library, char** file);
file_type get_lib_type(enum target_platform platform, strarray* path, const char* library, char** file);
void spawn(const strarray* prefix, const strarray* arr, int ignore_errors);
extern int verbose;

View file

@ -145,16 +145,6 @@ static sigset_t signal_mask;
enum processor { proc_cc, proc_cxx, proc_cpp, proc_as };
enum target_cpu
{
CPU_x86, CPU_x86_64, CPU_SPARC, CPU_ALPHA, CPU_POWERPC
};
enum target_platform
{
PLATFORM_UNSPECIFIED, PLATFORM_APPLE, PLATFORM_SOLARIS, PLATFORM_WINDOWS
};
static const struct
{
const char *name;
@ -474,6 +464,24 @@ static const char* compile_to_object(struct options* opts, const char* file, con
return copts.output_name;
}
/* return the initial set of options needed to run winebuild */
static strarray *get_winebuild_args(struct options *opts)
{
const char* winebuild = getenv("WINEBUILD");
strarray *spec_args = strarray_alloc();
if (!winebuild) winebuild = "winebuild";
strarray_add( spec_args, winebuild );
if (verbose) strarray_add( spec_args, "-v" );
if (keep_generated) strarray_add( spec_args, "--save-temps" );
if (opts->target)
{
strarray_add( spec_args, "--target" );
strarray_add( spec_args, opts->target );
}
return spec_args;
}
/* check if there is a static lib associated to a given dll */
static char *find_static_lib( const char *dll )
{
@ -484,11 +492,11 @@ static char *find_static_lib( const char *dll )
}
/* add specified library to the list of files */
static void add_library( strarray *lib_dirs, strarray *files, const char *library )
static void add_library( struct options *opts, strarray *lib_dirs, strarray *files, const char *library )
{
char *static_lib, *fullname = 0;
switch(get_lib_type(lib_dirs, library, &fullname))
switch(get_lib_type(opts->target_platform, lib_dirs, library, &fullname))
{
case file_arh:
strarray_add(files, strmake("-a%s", fullname));
@ -518,7 +526,6 @@ static void build(struct options* opts)
char *output_file;
const char *spec_o_name;
const char *output_name, *spec_file, *lang;
const char* winebuild = getenv("WINEBUILD");
int generate_app_loader = 1;
unsigned int j;
@ -532,8 +539,6 @@ static void build(struct options* opts)
* -xlll: lll is the language (c, c++, etc.)
*/
if (!winebuild) winebuild = "winebuild";
output_file = strdup( opts->output_name ? opts->output_name : "a.out" );
/* 'winegcc -o app xxx.exe.so' only creates the load script */
@ -577,6 +582,7 @@ static void build(struct options* opts)
/* mark the files with their appropriate type */
spec_file = lang = 0;
files = strarray_alloc();
link_args = strarray_alloc();
for ( j = 0; j < opts->files->size; j++ )
{
const char* file = opts->files->base[j];
@ -616,43 +622,131 @@ static void build(struct options* opts)
}
}
else if (file[1] == 'l')
add_library( lib_dirs, files, file + 2 );
add_library(opts, lib_dirs, files, file + 2 );
else if (file[1] == 'x')
lang = file;
}
if (opts->shared && !spec_file)
error("A spec file is currently needed in shared mode\n");
/* building for Windows is completely different */
if (opts->target_platform == PLATFORM_WINDOWS)
{
if (opts->shared)
{
/* run winebuild to generate the .def file */
char *spec_def_name = get_temp_file(output_name, ".spec.def");
spec_args = get_winebuild_args( opts );
strarray_add(spec_args, "--def");
strarray_add(spec_args, "-o");
strarray_add(spec_args, spec_def_name);
if (spec_file)
{
strarray_add(spec_args, "--export");
strarray_add(spec_args, spec_file);
}
spawn(opts->prefix, spec_args, 0);
strarray_free(spec_args);
if (opts->target) strarray_add(link_args, strmake("%s-dllwrap", opts->target));
else strarray_add(link_args, "dllwrap");
if (verbose) strarray_add(link_args, "-v");
strarray_add(link_args, "-k");
strarray_add(link_args, "--def");
strarray_add(link_args, spec_def_name);
}
else
{
strarray_addall(link_args, get_translator(opts));
strarray_add(link_args, opts->gui_app ? "-mwindows" : "-mconsole");
if (opts->use_msvcrt) strarray_add(link_args, "-mno-cygwin");
if (opts->nodefaultlibs) strarray_add(link_args, "-nodefaultlibs");
}
for ( j = 0 ; j < opts->linker_args->size ; j++ )
strarray_add(link_args, opts->linker_args->base[j]);
strarray_add(link_args, "-o");
strarray_add(link_args, output_file);
if (opts->image_base)
strarray_add(link_args, strmake("-Wl,--image-base,%s", opts->image_base));
for ( j = 0; j < lib_dirs->size; j++ )
strarray_add(link_args, strmake("-L%s", lib_dirs->base[j]));
if (opts->shared && !opts->nostdlib) add_library(opts, lib_dirs, files, "wine");
for ( j = 0; j < files->size; j++ )
{
const char* name = files->base[j] + 2;
switch(files->base[j][1])
{
case 'l':
case 's':
case 'd':
strarray_add(link_args, strmake("-l%s", name));
break;
case 'o':
strarray_add(link_args, name);
break;
case 'a':
if (strchr(name, '/'))
{
/* turn the path back into -Ldir -lfoo options
* this makes sure that we use the specified libs even
* when mingw adds its own import libs to the link */
char *lib = xstrdup( name );
char *p = strrchr( lib, '/' );
*p++ = 0;
if (!strncmp( p, "lib", 3 ))
{
char *ext = strrchr( p, '.' );
if (ext) *ext = 0;
p += 3;
strarray_add(link_args, strmake("-L%s", lib ));
strarray_add(link_args, strmake("-l%s", p ));
free( lib );
break;
}
free( lib );
}
strarray_add(link_args, name);
break;
}
}
spawn(opts->prefix, link_args, 0);
strarray_free (link_args);
return;
}
/* add the default libraries, if needed */
if (!opts->nostdlib && opts->use_msvcrt) add_library(lib_dirs, files, "msvcrt");
if (!opts->nostdlib && opts->use_msvcrt) add_library(opts, lib_dirs, files, "msvcrt");
if (!opts->wine_objdir && !opts->nodefaultlibs)
{
if (opts->gui_app)
{
add_library(lib_dirs, files, "shell32");
add_library(lib_dirs, files, "comdlg32");
add_library(lib_dirs, files, "gdi32");
add_library(opts, lib_dirs, files, "shell32");
add_library(opts, lib_dirs, files, "comdlg32");
add_library(opts, lib_dirs, files, "gdi32");
}
add_library(lib_dirs, files, "advapi32");
add_library(lib_dirs, files, "user32");
add_library(lib_dirs, files, "kernel32");
add_library(opts, lib_dirs, files, "advapi32");
add_library(opts, lib_dirs, files, "user32");
add_library(opts, lib_dirs, files, "kernel32");
}
if (!opts->nostartfiles) add_library(lib_dirs, files, "winecrt0");
if (!opts->nostdlib) add_library(lib_dirs, files, "wine");
if (!opts->nostartfiles) add_library(opts, lib_dirs, files, "winecrt0");
if (!opts->nostdlib) add_library(opts, lib_dirs, files, "wine");
/* run winebuild to generate the .spec.o file */
spec_args = strarray_alloc();
spec_args = get_winebuild_args( opts );
spec_o_name = get_temp_file(output_name, ".spec.o");
strarray_add(spec_args, winebuild);
if (verbose) strarray_add(spec_args, "-v");
if (keep_generated) strarray_add(spec_args, "--save-temps");
if (opts->target)
{
strarray_add(spec_args, "--target");
strarray_add(spec_args, opts->target);
}
if (opts->force_pointer_size)
strarray_add(spec_args, strmake("-m%u", 8 * opts->force_pointer_size ));
strarray_addall(spec_args, strarray_fromstring(DLLFLAGS, " "));
@ -704,7 +798,6 @@ static void build(struct options* opts)
strarray_free (spec_args);
/* link everything together now */
link_args = strarray_alloc();
strarray_addall(link_args, get_translator(opts));
strarray_addall(link_args, strarray_fromstring(LDDLLFLAGS, " "));