winegcc: Add support for building PE executables using Mingw.
This commit is contained in:
parent
bcc1379bda
commit
6f74b45a81
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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, " "));
|
||||
|
||||
|
|
Loading…
Reference in New Issue