Alexandre Julliard : winebuild: Add support for creating static import libraries.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Mar 25 10:00:38 CDT 2016
Module: wine
Branch: master
Commit: aac69889bf1e276688895eca313dc861cab07545
URL: http://source.winehq.org/git/wine.git/?a=commit;h=aac69889bf1e276688895eca313dc861cab07545
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Mar 25 15:32:22 2016 +0900
winebuild: Add support for creating static import libraries.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
tools/winebuild/build.h | 1 +
tools/winebuild/import.c | 132 ++++++++++++++++++++++++++++++++++++---
tools/winebuild/utils.c | 7 +++
tools/winebuild/winebuild.man.in | 2 +-
4 files changed, 131 insertions(+), 11 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 5cf984b..03b88fa 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -233,6 +233,7 @@ extern char *strmake(const char* fmt, ...) __attribute__((__format__ (__printf__
extern struct strarray strarray_fromstring( const char *str, const char *delim );
extern void strarray_add( struct strarray *array, ... );
extern void strarray_addv( struct strarray *array, char * const *argv );
+extern void strarray_addall( struct strarray *array, struct strarray args );
extern DECLSPEC_NORETURN void fatal_error( const char *msg, ... )
__attribute__ ((__format__ (__printf__, 1, 2)));
extern DECLSPEC_NORETURN void fatal_perror( const char *msg, ... )
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 1d561c4..d2d6f57 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -68,6 +68,10 @@ static struct strarray ext_link_imports; /* list of external symbols to link to
static struct list dll_imports = LIST_INIT( dll_imports );
static struct list dll_delayed = LIST_INIT( dll_delayed );
+static struct strarray as_files;
+
+static const char import_func_prefix[] = "__wine$func$";
+static const char import_ord_prefix[] = "__wine$ord$";
static inline const char *ppc_reg( int reg )
{
@@ -1283,16 +1287,56 @@ void output_imports( DLLSPEC *spec )
output_external_link_imports( spec );
}
-/* output an import library for a Win32 module and additional object files */
-void output_import_lib( DLLSPEC *spec, char **argv )
+/* create a new asm temp file */
+static void new_output_as_file( const char *prefix )
+{
+ char *name = get_temp_file_name( prefix, ".s" );
+
+ if (output_file) fclose( output_file );
+ if (!(output_file = fopen( name, "w" )))
+ fatal_error( "Unable to create output file '%s'\n", name );
+ strarray_add( &as_files, name, NULL );
+}
+
+/* assemble all the asm files */
+static void assemble_files( const char *prefix )
+{
+ unsigned int i;
+
+ if (output_file) fclose( output_file );
+ output_file = NULL;
+
+ for (i = 0; i < as_files.count; i++)
+ {
+ char *obj = get_temp_file_name( prefix, ".o" );
+ assemble_file( as_files.str[i], obj );
+ as_files.str[i] = obj;
+ }
+}
+
+/* build a library from the current asm files and any additional object files in argv */
+static void build_library( const char *output_name, char **argv, int create )
+{
+ struct strarray args = find_tool( "ar", NULL );
+ struct strarray ranlib = find_tool( "ranlib", NULL );
+
+ strarray_add( &args, create ? "rc" : "r", output_name, NULL );
+ strarray_addall( &args, as_files );
+ strarray_addv( &args, argv );
+ if (create) unlink( output_name );
+ spawn( args );
+
+ strarray_add( &ranlib, output_name, NULL );
+ spawn( ranlib );
+}
+
+/* create a Windows-style import library */
+static void build_windows_import_lib( DLLSPEC *spec )
{
struct strarray args;
char *def_file;
const char *as_flags, *m_flag;
- if (target_platform != PLATFORM_WINDOWS)
- fatal_error( "Unix-style import libraries not supported yet\n" );
-
def_file = get_temp_file_name( output_file_name, ".def" );
fclose( output_file );
if (!(output_file = fopen( def_file, "w" )))
@@ -1320,13 +1364,81 @@ void output_import_lib( DLLSPEC *spec, char **argv )
if (m_flag)
strarray_add( &args, "-m", m_flag, as_flags, NULL );
spawn( args );
+}
+
+/* create a Unix-style import library */
+static void build_unix_import_lib( DLLSPEC *spec )
+{
+ static const char valid_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789._@";
+ int i, total;
+ const char *name, *prefix;
+ char *dll_name = xstrdup( spec->file_name );
- if (argv[0])
+ if (strendswith( dll_name, ".dll" )) dll_name[strlen(dll_name) - 4] = 0;
+ if (strspn( dll_name, valid_chars ) < strlen( dll_name ))
+ fatal_error( "%s contains invalid characters\n", spec->file_name );
+
+ /* entry points */
+
+ for (i = total = 0; i < spec->nb_entry_points; i++)
+ {
+ const ORDDEF *odp = &spec->entry_points[i];
+
+ if (odp->name) name = odp->name;
+ else if (odp->export_name) name = odp->export_name;
+ else continue;
+
+ if (odp->flags & FLAG_PRIVATE) continue;
+ total++;
+
+ /* C++ mangled names cannot be imported */
+ if (strpbrk( name, "?@" )) continue;
+
+ switch(odp->type)
+ {
+ case TYPE_VARARGS:
+ case TYPE_CDECL:
+ case TYPE_STDCALL:
+ case TYPE_THISCALL:
+ prefix = (!odp->name || (odp->flags & FLAG_ORDINAL)) ? import_ord_prefix : import_func_prefix;
+ new_output_as_file( spec->file_name );
+ output( "\t.text\n" );
+ output( "\n\t.align %d\n", get_alignment( get_ptr_size() ));
+ output( "\t%s\n", func_declaration( name ) );
+ output( "%s\n", asm_globl( name ) );
+ output( "\t%s %s%s$%u$%s\n", get_asm_ptr_keyword(),
+ asm_name( prefix ), dll_name, odp->ordinal, name );
+ output_function_size( name );
+ break;
+
+ default:
+ break;
+ }
+ }
+ if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
+
+ if (!as_files.count) /* create a dummy file to avoid empty import libraries */
+ {
+ new_output_as_file( spec->file_name );
+ output( "\t.text\n" );
+ }
+
+ assemble_files( spec->file_name );
+ free( dll_name );
+}
+
+/* output an import library for a Win32 module and additional object files */
+void output_import_lib( DLLSPEC *spec, char **argv )
+{
+ if (target_platform == PLATFORM_WINDOWS)
+ {
+ build_windows_import_lib( spec );
+ if (argv[0]) build_library( output_file_name, argv, 0 );
+ }
+ else
{
- args = find_tool( "ar", NULL );
- strarray_add( &args, "rs", output_file_name, NULL );
- strarray_addv( &args, argv );
- spawn( args );
+ build_unix_import_lib( spec );
+ build_library( output_file_name, argv, 1 );
}
output_file_name = NULL;
}
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index c513565..9308e83 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -182,6 +182,13 @@ void strarray_addv( struct strarray *array, char * const *argv )
while (*argv) strarray_add_one( array, *argv++ );
}
+void strarray_addall( struct strarray *array, struct strarray args )
+{
+ unsigned int i;
+
+ for (i = 0; i < args.count; i++) strarray_add_one( array, args.str[i] );
+}
+
struct strarray strarray_fromstring( const char *str, const char *delim )
{
const char *tok;
diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in
index 2063738..d99fb57 100644
--- a/tools/winebuild/winebuild.man.in
+++ b/tools/winebuild/winebuild.man.in
@@ -47,7 +47,7 @@ Build a .def file from a spec file. The .spec file is specified via the
\fB-E\fR option. This is used when building dlls with a PE (Win32) compiler.
.TP
.BI \--implib
-Build a PE import library from a spec file. The .spec file is
+Build a .a import library from a spec file. The .spec file is
specified via the \fB-E\fR option.
.TP
.B \--resources
More information about the wine-cvs
mailing list