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