diff options
-rw-r--r-- | ChangeLog | 65 | ||||
-rw-r--r-- | configure.ac | 21 | ||||
-rw-r--r-- | gir/Makefile.am | 32 | ||||
-rw-r--r-- | girepository/Makefile.am | 1 | ||||
-rw-r--r-- | girepository/girparser.c | 2 | ||||
-rw-r--r-- | girepository/gtypelib.c | 64 | ||||
-rw-r--r-- | giscanner/Makefile.am | 23 | ||||
-rw-r--r-- | giscanner/cgobject.py | 6 | ||||
-rw-r--r-- | giscanner/giscannermodule.c | 49 | ||||
-rw-r--r-- | giscanner/grealpath.h | 33 | ||||
-rw-r--r-- | giscanner/scannerlexer.l | 52 | ||||
-rw-r--r-- | giscanner/sourcescanner.py | 2 | ||||
-rw-r--r-- | tools/Makefile.am | 8 | ||||
-rw-r--r-- | tools/generate.c | 1 |
14 files changed, 320 insertions, 39 deletions
@@ -1,3 +1,68 @@ +2008-08-27 Tor Lillqvist <tml@novell.com> + + Make g-ir-scanner work on Windows. Still problems with the typelib + code. Changes okayed by jdahlin. + + * configure.ac: Check for Windows, set Automake conditional + OS_WIN32. Change backslashes to forward slashes in pyexecdir to + avoid shell quoting issues + + * girepository/Makefile.am: Use -no-undefined so that libtool + agrees to build a shared library on Windows. + + * girepository/girparser.c (backtrace_stderr): No backtrace() on + Windows. Empty implementation on Windows so far. + + * girepository/gtypelib.c (g_typelib_check_sanity): Give more + informative error message for the assertion failures. Tell also + what the expected size of the struct is. Check all sizes first and + fail afterwards if at least one size was different from expected. + + * tools/Makefile.am: Reorder libraries into proper logical + dependency order. + + * tools/generate.c: Don't include <dlfcn.h>, not used. + + * giscanner/Makefile.am: On Windows, link with the Python library, + and install the module DLL as _giscanner.pyd. Remove the + unnecessary import library and libtool library that libtool has + installed. + + * giscanner/scannerlexer.l: Recognize the gcc __attribute__ syntax + and just skip it. Recognize also two "l" suffixes for long long + constants. Recognize also __inline__. + + * giscanner/grealpath.h (g_realpath): Implement on Windows, using + GetFullPathName(). As such, GetFullPathName() does more than the + UNIX realpath(). It also changes relative paths into absolute + paths. But for our purposes that shouldn't matter. + + * giscanner/giscannermodule.c (pygi_source_scanner_parse_file): On + Windows the file descriptor passed to us is from Python. Python + Python2.5 uses the msvcr71.dll C library, while mingw-built code + uses msvcrt.dll. On Windows, file descriptors are specific to + which C library is used. So we must find out what underlying OS + handle corresponds to the file descriptor Python passes us, and + then make that into a file descriptor valid for the C library this + code uses. + + * giscanner/sourcescanner.py (_parse): Don't need to bypass + __attribute__ as the lexer now handles it. The definition as empty + was ineffective for mingw anyway, as mingw's _mingw.h undefines + __attribute__. Close the temp file before unlinking it. + + * giscanner/cgobject.py: Use correct library name for the gobject + DLL on Windows. + + * gir/Makefile.am: Must pass the full basename of the DLLs on + Windows to g-ir-scanner. It's a bit ugly that we have to "know" + that the names of the GLib DLLs are like libglib-2.0-0.dll, but in + reality they won't change, until there is a GLib 3, and then also + the Unix code here needs changing. + + Must pass CPPFLAGS to g-ir-scanner when building GLib.gir so that + libintl.h is found. + 2008-08-26 Colin Walters <walters@verbum.org> * girepository/girepository.c: Search diff --git a/configure.ac b/configure.ac index ccd0c31a..d45b5e36 100644 --- a/configure.ac +++ b/configure.ac @@ -9,6 +9,20 @@ AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([m4]) +# Check for Win32 +AC_CANONICAL_HOST +AC_MSG_CHECKING([for Win32]) +case "$host" in +*-*-mingw*) + os_win32=yes + ;; +*) + os_win32=no + ;; +esac +AC_MSG_RESULT([$os_win32]) +AM_CONDITIONAL(OS_WIN32, [test "$os_win32" = "yes"]) + # Checks for programs. AC_PROG_CC AM_PROG_CC_C_O @@ -95,6 +109,13 @@ AC_CHECK_FUNCS([memchr strchr strspn strstr strtol strtoull]) AC_MSG_CHECKING([whether Python support is requested]) AM_PATH_PYTHON([2.5]) +case "$host" in +*-*-mingw*) + # Change backslashes to forward slashes in pyexecdir to avoid + # quoting issues + pyexecdir=`echo $pyexecdir | tr '\\\\' '/'` + ;; +esac AM_CHECK_PYTHON_HEADERS AC_CONFIG_FILES([ diff --git a/gir/Makefile.am b/gir/Makefile.am index 0c81b256..4dab268a 100644 --- a/gir/Makefile.am +++ b/gir/Makefile.am @@ -7,13 +7,21 @@ G_IR_SCANNER_FILES = $(top_srcdir)/giscanner/*.py \ # glib GLIB_INCLUDEDIR=`pkg-config --variable=includedir glib-2.0`/glib-2.0 GLIB_LIBDIR=`pkg-config --variable=libdir glib-2.0` + +if OS_WIN32 +GLIB_LIBRARY=libglib-2.0-0 +else +GLIB_LIBRARY=glib-2.0 +endif + GLib.gir: $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) PYTHONPATH=$(top_srcdir):$$PYTHONPATH $(G_IR_SCANNER) \ -v --namespace GLib \ --noclosure \ --output $@ \ --strip-prefix=g \ - --library=glib-2.0 \ + --library=$(GLIB_LIBRARY) \ + $(CPPFLAGS) \ -I$(GLIB_INCLUDEDIR) \ -I$(GLIB_LIBDIR)/glib-2.0/include \ -DGETTEXT_PACKAGE=Dummy \ @@ -25,6 +33,13 @@ BUILT_SOURCES += GLib.gir # gobject GOBJECT_INCLUDEDIR=`pkg-config --variable=includedir gobject-2.0`/glib-2.0 GOBJECT_LIBDIR=`pkg-config --variable=libdir gobject-2.0` + +if OS_WIN32 +GOBJECT_LIBRARY=libgobject-2.0-0 +else +GOBJECT_LIBRARY=gobject-2.0 +endif + GObject.gir: GLib.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) PYTHONPATH=$(top_srcdir):$$PYTHONPATH $(G_IR_SCANNER) \ -v --namespace GObject \ @@ -32,7 +47,7 @@ GObject.gir: GLib.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) --output $@ \ --strip-prefix=g \ --include=$(top_builddir)/gir/GLib.gir \ - --library=gobject-2.0 \ + --library=$(GOBJECT_LIBRARY) \ -I$(GOBJECT_INCLUDEDIR) \ -I$(GOBJECT_LIBDIR)/glib-2.0/include \ -DGOBJECT_COMPILATION \ @@ -43,6 +58,13 @@ BUILT_SOURCES += GObject.gir # gio GIO_INCLUDEDIR=`pkg-config --variable=includedir gio-2.0`/glib-2.0 GIO_LIBDIR=`pkg-config --variable=libdir gio-2.0` + +if OS_WIN32 +GIO_LIBRARY=libgio-2.0-0 +else +GIO_LIBRARY=gio-2.0 +endif + Gio.gir: GObject.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) PYTHONPATH=$(top_srcdir):$$PYTHONPATH $(G_IR_SCANNER) \ -v --namespace Gio \ @@ -50,7 +72,7 @@ Gio.gir: GObject.gir $(G_IR_SCANNER) $(G_IR_SCANNER_FILES) --output $@ \ --strip-prefix=g \ --include=$(top_builddir)/gir/GObject.gir \ - --library=gio-2.0 \ + --library=$(GIO_LIBRARY) \ -I$(GIO_INCLUDEDIR) \ -I$(GIO_LIBDIR)/glib-2.0/include \ -DGIO_COMPILATION \ @@ -63,8 +85,8 @@ CLEANFILES = $(BUILT_SOURCES) girdir=$(datadir)/gir dist_gir_DATA = $(BUILT_SOURCES) -%.typelib: %.gir $(top_builddir)/tools/g-ir-compiler - $(DEBUG) $(top_builddir)/tools/g-ir-compiler $< -o $@ +%.typelib: %.gir $(top_builddir)/tools/g-ir-compiler$(EXEEXT) + $(DEBUG) $(top_builddir)/tools/g-ir-compiler$(EXEEXT) $< -o $@ typelibsdir = $(datadir)/girepository typelibs_DATA = GLib.typelib GObject.typelib Gio.typelib diff --git a/girepository/Makefile.am b/girepository/Makefile.am index fe66da26..be2d0d9c 100644 --- a/girepository/Makefile.am +++ b/girepository/Makefile.am @@ -16,6 +16,7 @@ libgirepository_la_SOURCES = \ ginvoke.c libgirepository_la_CPPFLAGS = $(GIREPO_CFLAGS) libgirepository_la_LIBADD = $(GIREPO_LIBS) +libgirepository_la_LDFLAGS = -no-undefined libgirepository_parser_la_SOURCES = \ girmodule.c \ diff --git a/girepository/girparser.c b/girepository/girparser.c index 0f0a6add..247f896c 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -91,6 +91,7 @@ struct _ParseContext static void backtrace_stderr (void) { +#ifndef _WIN32 void *array[50]; int size; char **strings; @@ -107,6 +108,7 @@ backtrace_stderr (void) fprintf (stderr, "--- END BACKTRACE ---\n", size); free (strings); +#endif } diff --git a/girepository/gtypelib.c b/girepository/gtypelib.c index bfd7fd41..a6295cbb 100644 --- a/girepository/gtypelib.c +++ b/girepository/gtypelib.c @@ -141,31 +141,45 @@ void g_typelib_check_sanity (void) { /* Check that struct layout is as we expect */ - g_assert (sizeof (Header) == 100); - g_assert (sizeof (DirEntry) == 12); - g_assert (sizeof (SimpleTypeBlob) == 4); - g_assert (sizeof (ArgBlob) == 12); - g_assert (sizeof (SignatureBlob) == 8); - g_assert (sizeof (CommonBlob) == 8); - g_assert (sizeof (FunctionBlob) == 16); - g_assert (sizeof (InterfaceTypeBlob) == 4); - g_assert (sizeof (ArrayTypeBlob) == 8); - g_assert (sizeof (ParamTypeBlob) == 4); - g_assert (sizeof (ErrorTypeBlob) == 4); - g_assert (sizeof (ErrorDomainBlob) == 16); - g_assert (sizeof (ValueBlob) == 12); - g_assert (sizeof (FieldBlob) == 12); - g_assert (sizeof (RegisteredTypeBlob) == 16); - g_assert (sizeof (StructBlob) == 20); - g_assert (sizeof (EnumBlob) == 20); - g_assert (sizeof (PropertyBlob) == 12); - g_assert (sizeof (SignalBlob) == 12); - g_assert (sizeof (VFuncBlob) == 16); - g_assert (sizeof (ObjectBlob) == 32); - g_assert (sizeof (InterfaceBlob) == 28); - g_assert (sizeof (ConstantBlob) == 20); - g_assert (sizeof (AnnotationBlob) == 12); - g_assert (sizeof (UnionBlob) == 28); + + gboolean size_check_ok = TRUE; + +#define CHECK_SIZE(s,n) \ + if (sizeof(s) != n) \ + { \ + g_printerr ("sizeof("#s") is expected to be %d but is %"G_GSIZE_FORMAT".\n", \ + n, sizeof (s)); \ + size_check_ok = FALSE; \ + } + + CHECK_SIZE (Header, 100); + CHECK_SIZE (DirEntry, 12); + CHECK_SIZE (SimpleTypeBlob, 4); + CHECK_SIZE (ArgBlob, 12); + CHECK_SIZE (SignatureBlob, 8); + CHECK_SIZE (CommonBlob, 8); + CHECK_SIZE (FunctionBlob, 16); + CHECK_SIZE (InterfaceTypeBlob, 4); + CHECK_SIZE (ArrayTypeBlob, 8); + CHECK_SIZE (ParamTypeBlob, 4); + CHECK_SIZE (ErrorTypeBlob, 4); + CHECK_SIZE (ErrorDomainBlob, 16); + CHECK_SIZE (ValueBlob, 12); + CHECK_SIZE (FieldBlob, 12); + CHECK_SIZE (RegisteredTypeBlob, 16); + CHECK_SIZE (StructBlob, 20); + CHECK_SIZE (EnumBlob, 20); + CHECK_SIZE (PropertyBlob, 12); + CHECK_SIZE (SignalBlob, 12); + CHECK_SIZE (VFuncBlob, 16); + CHECK_SIZE (ObjectBlob, 32); + CHECK_SIZE (InterfaceBlob, 28); + CHECK_SIZE (ConstantBlob, 20); + CHECK_SIZE (AnnotationBlob, 12); + CHECK_SIZE (UnionBlob, 28); +#undef CHECK_SIZE + + g_assert (size_check_ok); } diff --git a/giscanner/Makefile.am b/giscanner/Makefile.am index 014a83d7..9ab9d8d4 100644 --- a/giscanner/Makefile.am +++ b/giscanner/Makefile.am @@ -55,12 +55,33 @@ _giscanner_la_CFLAGS = \ $(GOBJECT_CFLAGS) \ -I$(top_srcdir)/giscanner _giscanner_la_LIBADD = $(GOBJECT_LIBS) libgiscanner.la + _giscanner_la_LDFLAGS = \ - -module -avoid-version -export-symbols-regex init_giscanner + -module -avoid-version -export-symbols-regex init_giscanner -no-undefined + +if OS_WIN32 +# Yuck. Probably there is a way to get this from Python, but I don't +# know how. Use -Wl to avoid libtool crack. +_giscanner_la_LDFLAGS += -Wl,$(pyexecdir)/../../libs/libpython25.a +endif + _giscanner_la_SOURCES = giscannermodule.c +if OS_WIN32 +BUILT_SOURCES += _giscanner.pyd +CLEANFILES += _giscanner.pyd + +_giscanner.pyd: _giscanner.la + cp .libs/_giscanner.dll $@ + +install-exec-hook: + mv $(pkgpyexecdir)/_giscanner.dll $(pkgpyexecdir)/_giscanner.pyd + rm $(pkgpyexecdir)/_giscanner.dll.a + rm $(pkgpyexecdir)/_giscanner.la +else BUILT_SOURCES += _giscanner.so CLEANFILES += _giscanner.so +endif # Yuck, ugly but... _giscanner.so: _giscanner.la diff --git a/giscanner/cgobject.py b/giscanner/cgobject.py index c34f4977..2040cd38 100644 --- a/giscanner/cgobject.py +++ b/giscanner/cgobject.py @@ -29,6 +29,7 @@ # based on defsgen.py (C) 2006 John Finlay # +import os import ctypes from ctypes.util import find_library @@ -124,7 +125,10 @@ class GSignalInfo(ctypes.Structure): yield self.param_types[i] -_library_path = find_library('gobject-2.0') +if os.name == 'nt': + _library_path = find_library('libgobject-2.0-0') +else: + _library_path = find_library('gobject-2.0') if not _library_path: raise ImportError("Could not find gobject-2.0 library") _gobj = ctypes.CDLL(_library_path, ctypes.RTLD_GLOBAL) diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c index 3d3e7d95..8159c599 100644 --- a/giscanner/giscannermodule.c +++ b/giscanner/giscannermodule.c @@ -25,6 +25,14 @@ #include "sourcescanner.h" #include <Python.h> +#ifdef _WIN32 +#include <fcntl.h> +#include <io.h> +#define WIN32_LEAN_AND_MEAN +#define STRICT +#include <windows.h> +#endif + #define NEW_CLASS(ctype, name, cname) \ static const PyMethodDef _Py##cname##_methods[]; \ PyTypeObject Py##cname##_Type = { \ @@ -393,6 +401,47 @@ pygi_source_scanner_parse_file (PyGISourceScanner *self, if (!PyArg_ParseTuple (args, "i:SourceScanner.parse_file", &fd)) return NULL; +#ifdef _WIN32 + /* The file descriptor passed to us is from the C library Python + * uses. That is msvcr71.dll at least for Python 2.5. This code, at + * least if compiled with mingw, uses msvcrt.dll, so we cannot use + * the file descriptor directly. So perform appropriate magic. + */ + { + HMODULE msvcr71; + int (*p__get_osfhandle) (int); + HANDLE handle; + + msvcr71 = GetModuleHandle ("msvcr71.dll"); + if (!msvcr71) + { + g_print ("No msvcr71.dll loaded.\n"); + return NULL; + } + + p__get_osfhandle = GetProcAddress (msvcr71, "_get_osfhandle"); + if (!p__get_osfhandle) + { + g_print ("No _get_osfhandle found in msvcr71.dll.\n"); + return NULL; + } + + handle = p__get_osfhandle (fd); + if (!p__get_osfhandle) + { + g_print ("Could not get OS handle from msvcr71 fd.\n"); + return NULL; + } + + fd = _open_osfhandle (handle, _O_RDONLY); + if (fd == -1) + { + g_print ("Could not open C fd from OS handle.\n"); + return NULL; + } + } +#endif + fp = fdopen (fd, "r"); if (!fp) { diff --git a/giscanner/grealpath.h b/giscanner/grealpath.h index ca88190b..01d0a54c 100644 --- a/giscanner/grealpath.h +++ b/giscanner/grealpath.h @@ -10,11 +10,44 @@ static inline gchar* g_realpath (const char *path) { +#ifndef _WIN32 char buffer [PATH_MAX]; if (realpath(path, buffer)) return g_strdup(buffer); else return NULL; +#else + /* We don't want to include <windows.h> as it clashes horribly + * with token names from scannerparser.h. So just declare + * GetFullPathNameA() here. + */ + extern __stdcall GetFullPathNameA(const char*, int, char*, char**); + char *buffer; + char dummy; + int rc, len; + + rc = GetFullPathNameA(path, 1, &dummy, NULL); + + if (rc == 0) + { + /* Weird failure, so just return the input path as such */ + return g_strdup(path); + } + + len = rc + 1; + buffer = g_malloc(len); + + rc = GetFullPathNameA(path, len, buffer, NULL); + + if (rc == 0 || rc > len) + { + /* Weird failure again */ + g_free(buffer); + return g_strdup(path); + } + + return buffer; +#endif } #endif diff --git a/giscanner/scannerlexer.l b/giscanner/scannerlexer.l index 51355c2a..c4eb1d41 100644 --- a/giscanner/scannerlexer.l +++ b/giscanner/scannerlexer.l @@ -44,9 +44,10 @@ static int yywrap (void); static void parse_comment (GISourceScanner *scanner); static void process_directive (GISourceScanner *scanner); static int check_identifier (GISourceScanner *scanner, const char *); +static int parse_attribute (void); %} -intsuffix ([uU][lL]?)|([lL][uU]?) +intsuffix ([uU][lL]?[lL]?)|([lL][lL]?[uU]?) fracconst ([0-9]*\.[0-9]+)|([0-9]+\.) exppart [eE][-+]?[0-9]+ floatsuffix [fFlL] @@ -117,6 +118,8 @@ stringtext ([^\"])|(\\.) "," { return ','; } "->" { return ARROW; } +"__attribute__" { if (!parse_attribute()) REJECT; } + [a-zA-Z_][a-zA-Z_0-9]* { if (scanner->macro_scan) return IDENTIFIER; else REJECT; } "auto" { return AUTO; } @@ -137,6 +140,7 @@ stringtext ([^\"])|(\\.) "goto" { return GOTO; } "if" { return IF; } "inline" { return INLINE; } +"__inline__" { return INLINE; } "int" { return INT; } "long" { return LONG; } "register" { return REGISTER; } @@ -405,3 +409,49 @@ process_directive (GISourceScanner *scanner) g_string_free (filename_builder, TRUE); } +static int +parse_attribute (void) +{ + int c; + int nest; + + while ((c = input ()) != EOF && isspace (c)) + ; + if (c != '(') + return FALSE; + while ((c = input ()) != EOF && isspace (c)) + ; + if (c != '(') + return FALSE; + + nest = 0; + while ((c = input ()) != EOF && (nest > 0 || c != ')')) { + if (c == '(') + nest++; + else if (c == ')') + nest--; + else if (c == '"') { + while ((c = input ()) != EOF && c != '"') { + if (c == '\\') + c = input (); + } + } else if (c == '\'') { + c = input (); + if (c == '\\') + c = input (); + else if (c == '\'') + return FALSE; + c = input (); + if (c != '\'') + return FALSE; + } else if (c == '\n') + lineno++; + } + + while ((c = input ()) != EOF && isspace (c)) + ; + if (c != ')') + return FALSE; + + return TRUE; +} diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py index f6385a88..a58c44a2 100644 --- a/giscanner/sourcescanner.py +++ b/giscanner/sourcescanner.py @@ -231,7 +231,6 @@ class SourceScanner(object): stdin=subprocess.PIPE, stdout=subprocess.PIPE) - proc.stdin.write('#define __attribute__(x)\n') proc.stdin.write('#define __const\n') proc.stdin.write('#define __extension__\n') proc.stdin.write('#define __inline\n') @@ -260,4 +259,5 @@ class SourceScanner(object): fp.seek(0, 0) assert proc, 'Proc was none' self._scanner.parse_file(fp.fileno()) + fp.close() os.unlink(tmp) diff --git a/tools/Makefile.am b/tools/Makefile.am index 17fd0080..96dcecb0 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -10,15 +10,15 @@ bin_SCRIPTS = g-ir-scanner g_ir_compiler_SOURCES = compiler.c g_ir_compiler_CFLAGS = $(GIREPO_CFLAGS) g_ir_compiler_LDADD = \ - $(GIREPO_LIBS) \ + $(top_builddir)/girepository/libgirepository-parser.la \ $(top_builddir)/girepository/libgirepository.la \ - $(top_builddir)/girepository/libgirepository-parser.la + $(GIREPO_LIBS) g_ir_generate_SOURCES = generate.c g_ir_generate_CFLAGS = $(GIREPO_CFLAGS) g_ir_generate_LDADD = \ - $(GIREPO_LIBS) \ - $(top_builddir)/girepository/libgirepository.la + $(top_builddir)/girepository/libgirepository.la \ + $(GIREPO_LIBS) GCOVSOURCES = \ $(g_ir_compiler_SOURCES) \ diff --git a/tools/generate.c b/tools/generate.c index 53bebd22..02152df3 100644 --- a/tools/generate.c +++ b/tools/generate.c @@ -20,7 +20,6 @@ */ #include <errno.h> -#include <dlfcn.h> #include <string.h> #include <glib.h> |