Commit 6f74b45a authored by Alexandre Julliard's avatar Alexandre Julliard

winegcc: Add support for building PE executables using Mingw.

parent bcc1379b
...@@ -35,8 +35,8 @@ $(MODULE).so: $(MAINSPEC) $(ALL_OBJS) Makefile.in ...@@ -35,8 +35,8 @@ $(MODULE).so: $(MAINSPEC) $(ALL_OBJS) Makefile.in
# Rules for .dll files # Rules for .dll files
$(MODULE): $(RCOBJS) $(OBJS) $(SPEC_DEF) Makefile.in $(MODULE): $(MAINSPEC) $(RCOBJS) $(OBJS) Makefile.in
$(DLLWRAP) -k --def $(SPEC_DEF) -o $@ $(RCOBJS) $(OBJS) $(DLL_LDPATH) $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(LIBWINE) $(ALL_LIBS) $(WINEGCC) -shared $(SRCDIR)/$(MAINSPEC) $(OBJS) $(RCOBJS) $(EXTRADLLFLAGS) -o $@ $(DELAYIMPORTS:%=-l%) $(IMPORTS:%=-l%) $(ALL_LIBS)
# Rules for import libraries # Rules for import libraries
......
...@@ -38,7 +38,7 @@ $(MODULE).so: $(OBJS) $(RC_SRCS:.rc=.res) Makefile.in ...@@ -38,7 +38,7 @@ $(MODULE).so: $(OBJS) $(RC_SRCS:.rc=.res) Makefile.in
# Rules for .exe main module # Rules for .exe main module
$(MODULE): $(OBJS) $(RCOBJS) Makefile.in $(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 # Rules for building test list
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
DLLFLAGS = @DLLFLAGS@ DLLFLAGS = @DLLFLAGS@
DEFS = $(EXTRADEFS) 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) RUNTESTFLAGS= -q -P wine -T $(TOPOBJDIR)
INSTALLDIRS = $(DESTDIR)$(bindir) $(DESTDIR)$(dlldir) $(DESTDIR)$(mandir)/man$(prog_manext) INSTALLDIRS = $(DESTDIR)$(bindir) $(DESTDIR)$(dlldir) $(DESTDIR)$(mandir)/man$(prog_manext)
...@@ -27,7 +27,7 @@ $(MODULE).so: $(OBJS) $(RC_SRCS:.rc=.res) Makefile.in ...@@ -27,7 +27,7 @@ $(MODULE).so: $(OBJS) $(RC_SRCS:.rc=.res) Makefile.in
# Rules for .exe main module # Rules for .exe main module
$(MODULE): $(OBJS) $(RCOBJS) Makefile.in $(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 # Rules for testing
......
...@@ -50,7 +50,7 @@ winetest-dist.exe.so: $(OBJS) dist.res Makefile.in ...@@ -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) $(WINEGCC) $(APPMODE) $(OBJS) dist.res -o $@ -L$(DLLDIR) $(DELAYIMPORTS:%=-Wb,-d%) $(ALL_LIBS)
winetest-dist.exe: $(OBJS) dist.res.o Makefile.in 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 $@ -upx -9 -qqq $@
dist.res: winetest.rc tests.rc build.nfo winetest.ico $(TESTBINS) dist.res: winetest.rc tests.rc build.nfo winetest.ico $(TESTBINS)
......
...@@ -258,36 +258,38 @@ static char* try_lib_path(const char* dir, const char* pre, ...@@ -258,36 +258,38 @@ static char* try_lib_path(const char* dir, const char* pre,
return 0; 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 (platform != PLATFORM_WINDOWS)
if ((*file = try_lib_path(dir, "lib", library, ".so", file_so))) {
return file_so; /* Unix shared object */
if ((*file = try_lib_path(dir, "lib", library, ".so", file_so)))
/* Mach-O (Darwin/Mac OS X) Dynamic Library behaves mostly like .so */ return file_so;
if ((*file = try_lib_path(dir, "lib", library, ".dylib", 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)))
/* Windows DLL */ return file_so;
if ((*file = try_lib_path(dir, "lib", library, ".def", file_def)))
return file_dll; /* Windows DLL */
if ((*file = try_lib_path(dir, "", library, ".def", file_def))) if ((*file = try_lib_path(dir, "lib", library, ".def", file_def)))
return file_dll; return file_dll;
}
/* Unix static archives */
/* static archives */
if ((*file = try_lib_path(dir, "lib", library, ".a", file_arh))) if ((*file = try_lib_path(dir, "lib", library, ".a", file_arh)))
return file_arh; return file_arh;
return file_na; 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; unsigned int i;
for (i = 0; i < path->size; 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; if (type != file_na) return type;
} }
return file_na; return file_na;
......
...@@ -31,6 +31,16 @@ ...@@ -31,6 +31,16 @@
# endif # endif
#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 error(const char* s, ...) DECLSPEC_NORETURN;
void* xmalloc(size_t size); void* xmalloc(size_t size);
...@@ -62,7 +72,7 @@ typedef enum { ...@@ -62,7 +72,7 @@ typedef enum {
char* get_basename(const char* file); char* get_basename(const char* file);
void create_file(const char* name, int mode, const char* fmt, ...); void create_file(const char* name, int mode, const char* fmt, ...);
file_type get_file_type(const char* filename); 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); void spawn(const strarray* prefix, const strarray* arr, int ignore_errors);
extern int verbose; extern int verbose;
...@@ -145,16 +145,6 @@ static sigset_t signal_mask; ...@@ -145,16 +145,6 @@ static sigset_t signal_mask;
enum processor { proc_cc, proc_cxx, proc_cpp, proc_as }; 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 static const struct
{ {
const char *name; const char *name;
...@@ -474,6 +464,24 @@ static const char* compile_to_object(struct options* opts, const char* file, con ...@@ -474,6 +464,24 @@ static const char* compile_to_object(struct options* opts, const char* file, con
return copts.output_name; 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 */ /* check if there is a static lib associated to a given dll */
static char *find_static_lib( const char *dll ) static char *find_static_lib( const char *dll )
{ {
...@@ -484,11 +492,11 @@ 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 */ /* 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; 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: case file_arh:
strarray_add(files, strmake("-a%s", fullname)); strarray_add(files, strmake("-a%s", fullname));
...@@ -518,7 +526,6 @@ static void build(struct options* opts) ...@@ -518,7 +526,6 @@ static void build(struct options* opts)
char *output_file; char *output_file;
const char *spec_o_name; const char *spec_o_name;
const char *output_name, *spec_file, *lang; const char *output_name, *spec_file, *lang;
const char* winebuild = getenv("WINEBUILD");
int generate_app_loader = 1; int generate_app_loader = 1;
unsigned int j; unsigned int j;
...@@ -532,8 +539,6 @@ static void build(struct options* opts) ...@@ -532,8 +539,6 @@ static void build(struct options* opts)
* -xlll: lll is the language (c, c++, etc.) * -xlll: lll is the language (c, c++, etc.)
*/ */
if (!winebuild) winebuild = "winebuild";
output_file = strdup( opts->output_name ? opts->output_name : "a.out" ); output_file = strdup( opts->output_name ? opts->output_name : "a.out" );
/* 'winegcc -o app xxx.exe.so' only creates the load script */ /* 'winegcc -o app xxx.exe.so' only creates the load script */
...@@ -577,6 +582,7 @@ static void build(struct options* opts) ...@@ -577,6 +582,7 @@ static void build(struct options* opts)
/* mark the files with their appropriate type */ /* mark the files with their appropriate type */
spec_file = lang = 0; spec_file = lang = 0;
files = strarray_alloc(); files = strarray_alloc();
link_args = strarray_alloc();
for ( j = 0; j < opts->files->size; j++ ) for ( j = 0; j < opts->files->size; j++ )
{ {
const char* file = opts->files->base[j]; const char* file = opts->files->base[j];
...@@ -616,43 +622,131 @@ static void build(struct options* opts) ...@@ -616,43 +622,131 @@ static void build(struct options* opts)
} }
} }
else if (file[1] == 'l') 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') else if (file[1] == 'x')
lang = file; lang = file;
} }
if (opts->shared && !spec_file) if (opts->shared && !spec_file)
error("A spec file is currently needed in shared mode\n"); 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 */ /* 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->wine_objdir && !opts->nodefaultlibs)
{ {
if (opts->gui_app) if (opts->gui_app)
{ {
add_library(lib_dirs, files, "shell32"); add_library(opts, lib_dirs, files, "shell32");
add_library(lib_dirs, files, "comdlg32"); add_library(opts, lib_dirs, files, "comdlg32");
add_library(lib_dirs, files, "gdi32"); add_library(opts, lib_dirs, files, "gdi32");
} }
add_library(lib_dirs, files, "advapi32"); add_library(opts, lib_dirs, files, "advapi32");
add_library(lib_dirs, files, "user32"); add_library(opts, lib_dirs, files, "user32");
add_library(lib_dirs, files, "kernel32"); add_library(opts, lib_dirs, files, "kernel32");
} }
if (!opts->nostartfiles) add_library(lib_dirs, files, "winecrt0"); if (!opts->nostartfiles) add_library(opts, lib_dirs, files, "winecrt0");
if (!opts->nostdlib) add_library(lib_dirs, files, "wine"); if (!opts->nostdlib) add_library(opts, lib_dirs, files, "wine");
/* run winebuild to generate the .spec.o file */ /* 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"); 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) if (opts->force_pointer_size)
strarray_add(spec_args, strmake("-m%u", 8 * opts->force_pointer_size )); strarray_add(spec_args, strmake("-m%u", 8 * opts->force_pointer_size ));
strarray_addall(spec_args, strarray_fromstring(DLLFLAGS, " ")); strarray_addall(spec_args, strarray_fromstring(DLLFLAGS, " "));
...@@ -704,7 +798,6 @@ static void build(struct options* opts) ...@@ -704,7 +798,6 @@ static void build(struct options* opts)
strarray_free (spec_args); strarray_free (spec_args);
/* link everything together now */ /* link everything together now */
link_args = strarray_alloc();
strarray_addall(link_args, get_translator(opts)); strarray_addall(link_args, get_translator(opts));
strarray_addall(link_args, strarray_fromstring(LDDLLFLAGS, " ")); strarray_addall(link_args, strarray_fromstring(LDDLLFLAGS, " "));
......
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