[pygobject/wip/msvc: 17/17] Support MSVC builds of PyGObject-3.x



commit 6e03803cf31e5f375ed204d01cddcc977fd0f7b2
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Sat Nov 26 23:42:56 2016 +0800

    Support MSVC builds of PyGObject-3.x
    
    The official compiler that is supported by Python is Visual Studio, namely
    2008 for 2.7.x and 3.2.x, 2010 for 3.3.x and 3.4.x and 2015 for 3.5.x and
    later, so this is work to add build support for Visual Studio via NMake,
    so that we can reduce the problems that are caused by different CRTs that
    are used by Python and PyGObject builds, as GLib and g-i supported builds
    using Visual Studio 2008~2015 for a while.
    
    Some wrapper calls are also added to setup.py so that installations using
    setuptools can be supported, like what is done for the autotools buids,
    for release builds.

 Makefile.am                    |    2 +-
 configure.ac                   |    2 +
 gi/Makefile.am                 |   92 +--------------------------
 gi/pygi-srcs.mak               |   88 ++++++++++++++++++++++++++
 setup.py                       |   72 +++++++++++++++------
 win32/Makefile.am              |   17 +++++
 win32/Makefile.vc              |   44 +++++++++++++
 win32/README.txt               |   82 ++++++++++++++++++++++++
 win32/build-rules-msvc.mak     |   60 ++++++++++++++++++
 win32/config-msvc.mak          |   68 ++++++++++++++++++++
 win32/configpy.py              |   24 +++++++
 win32/create-lists-msvc.mak    |   61 ++++++++++++++++++
 win32/create-lists.bat         |   42 ++++++++++++
 win32/detectenv-msvc.mak       |  136 ++++++++++++++++++++++++++++++++++++++++
 win32/generate-msvc.mak        |    8 +++
 win32/info-msvc.mak            |   76 ++++++++++++++++++++++
 win32/install.mak              |   26 ++++++++
 win32/pc_base.py               |  124 ++++++++++++++++++++++++++++++++++++
 win32/pygobject-version.mak.in |    5 ++
 win32/pygobjectpc.py           |   32 +++++++++
 win32/pythonconfig.mak         |   15 +++++
 win32/replace.py               |  109 ++++++++++++++++++++++++++++++++
 22 files changed, 1076 insertions(+), 109 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4c91362..05c46d0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 # Limit PyFlakes and PEP8 to these directories.
-pycheck_dirs = examples gi tests pygtkcompat
+pycheck_dirs = examples gi tests pygtkcompat win32
 
 # Part of the gi subdirectory is handled with non-recursive make to avoid
 # py-compile getting confused between gi/types.py and Python's standard
diff --git a/configure.ac b/configure.ac
index b9358ea..aa04cde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -238,6 +238,8 @@ AC_CONFIG_FILES(
   examples/Makefile
   tests/Makefile
   pygtkcompat/Makefile
+  win32/Makefile
+  win32/pygobject-version.mak
   PKG-INFO)
 AC_OUTPUT
 
diff --git a/gi/Makefile.am b/gi/Makefile.am
index 9a8b7ec..2ecc935 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -34,92 +34,9 @@ pygidir = $(pyexecdir)/gi
 
 pygi_LTLIBRARIES = _gi.la
 
-_gi_la_SOURCES = \
-       gobjectmodule.c \
-       gobjectmodule.h \
-       pygboxed.c \
-       pygboxed.h \
-       pygenum.c \
-       pygenum.h \
-       pygflags.c \
-       pygflags.h \
-       pyginterface.c \
-       pyginterface.h \
-       pygobject.h \
-       pygobject-internal.h \
-       pygobject-object.c \
-       pygobject-object.h \
-       pygparamspec.c \
-       pygparamspec.h \
-       pygpointer.c \
-       pygpointer.h \
-       pygtype.c \
-       pygtype.h \
-       glibmodule.c \
-       pygoptioncontext.c \
-       pygoptioncontext.h \
-       pygoptiongroup.c \
-       pygoptiongroup.h \
-       pygspawn.c \
-       pygspawn.h \
-       pyglib.c \
-       pyglib.h \
-       pyglib-python-compat.h \
-       gimodule.c \
-       pygi-repository.c \
-       pygi-repository.h \
-       pygi-info.c \
-       pygi-info.h \
-       pygi-foreign.c \
-       pygi-foreign.h \
-       pygi-foreign-api.h \
-       pygi-struct.c \
-       pygi-struct.h \
-       pygi-source.c \
-       pygi-source.h \
-       pygi-argument.c \
-       pygi-argument.h \
-       pygi-resulttuple.c \
-       pygi-resulttuple.h \
-       pygi-type.c \
-       pygi-type.h \
-       pygi-boxed.c \
-       pygi-boxed.h \
-       pygi-closure.c \
-       pygi-closure.h \
-       pygi-ccallback.c \
-       pygi-ccallback.h \
-       pygi-util.c \
-       pygi-util.h \
-       pygi-property.c \
-       pygi-property.h \
-       pygi-signal-closure.c \
-       pygi-signal-closure.h \
-       pygi-invoke.c \
-       pygi-invoke.h \
-       pygi-invoke-state-struct.h \
-       pygi-cache.h \
-       pygi-cache.c \
-       pygi-marshal-cleanup.c \
-       pygi-marshal-cleanup.h \
-       pygi-basictype.c \
-       pygi-basictype.h \
-       pygi-list.c \
-       pygi-list.h \
-       pygi-array.c \
-       pygi-array.h \
-       pygi-error.c \
-       pygi-error.h \
-       pygi-object.c \
-       pygi-object.h \
-       pygi-value.c \
-       pygi-value.h \
-       pygi-enum-marshal.c \
-       pygi-enum-marshal.h \
-       pygi-struct-marshal.c \
-       pygi-struct-marshal.h \
-       pygi-hashtable.c \
-       pygi-hashtable.h
+include pygi-srcs.mak
+
+_gi_la_SOURCES = $(pygi_module_sources)
 _gi_la_CFLAGS = \
        $(CODE_COVERAGE_CFLAGS) \
        $(WARN_CFLAGS) \
@@ -144,8 +61,7 @@ if ENABLE_CAIRO
 pygi_LTLIBRARIES += _gi_cairo.la
 endif
 
-_gi_cairo_la_SOURCES = \
-       pygi-foreign-cairo.c
+_gi_cairo_la_SOURCES = $(pygi_cairo_module_sources)
 _gi_cairo_la_CFLAGS = \
        $(CODE_COVERAGE_CFLAGS) \
        $(WARN_CFLAGS) \
diff --git a/gi/pygi-srcs.mak b/gi/pygi-srcs.mak
new file mode 100644
index 0000000..59131ab
--- /dev/null
+++ b/gi/pygi-srcs.mak
@@ -0,0 +1,88 @@
+pygi_module_sources = \
+       gobjectmodule.c \
+       gobjectmodule.h \
+       pygboxed.c \
+       pygboxed.h \
+       pygenum.c \
+       pygenum.h \
+       pygflags.c \
+       pygflags.h \
+       pyginterface.c \
+       pyginterface.h \
+       pygobject.h \
+       pygobject-internal.h \
+       pygobject-object.c \
+       pygobject-object.h \
+       pygparamspec.c \
+       pygparamspec.h \
+       pygpointer.c \
+       pygpointer.h \
+       pygtype.c \
+       pygtype.h \
+       glibmodule.c \
+       pygoptioncontext.c \
+       pygoptioncontext.h \
+       pygoptiongroup.c \
+       pygoptiongroup.h \
+       pygspawn.c \
+       pygspawn.h \
+       pyglib.c \
+       pyglib.h \
+       pyglib-python-compat.h \
+       gimodule.c \
+       pygi-repository.c \
+       pygi-repository.h \
+       pygi-info.c \
+       pygi-info.h \
+       pygi-foreign.c \
+       pygi-foreign.h \
+       pygi-foreign-api.h \
+       pygi-struct.c \
+       pygi-struct.h \
+       pygi-source.c \
+       pygi-source.h \
+       pygi-argument.c \
+       pygi-argument.h \
+       pygi-resulttuple.c \
+       pygi-resulttuple.h \
+       pygi-type.c \
+       pygi-type.h \
+       pygi-boxed.c \
+       pygi-boxed.h \
+       pygi-closure.c \
+       pygi-closure.h \
+       pygi-ccallback.c \
+       pygi-ccallback.h \
+       pygi-util.c \
+       pygi-util.h \
+       pygi-property.c \
+       pygi-property.h \
+       pygi-signal-closure.c \
+       pygi-signal-closure.h \
+       pygi-invoke.c \
+       pygi-invoke.h \
+       pygi-invoke-state-struct.h \
+       pygi-cache.h \
+       pygi-cache.c \
+       pygi-marshal-cleanup.c \
+       pygi-marshal-cleanup.h \
+       pygi-basictype.c \
+       pygi-basictype.h \
+       pygi-list.c \
+       pygi-list.h \
+       pygi-array.c \
+       pygi-array.h \
+       pygi-error.c \
+       pygi-error.h \
+       pygi-object.c \
+       pygi-object.h \
+       pygi-value.c \
+       pygi-value.h \
+       pygi-enum-marshal.c \
+       pygi-enum-marshal.h \
+       pygi-struct-marshal.c \
+       pygi-struct-marshal.h \
+       pygi-hashtable.c \
+       pygi-hashtable.h
+
+pygi_cairo_module_sources = pygi-foreign-cairo.c
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 0da9ed9..92020ba 100755
--- a/setup.py
+++ b/setup.py
@@ -15,6 +15,11 @@ from setuptools import setup, Extension
 with open("configure.ac", "r") as h:
     version = ".".join(re.findall("pygobject_[^\s]+_version,\s*(\d+)\)", h.read()))
 
+if os.name == 'nt' and 'MSYSTEM' not in os.environ:
+    data_files = [('include/pygobject-3.0', ['gi/pygobject.h']),
+                  ('lib/pkgconfig', ['win32/pygobject-3.0.pc'])]
+else:
+    data_files = []
 
 def makedirs(dirpath):
     """Safely make directories
@@ -38,31 +43,57 @@ def makedirs(dirpath):
 
 class Build(orig_build):
     """Dummy version of distutils build which runs an Autotools build system
-    instead.
+    or NMake instead.
     """
+
     def run(self):
         srcdir = os.getcwd()
         builddir = os.path.join(srcdir, self.build_temp)
+        print(builddir)
         makedirs(builddir)
-        configure = os.path.join(srcdir, 'configure')
-
-        if not os.path.exists(configure):
-            configure = os.path.join(srcdir, 'autogen.sh')
-
-        subprocess.check_call([
-                configure,
-                'PYTHON=%s' % sys.executable,
-                # Put the documentation, etc. out of the way: we only want
-                # the Python code and extensions
-                '--prefix=' + os.path.join(builddir, 'prefix'),
-            ],
-            cwd=builddir)
-        make_args = [
-            'pythondir=%s' % os.path.join(srcdir, self.build_lib),
-            'pyexecdir=%s' % os.path.join(srcdir, self.build_lib),
-        ]
-        subprocess.check_call(['make', '-C', builddir] + make_args)
-        subprocess.check_call(['make', '-C', builddir, 'install'] + make_args)
+
+        if os.name == 'nt':
+            if 'MSYSTEM' in os.environ:
+                use_autotools = True
+            else:
+                use_autotools = False
+        else:
+            use_autotools = True
+
+        if use_autotools is True:
+            configure = os.path.join(srcdir, 'configure')
+
+            if not os.path.exists(configure):
+                configure = os.path.join(srcdir, 'autogen.sh')
+
+            subprocess.check_call([
+                    configure,
+                    'PYTHON=%s' % sys.executable,
+                    # Put the documentation, etc. out of the way: we only want
+                    # the Python code and extensions
+                    '--prefix=' + os.path.join(builddir, 'prefix'),
+                ],
+                cwd=builddir)
+            make_args = [
+                'pythondir=%s' % os.path.join(srcdir, self.build_lib),
+                'pyexecdir=%s' % os.path.join(srcdir, self.build_lib),
+            ]
+            subprocess.check_call(['make', '-C', builddir] + make_args)
+            subprocess.check_call(['make', '-C', builddir, 'install'] + make_args)
+
+        else:
+            os.chdir('win32')
+            subprocess.check_call(['nmake', '-f',
+                                   'Makefile.vc',
+                                   'CFG=release',
+                                   'PYTHON=%s' % sys.executable])
+            subprocess.check_call(['nmake', '-f',
+                                   'Makefile.vc',
+                                   'CFG=release',
+                                   'PYTHON=%s' % sys.executable,
+                                   'USE_SETUP_TOOLS=1',
+                                   'install'])
+            os.chdir('..')
 
 
 class BuildExt(orig_build_ext):
@@ -102,4 +133,5 @@ setup(
         'build_py': BuildPy,
         'build_ext': BuildExt,
     },
+    data_files = data_files,
 )
diff --git a/win32/Makefile.am b/win32/Makefile.am
new file mode 100644
index 0000000..963792b
--- /dev/null
+++ b/win32/Makefile.am
@@ -0,0 +1,17 @@
+EXTRA_DIST =                   \
+       build-rules-msvc.mak    \
+       config-msvc.mak         \
+       configpy.py             \
+       create-lists-msvc.mak   \
+       create-lists.bat        \
+       detectenv-msvc.mak      \
+       generate-msvc.mak       \
+       info-msvc.mak           \
+       install.mak             \
+       Makefile.vc             \
+       pc_base.py              \
+       pygobject-version.mak   \
+       pygobjectpc.py          \
+       pythonconfig.mak        \
+       README.txt              \
+       replace.py
diff --git a/win32/Makefile.vc b/win32/Makefile.vc
new file mode 100644
index 0000000..9317033
--- /dev/null
+++ b/win32/Makefile.vc
@@ -0,0 +1,44 @@
+# NMake Makefile for building PyGObject on Windows
+
+# The items below this line should not be changed, unless one is maintaining
+# the NMake Makefiles.  Customizations can be done in the following NMake Makefile
+# portions (please see comments in the these files to see what can be customized):
+#
+# detectenv-msvc.mak
+# config-msvc.mak
+
+!include detectenv-msvc.mak
+
+# Include the Makefile portions with the source listings
+!include ..\gi\pygi-srcs.mak
+
+!include pythonconfig.mak
+
+# Include the Makefile portion that enables features based on user input
+!include config-msvc.mak
+
+!if "$(VALID_CFGSET)" == "TRUE"
+
+# Include the Makefile portion to convert the source and header lists
+# into the lists we need for compilation and introspection
+!include create-lists-msvc.mak
+
+all: $(PYGI_MODULES) all-build-info
+
+#tests: all
+
+# Include the build rules for sources, DLLs and executables
+!include build-rules-msvc.mak
+
+# Include the rules for build directory creation and code generation
+!include generate-msvc.mak
+
+!include install.mak
+
+!else
+all: help
+       @echo You need to specify a valid configuration, via
+       @echo CFG=release or CFG=debug
+!endif
+
+!include info-msvc.mak
diff --git a/win32/README.txt b/win32/README.txt
new file mode 100644
index 0000000..b455800
--- /dev/null
+++ b/win32/README.txt
@@ -0,0 +1,82 @@
+Instructions for building PyGObject on Visual Studio
+====================================================
+Building PyGObject on Windows is now also supported using Visual Studio
+versions 2008 through 2015, in both 32-bit and 64-bit (x64) flavors, via NMake
+Makefiles and using setuptools/distutils (which, in turn, does the NMake build).
+
+You will need Python 2.7.x or Python 3.1+ to build this package,
+in addition to a full GLib and gobject-introspection build, preferably
+built with the same compiler that is used here to build PyGObject.
+The free-of-charge Express/Community editions of Visual Studio are
+supported as well.
+
+Since the official Windows installers for Python are built with
+Visual Studio, the following lists the recommended Visual Studio/Visual C++
+versions to be used for building PyGObject against the official Python/CPython
+installer packages from www.python.org:
+-Python 2.7.x/3.1.x/3.2.x: 2008
+-Python 3.3.x/3.4.x: 2010
+-Python 3.5.x/3.6.x: 2015
+
+Again, it is recommended
+that if you built your own Python from source, the compiler used to build
+Python should match the compiler that is being used here.
+
+The following are instructions for performing such a build, as there mainly
+two options that are needed for the build.  A 'clean' target is provided-it is
+recommended that one cleans the build and redo the build if any configuration
+option changed, as changes in the options can very well produce incompatible
+builds from the previous build, due to Release/Debug settings and Python version
+differences, since Python modules on Visual Studio builds will link implicitly
+to the Python library (pythonxx.dll/pythonxx_d.dll) that is used/specified
+during the build.
+
+Note that the build type and platform type (Win32/x64) of Python, GLib,
+GObject-Introspection and libffi (and Cairo/Cairo-GObject if the cairo module
+in this package is used) that is used in the builds must correspond to the build
+type and platform that the attempted build is targetting.  Note that the
+setuptools/distutils build only build the release build type.
+
+The build system will determine whether the cairo module in this package will
+be built based on:
+-The existence of the py2cairo modulein the Python-2.7.x or pycairo module
+ in the Python-3.1+ installation.
+-and-
+-The existence of the the pycairo.h (for Python 2.7.x) or py3cairo.h (for Python
+ 3.x) in the include\pycairo sub-directory in your Python installation.
+
+To successfully build the cairo module in this package, you will need both Cairo
+and Cairo-GObject.
+
+An 'install' target is also provided to copy the built items in their appropriate
+locations under
+$(srcroot)\build\lib.$(python_windows_platform)-$(python_version_series),
+which is described below, which then can be picked up by setuptools and/or
+setting PYTHONPATH to that output directory to test the build.  The 'install'
+target is also the one that will be in-turn invoked by running the
+setuptools/distutils-based build.
+
+Invoke the build by issuing the command:
+-in $(srcroot)/win32:
+nmake /f Makefile.vc CFG=[release|debug] PYTHON=<full path to python interpreter>
+
+-or in $(srcroot), release builds only-
+$(PYTHON) setup.py build, where $(PYTHON) is the full path to python interpreter,
+or just python if it is already in your PATH.
+
+where:
+
+CFG: Required for NMake builds.  Choose from a release or debug build.  Note that 
+     all builds generate a .pdb file for each .pyd built--this refers
+     to the C/C++ runtime that the build uses.  Note that release builds will
+     link to pythonxx.dll and debug builds will link to pythonxx_d.dll implicitly.
+
+PYTHON: Required unless the Python interpretor is in your PATH.  Specifying this
+        will override the interpreter that is in your PATH.
+
+PREFIX: Optional for overriding the default prefix, $(srcroot)\vs$(VSVER)\$(PLAT)
+        if needed.  GLib, g-i and cairo headers and libraries will be searched
+        first in $(PREFIX)\include and $(PREFIX)\lib respectively before searching
+        in the directories in %INCLUDE% and %LIB%.  Python headers and libraries
+        will be searched in the directories that are deduced based on the interpreter
+        used.
diff --git a/win32/build-rules-msvc.mak b/win32/build-rules-msvc.mak
new file mode 100644
index 0000000..a2ccc09
--- /dev/null
+++ b/win32/build-rules-msvc.mak
@@ -0,0 +1,60 @@
+# NMake Makefile portion for compilation rules
+# Items in here should not need to be edited unless
+# one is maintaining the NMake build files.  The format
+# of NMake Makefiles here are different from the GNU
+# Makefiles.  Please see the comments about these formats.
+
+# Inference rules for compiling the .obj files.
+# Used for libs and programs with more than a single source file.
+# Format is as follows
+# (all dirs must have a trailing '\'):
+#
+# {$(srcdir)}.$(srcext){$(destdir)}.obj::
+#      $(CC)|$(CXX) $(cflags) /Fo$(destdir) /c @<<
+# $<
+# <<
+{..\gi\}.c{..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\}.obj::
+       $(CC) $(CFLAGS) $(PYGI_DEFINES) $(PYGI_CFLAGS) /Fo..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\ /c 
@<<
+$<
+<<
+
+# Inference rules for building the test programs
+# Used for programs with a single source file.
+# Format is as follows
+# (all dirs must have a trailing '\'):
+#
+# {$(srcdir)}.$(srcext){$(destdir)}.exe::
+#      $(CC)|$(CXX) $(cflags) $< /Fo$*.obj  /Fe$@ [/link $(linker_flags) $(dep_libs)]< /Fo$*.obj /Fe$@ /link 
$(LDFLAGS) $(CFG)\$(PLAT)\deplib.lib $(TEST_DEP_LIBS)
+
+# Rules for linking DLLs
+# Format is as follows (the mt command is needed for MSVC 2005/2008 builds):
+# $(dll_name_with_path): $(dependent_libs_files_objects_and_items)
+#      link /DLL [$(linker_flags)] [$(dependent_libs)] [/def:$(def_file_if_used)] 
[/implib:$(lib_name_if_needed)] -out:$@ @<<
+# $(dependent_objects)
+# <<
+#      @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2
+..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\_gi.pyd: ..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT) 
$(gi_pyd_OBJS) ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi
+       link /DLL $(PYGI_LDFLAGS) $(PYGI_DEP_LIBS) -out:$@ 
-implib:..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\$(@B).lib @<<
+$(gi_pyd_OBJS)
+<<
+       @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2
+       @-if exist $@.manifest del $@.manifest
+
+..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\_gi_cairo.pyd: 
..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT) $(gi_cairo_pyd_OBJS) 
..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi
+       link /DLL $(PYGI_LDFLAGS) $(PYGI_DEP_LIBS) $(PYGI_CAIRO_DEP_LIBS) -out:$@ 
-implib:..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\$(@B).lib @<<
+$(gi_cairo_pyd_OBJS)
+<<
+       @-if exist $@.manifest mt /manifest $@.manifest /outputresource:$@;2
+       @-if exist $@.manifest del $@.manifest
+
+clean:
+       @-del /f /q ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\*.pdb
+       @-del /f /q ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\*.pyd
+       @-del /f /q ..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\*.ilk
+       @-del /f /q ..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\*.obj
+       @-rmdir /s /q ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)
+       @-rmdir /s /q ..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)
+       @if exist __pycache__ rmdir /s /q __pycache__
+       @-del /f /q *.pyc
+       @-del /f /q pygobject-3.0.pc
+       @-del /f /q vc$(VSVER)0.pdb
diff --git a/win32/config-msvc.mak b/win32/config-msvc.mak
new file mode 100644
index 0000000..b0cf6bd
--- /dev/null
+++ b/win32/config-msvc.mak
@@ -0,0 +1,68 @@
+# NMake Makefile portion for enabling features for Windows builds
+
+# You may change these lines to customize the .lib files that will be linked to
+
+# gobject-introspection, GLib and libffi are required for everything
+PYGI_DEP_LIBS = girepository-1.0.lib gobject-2.0.lib glib-2.0.lib libffi.lib
+PYGI_CAIRO_DEP_LIBS = cairo-gobject.lib cairo.lib
+
+# Please do not change anything beneath this line unless maintaining the NMake Makefiles
+
+!if "$(PLAT)" == "x64"
+PYTHON_PLAT = win-amd64
+!else
+PYTHON_PLAT = win32
+!endif
+
+!if "$(PYCAIRO)" == "1"
+!if ![echo PYCAIRO_CONFIG= > pycairoconfig.mak]
+!endif
+
+!if "$(PYTHONMAJ)" == "2"
+!if ![if exist $(PYTHONPREFIX)\include\pycairo\pycairo.h echo HAVE_PYCAIRO=1 >> pycairoconfig.mak]
+!endif
+!else
+!if ![if exist $(PYTHONPREFIX)\include\pycairo\py3cairo.h echo HAVE_PYCAIRO=1 >> pycairoconfig.mak]
+!endif
+!endif
+
+!include pycairoconfig.mak
+
+!if ![del /f pycairoconfig.mak]
+!endif
+!endif
+
+!include pygobject-version.mak
+
+PYGI_DEFINES =                                         \
+       /DPY_SSIZE_T_CLEAN                              \
+       /DPYGOBJECT_MAJOR_VERSION=$(PYGI_MAJOR_VERSION) \
+       /DPYGOBJECT_MINOR_VERSION=$(PYGI_MINOR_VERSION) \
+       /DPYGOBJECT_MICRO_VERSION=$(PYGI_MICRO_VERSION)
+
+PYGI_CFLAGS =                          \
+       /I..\gi                         \
+       /I$(PREFIX)\include             \
+       /I$(PYTHONPREFIX)\include
+
+PYGI_LDFLAGS =                                         \
+       $(LDFLAGS)                                              \
+       /libpath:$(PYTHONPREFIX)\libs
+
+!if "$(HAVE_PYCAIRO)" == "1"
+PYGI_CFLAGS = $(PYGI_CFLAGS) /I$(PYTHONPREFIX)\include\pycairo
+!endif
+
+!if "$(ADDITIONAL_LIB_DIR)" != ""
+PYGI_LDFLAGS = /libpath:$(ADDITIONAL_LIB_DIR) $(PYGI_LDFLAGS)
+!endif
+
+PYGI_SOURCES = $(pygi_module_sources)
+PYGI_CAIRO_SOURCES = $(pygi_cairo_module_sources)
+
+# We build the PyGI module at least
+PYGI_MODULES = ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\_gi.pyd
+
+!if "$(HAVE_PYCAIRO)" == "1"
+PYGI_MODULES = $(PYGI_MODULES) ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\_gi_cairo.pyd
+!endif
diff --git a/win32/configpy.py b/win32/configpy.py
new file mode 100644
index 0000000..4361dd8
--- /dev/null
+++ b/win32/configpy.py
@@ -0,0 +1,24 @@
+# Find out configuration of Python installation
+import sys
+import platform
+
+def configpy():
+    confignmake = open('configpy.mak', 'w')
+    pyver = platform.python_version().split('.')
+    compiler_details = platform.python_compiler().split()
+    compiler_ver = compiler_details[1][2:compiler_details[1].find('00')]
+
+    confignmake.write('PYTHONPREFIX=%s\n' % sys.prefix)
+    confignmake.write('PYTHONMAJ=%s\n' % pyver[0])
+    confignmake.write('PYTHONSERIESDOT=%s.%s\n' % (pyver[0], pyver[1]))
+    confignmake.write('PYTHONCOMPILER=%s\n' % compiler_details[0])
+    confignmake.write('PYTHONCOMPILERVER=%s\n' % compiler_ver)
+    try:
+        import cairo
+        confignmake.write('PYCAIRO=1')
+    except ImportError:
+        confignmake.write('PYCAIRO=')
+    confignmake.close()
+
+if __name__ == '__main__':
+    configpy()
\ No newline at end of file
diff --git a/win32/create-lists-msvc.mak b/win32/create-lists-msvc.mak
new file mode 100644
index 0000000..a737d43
--- /dev/null
+++ b/win32/create-lists-msvc.mak
@@ -0,0 +1,61 @@
+# Convert the source listing to object (.obj) listing in
+# another NMake Makefile module, include it, and clean it up.
+# This is a "fact-of-life" regarding NMake Makefiles...
+# This file does not need to be changed unless one is maintaining the NMake Makefiles
+
+# For those wanting to add things here:
+# To add a list, do the following:
+# # $(description_of_list)
+# if [call create-lists.bat header $(makefile_snippet_file) $(variable_name)]
+# endif
+#
+# if [call create-lists.bat file $(makefile_snippet_file) $(file_name)]
+# endif
+#
+# if [call create-lists.bat footer $(makefile_snippet_file)]
+# endif
+# ... (repeat the if [call ...] lines in the above order if needed)
+# !include $(makefile_snippet_file)
+#
+# (add the following after checking the entries in $(makefile_snippet_file) is correct)
+# (the batch script appends to $(makefile_snippet_file), you will need to clear the file unless the 
following line is added)
+#!if [del /f /q $(makefile_snippet_file)]
+#!endif
+
+# In order to obtain the .obj filename that is needed for NMake Makefiles to build DLLs/static LIBs or EXEs, 
do the following
+# instead when doing 'if [call create-lists.bat file $(makefile_snippet_file) $(file_name)]'
+# (repeat if there are multiple $(srcext)'s in $(source_list), ignore any headers):
+# !if [for %c in ($(source_list)) do @if "%~xc" == ".$(srcext)" @call create-lists.bat file 
$(makefile_snippet_file) $(intdir)\%~nc.obj]
+#
+# $(intdir)\%~nc.obj needs to correspond to the rules added in build-rules-msvc.mak
+# %~xc gives the file extension of a given file, %c in this case, so if %c is a.cc, %~xc means .cc
+# %~nc gives the file name of a given file without extension, %c in this case, so if %c is a.cc, %~nc means a
+
+NULL=
+
+# For PyGI
+!if [call create-lists.bat header gi_pyd_objs.mak gi_pyd_OBJS]
+!endif
+
+!if [for %c in ($(PYGI_SOURCES)) do @if "%~xc" == ".c" @call create-lists.bat file gi_pyd_objs.mak 
..\build\temp.^$(PYTHON_PLAT)-^$(PYTHONSERIESDOT)\%~nc.obj]
+!endif
+
+!if [call create-lists.bat footer gi_pyd_objs.mak]
+!endif
+
+!if "$(HAVE_PYCAIRO)" == "1"
+!if [call create-lists.bat header gi_pyd_objs.mak gi_cairo_pyd_OBJS]
+!endif
+
+!if [for %c in ($(PYGI_CAIRO_SOURCES)) do @if "%~xc" == ".c" @call create-lists.bat file gi_pyd_objs.mak 
..\build\temp.^$(PYTHON_PLAT)-^$(PYTHONSERIESDOT)\%~nc.obj]
+!endif
+
+!if [call create-lists.bat footer gi_pyd_objs.mak]
+!endif
+
+!endif
+
+!include gi_pyd_objs.mak
+
+!if [del /f /q gi_pyd_objs.mak]
+!endif
\ No newline at end of file
diff --git a/win32/create-lists.bat b/win32/create-lists.bat
new file mode 100644
index 0000000..ef60d5c
--- /dev/null
+++ b/win32/create-lists.bat
@@ -0,0 +1,42 @@
+@echo off
+rem Simple .bat script for creating the NMake Makefile snippets.
+
+if not "%1" == "header" if not "%1" == "file" if not "%1" == "footer" goto :error_cmd
+if "%2" == "" goto error_no_destfile
+
+if "%1" == "header" goto :header
+if "%1" == "file" goto :addfile
+if "%1" == "footer" goto :footer
+
+:header
+if "%3" == "" goto error_var
+echo %3 =      \>>%2
+goto done
+
+:addfile
+if "%3" == "" goto error_file
+echo.  %3      \>>%2
+goto done
+
+:footer
+echo.  $(NULL)>>%2
+echo.>>%2
+goto done
+
+:error_cmd
+echo Specified command '%1' was invalid.  Valid commands are: header file footer.
+goto done
+
+:error_no_destfile
+echo Destination NMake snippet file must be specified
+goto done
+
+:error_var
+echo A name must be specified for using '%1'.
+goto done
+
+:error_file
+echo A file must be specified for using '%1'.
+goto done
+
+:done
\ No newline at end of file
diff --git a/win32/detectenv-msvc.mak b/win32/detectenv-msvc.mak
new file mode 100644
index 0000000..7a6c047
--- /dev/null
+++ b/win32/detectenv-msvc.mak
@@ -0,0 +1,136 @@
+# Change this (or specify PREFIX= when invoking this NMake Makefile) if
+# necessary, so that the libs and headers of the dependent third-party
+# libraries can be located.  For instance, if building from GLib's
+# included Visual Studio projects, this should be able to locate the GLib
+# build out-of-the-box if they were not moved.  GLib's headers will be
+# found in $(GLIB_PREFIX)\include\glib-2.0 and
+# $(GLIB_PREFIX)\lib\glib-2.0\include and its import library will be found
+# in $(GLIB_PREFIX)\lib.
+
+!if "$(PREFIX)" == ""
+PREFIX = ..\..\vs$(VSVER)\$(PLAT)
+!endif
+
+# Location of the PERL interpretor, for running glib-mkenums.  glib-mkenums
+# needs to be found in $(PREFIX)\bin.  Using either a 32-bit or x64 PERL
+# interpretor are supported for either a 32-bit or x64 build.
+
+!if "$(PERL)" == ""
+PERL = perl
+!endif
+
+# Location of the Python interpretor, for building introspection.  The complete set
+# of Python Modules for introspection (the giscanner Python scripts and the _giscanner.pyd
+# compiled module) needs to be found in $(PREFIX)\lib\gobject-introspection\giscanner, and
+# the g-ir-scanner Python script and g-ir-compiler utility program needs to be found
+# in $(PREFIX)\bin, together with any DLLs they will depend on, if those DLLs are not already
+# in your PATH.
+# Note that the Python interpretor and the introspection modules and utility progam must
+# correspond to the build type (i.e. 32-bit Release for 32-bit Release builds, and so on).
+#
+# For introspection, currently only Python 2.7.x is supported.  This may change when Python 3.x
+# support is added upstream in gobject-introspection--when this happens, the _giscanner.pyd must
+# be the one that is built against the release series of Python that is used here.
+
+!if "$(PYTHON)" == ""
+PYTHON = python
+!endif
+
+# Location of the pkg-config utility program, for building introspection.  It needs to be able
+# to find the pkg-config (.pc) files so that the correct libraries and headers for the needed libraries
+# can be located, using PKG_CONFIG_PATH.  Using either a 32-bit or x64 pkg-config are supported for
+# either a 32-bit or x64 build.
+
+!if "$(PKG_CONFIG)" == ""
+PKG_CONFIG = pkg-config
+!endif
+
+# The items below this line should not be changed, unless one is maintaining
+# the NMake Makefiles.  The exception is for the CFLAGS_ADD line(s) where one
+# could use his/her desired compiler optimization flags, if he/she knows what is
+# being done.
+
+# Check to see we are configured to build with MSVC (MSDEVDIR, MSVCDIR or
+# VCINSTALLDIR) or with the MS Platform SDK (MSSDK or WindowsSDKDir)
+!if !defined(VCINSTALLDIR) && !defined(WINDOWSSDKDIR)
+MSG = ^
+This Makefile is only for Visual Studio 2008 and later.^
+You need to ensure that the Visual Studio Environment is properly set up^
+before running this Makefile.
+!error $(MSG)
+!endif
+
+ERRNUL  = 2>NUL
+_HASH=^#
+
+!if ![echo VCVERSION=_MSC_VER > vercl.x] \
+    && ![echo $(_HASH)if defined(_M_IX86) >> vercl.x] \
+    && ![echo PLAT=Win32 >> vercl.x] \
+    && ![echo $(_HASH)elif defined(_M_AMD64) >> vercl.x] \
+    && ![echo PLAT=x64 >> vercl.x] \
+    && ![echo $(_HASH)endif >> vercl.x] \
+    && ![cl -nologo -TC -P vercl.x $(ERRNUL)]
+!include vercl.i
+!if ![echo VCVER= ^\> vercl.vc] \
+    && ![set /a $(VCVERSION) / 100 - 6 >> vercl.vc]
+!include vercl.vc
+!endif
+!endif
+!if ![del $(ERRNUL) /q/f vercl.x vercl.i vercl.vc]
+!endif
+
+!if $(VCVERSION) > 1499 && $(VCVERSION) < 1600
+VSVER = 9
+!elseif $(VCVERSION) > 1599 && $(VCVERSION) < 1700
+VSVER = 10
+!elseif $(VCVERSION) > 1699 && $(VCVERSION) < 1800
+VSVER = 11
+!elseif $(VCVERSION) > 1799 && $(VCVERSION) < 1900
+VSVER = 12
+!elseif $(VCVERSION) > 1899 && $(VCVERSION) < 2000
+VSVER = 14
+!else
+VSVER = 0
+!endif
+
+!if "$(VSVER)" == "0"
+MSG = ^
+This NMake Makefile set supports Visual Studio^
+9 (2008) through 14 (2015).  Your Visual Studio^
+version is not supported.
+!error $(MSG)
+!endif
+
+VALID_CFGSET = FALSE
+!if "$(CFG)" == "release" || "$(CFG)" == "Release" || "$(CFG)" == "debug" || "$(CFG)" == "Debug"
+VALID_CFGSET = TRUE
+!endif
+
+# One may change these items, but be sure to test
+# the resulting binaries
+!if "$(CFG)" == "release" || "$(CFG)" == "Release"
+CFLAGS_ADD = /MD /O2 /GL /MP
+!if "$(VSVER)" != "9"
+CFLAGS_ADD = $(CFLAGS_ADD) /d2Zi+
+!endif
+!else
+CFLAGS_ADD = /MDd /Od
+!endif
+
+!if "$(PLAT)" == "x64"
+LDFLAGS_ARCH = /machine:x64
+!else
+LDFLAGS_ARCH = /machine:x86
+!endif
+
+!if "$(VALID_CFGSET)" == "TRUE"
+CFLAGS = $(CFLAGS_ADD) /W3 /Zi
+
+LDFLAGS_BASE = $(LDFLAGS_ARCH) /libpath:$(PREFIX)\lib /DEBUG
+
+!if "$(CFG)" == "debug" || "$(CFG)" == "Debug"
+LDFLAGS = $(LDFLAGS_BASE)
+!else
+LDFLAGS = $(LDFLAGS_BASE) /opt:ref /LTCG
+!endif
+!endif
diff --git a/win32/generate-msvc.mak b/win32/generate-msvc.mak
new file mode 100644
index 0000000..3f38db0
--- /dev/null
+++ b/win32/generate-msvc.mak
@@ -0,0 +1,8 @@
+# NMake Makefile portion for code generation and
+# intermediate build directory creation
+# Items in here should not need to be edited unless
+# one is maintaining the NMake build files.
+
+# Create the build directories
+..\build\temp.$(PYTHON_PLAT)-$(PYTHONSERIESDOT) ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi:
+       @-mkdir $@
\ No newline at end of file
diff --git a/win32/info-msvc.mak b/win32/info-msvc.mak
new file mode 100644
index 0000000..3b8e175
--- /dev/null
+++ b/win32/info-msvc.mak
@@ -0,0 +1,76 @@
+# NMake Makefile portion for displaying config info
+
+WITH_CAIRO = no
+
+!if "$(HAVE_PYCAIRO)" == "1"
+WITH_CAIRO = yes
+!endif
+
+!if "$(PYTHONCOMPILER)" != "MSC"
+WARN_MESSAGE=WARNING: Your Python installation is not built with Visual Studio
+!else
+!if "$(PYTHONCOMPILERVER)" == "15"
+PYMSCVER = 9
+!elseif "$(PYTHONCOMPILERVER)" == "16"
+PYMSCVER = 10
+!elseif "$(PYTHONCOMPILERVER)" == "17"
+PYMSCVER = 11
+!elseif "$(PYTHONCOMPILERVER)" == "18"
+PYMSCVER = 12
+!elseif "$(PYTHONCOMPILERVER)" == "19"
+PYMSCVER = 14
+!endif
+
+!if "$(VSVER)" == "$(PYMSCVER)"
+WARN_MESSAGE=No compiler version related warnings
+!else
+WARN_MESSAGE=WARNING: You are building PyGObject using vs$(VSVER) but Python is built with vs$(PYMSCVER).
+!endif
+!endif
+
+
+
+build-info-pygobject:
+       @echo.
+       @echo ===========================
+       @echo Configuration for PyGObject
+       @echo ===========================
+       @echo Build Type: $(CFG)
+       @echo Python Version Series: $(PYTHONSERIESDOT)
+       @echo Cairo Support: $(WITH_CAIRO)
+       @echo $(WARN_MESSAGE)
+
+all-build-info: build-info-pygobject
+
+help:
+       @echo.
+       @echo =============================
+       @echo Building PyGObject Using NMake
+       @echo =============================
+       @echo nmake /f Makefile.vc CFG=[release^|debug] ^<PREFIX=PATH^> ^<PYTHON=PATH^>
+       @echo.
+       @echo Where:
+       @echo ------
+       @echo CFG: Required, use CFG=release for an optimized build and CFG=debug
+       @echo for a debug build.  PDB files are generated for all builds.
+       @echo.
+       @echo PYTHON: Required, unless python.exe is already in your PATH.
+       @echo set to ^$(FULL_PATH_TO_PYTHON_INTERPRETOR).
+       @echo.
+       @echo PREFIX: Optional, the path where dependent libraries and tools may be
+       @echo found, default is ^$(srcrootdir)\..\vs^$(short_vs_ver)\^$(platform),
+       @echo where ^$(short_vs_ver) is 9 for VS 2008, 10 for VS 2010 and so on; and
+       @echo ^$(platform) is Win32 for 32-bit builds and x64 for x64 builds.
+       @echo ======
+       @echo A 'clean' target is supported to remove all generated files, intermediate
+       @echo object files and binaries for the specified configuration.
+       @echo.
+       @echo A 'tests' target is supported to build the test programs, use after building
+       @echo the main PyGObject Python Module.
+       @echo.
+       @echo An 'install' target is supported to copy the build to appropriate
+       @echo locations under ^$(srcroot)\build\ for preparation for packaging and/or
+       @echo testing by setting PYTHONPATH.
+       @echo ======
+       @echo.
+       
diff --git a/win32/install.mak b/win32/install.mak
new file mode 100644
index 0000000..64bd865
--- /dev/null
+++ b/win32/install.mak
@@ -0,0 +1,26 @@
+# NMake Makefile snippet for copying the built modules to
+# prepare for packaging
+
+!if "$(USE_SETUP_TOOLS)" == ""
+PYGOBJECT_PREFIX = $(PREFIX)
+PYGOBJECT_LIBDIR = $(PREFIX)\lib
+!else
+PYGOBJECT_PREFIX = $(PYTHONPREFIX)
+PYGOBJECT_LIBDIR = $(PYTHONPREFIX)\libs
+!endif
+
+PYGOBJECT_HEADER_DIR = $(PYGOBJECT_PREFIX)\include\pygobject-3.0
+PYGOBJECT_PKGC_DIR = $(PYGOBJECT_PREFIX)\lib\pkgconfig
+
+pygobject-3.0.pc: ..\pygobject-3.0.pc.in
+       @$(PYTHON) pygobjectpc.py --prefix=$(PYGOBJECT_PREFIX) --libdir=$(PYGOBJECT_LIBDIR) 
--version=$(PYGI_MAJOR_VERSION).$(PYGI_MINOR_VERSION).$(PYGI_MICRO_VERSION)
+
+install: prep-package pygobject-3.0.pc all-build-info
+
+prep-package: $(PYGI_MODULES)
+       @for /f %d in ('dir /b /ad ..\gi') do   \
+       @(if not exist ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\%d mkdir 
..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\%d) & \
+       @(copy ..\gi\%d\*.py ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi\%d\)
+       @copy ..\gi\*.py ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\gi
+       @-mkdir ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\pygtkcompat
+       @copy ..\pygtkcompat\*.py ..\build\lib.$(PYTHON_PLAT)-$(PYTHONSERIESDOT)\pygtkcompat
diff --git a/win32/pc_base.py b/win32/pc_base.py
new file mode 100644
index 0000000..285b6cd
--- /dev/null
+++ b/win32/pc_base.py
@@ -0,0 +1,124 @@
+#!/usr/bin/python
+#
+# Simple utility script to generate the basic info
+# needed in a .pc (pkg-config) file, used especially
+# for introspection purposes
+
+# This can be used in various projects where
+# there is the need to generate .pc files,
+# and is copied from GLib's $(srcroot)/build/win32
+
+# Author: Fan, Chun-wei
+# Date: March 10, 2016
+
+import os
+import sys
+import argparse
+
+class BasePCItems:
+    def __init__(self):
+        self.base_replace_items = {}
+        self.exec_prefix = ''
+        self.includedir = ''
+        self.libdir = ''
+        self.prefix = ''
+        self.srcdir = os.path.dirname(__file__)
+        self.top_srcdir = self.srcdir + '\\..'
+        self.version = ''
+
+    def setup(self, argv, parser=None):
+        if parser is None:
+            parser = argparse.ArgumentParser(description='Setup basic .pc file info')
+        parser.add_argument('--prefix', help='prefix of the installed library',
+                            required=True)
+        parser.add_argument('--exec-prefix',
+                            help='prefix of the installed programs, \
+                                  if different from the prefix')
+        parser.add_argument('--includedir',
+                            help='includedir of the installed library, \
+                                  if different from ${prefix}/include')
+        parser.add_argument('--libdir',
+                            help='libdir of the installed library, \
+                                  if different from ${prefix}/lib')
+        parser.add_argument('--version', help='Version of the package',
+                            required=True)
+        args = parser.parse_args()
+
+        self.version = args.version
+
+        # check whether the prefix and exec_prefix are valid
+        if not os.path.exists(args.prefix):
+            raise SystemExit('Specified prefix \'%s\' is invalid' % args.prefix)
+
+        # use absolute paths for prefix
+        self.prefix = os.path.abspath(args.prefix).replace('\\','/')
+
+        # check and setup the exec_prefix
+        if getattr(args, 'exec_prefix', None) is None:
+            exec_prefix_use_shorthand = True
+            self.exec_prefix = '${prefix}'
+        else:
+            if args.exec_prefix.startswith('${prefix}'):
+                exec_prefix_use_shorthand = True
+                input_exec_prefix = args.prefix + args.exec_prefix[len('${prefix}'):]
+            else:
+                exec_prefix_use_shorthand = False
+                input_exec_prefix = args.exec_prefix
+            if not os.path.exists(input_exec_prefix):
+                raise SystemExit('Specified exec_prefix \'%s\' is invalid' %
+                                  args.exec_prefix)
+            if exec_prefix_use_shorthand is True:
+                self.exec_prefix = args.exec_prefix.replace('\\','/')
+            else:
+                self.exec_prefix = os.path.abspath(input_exec_prefix).replace('\\','/')
+
+        # check and setup the includedir
+        if getattr(args, 'includedir', None) is None:
+            self.includedir = '${prefix}/include'
+        else:
+            if args.includedir.startswith('${prefix}'):
+                includedir_use_shorthand = True
+                input_includedir = args.prefix + args.includedir[len('${prefix}'):]
+            else:
+                if args.includedir.startswith('${exec_prefix}'):
+                    includedir_use_shorthand = True
+                    input_includedir = input_exec_prefix + args.includedir[len('${exec_prefix}'):]
+                else:
+                    includedir_use_shorthand = False
+                    input_includedir = args.includedir
+            if not os.path.exists(input_includedir):
+                raise SystemExit('Specified includedir \'%s\' is invalid' %
+                                  args.includedir)
+            if includedir_use_shorthand is True:
+                self.includedir = args.includedir.replace('\\','/')
+            else:
+                self.includedir = os.path.abspath(input_includedir).replace('\\','/')
+
+        # check and setup the libdir
+        if getattr(args, 'libdir', None) is None:
+            self.libdir = '${prefix}/lib'
+        else:
+            if args.libdir.startswith('${prefix}'):
+                libdir_use_shorthand = True
+                input_libdir = args.prefix + args.libdir[len('${prefix}'):]
+            else:
+                if args.libdir.startswith('${exec_prefix}'):
+                    libdir_use_shorthand = True
+                    input_libdir = input_exec_prefix + args.libdir[len('${exec_prefix}'):]
+                else:
+                    libdir_use_shorthand = False
+                    input_libdir = args.libdir
+            if not os.path.exists(input_libdir):
+                raise SystemExit('Specified libdir \'%s\' is invalid' %
+                                             args.libdir)
+            if libdir_use_shorthand is True:
+                self.libdir = args.libdir.replace('\\','/')
+            else:
+                self.libdir = os.path.abspath(input_libdir).replace('\\','/')
+
+        # setup dictionary for replacing items in *.pc.in
+        self.base_replace_items.update({'@VERSION@': self.version})
+        self.base_replace_items.update({'@prefix@': self.prefix})
+        self.base_replace_items.update({'@exec_prefix@': self.exec_prefix})
+        self.base_replace_items.update({'@libdir@': self.libdir})
+        self.base_replace_items.update({'@includedir@': self.includedir})
diff --git a/win32/pygobject-version.mak.in b/win32/pygobject-version.mak.in
new file mode 100644
index 0000000..ada8d0f
--- /dev/null
+++ b/win32/pygobject-version.mak.in
@@ -0,0 +1,5 @@
+# Version info for PyGObject
+
+PYGI_MAJOR_VERSION=@PYGOBJECT_MAJOR_VERSION@
+PYGI_MINOR_VERSION=@PYGOBJECT_MINOR_VERSION@
+PYGI_MICRO_VERSION=@PYGOBJECT_MICRO_VERSION@
diff --git a/win32/pygobjectpc.py b/win32/pygobjectpc.py
new file mode 100644
index 0000000..b993fd4
--- /dev/null
+++ b/win32/pygobjectpc.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python
+#
+# Utility script to generate .pc files for GLib
+# for Visual Studio builds, to be used for
+# building introspection files
+
+# Author: Fan, Chun-wei
+# Date: March 10, 2016
+
+import os
+import sys
+
+from replace import replace_multi
+from pc_base import BasePCItems
+
+def main(argv):
+    base_pc = BasePCItems()
+    
+    base_pc.setup(argv)
+    pkg_replace_items = {'@datadir@': '${prefix}/share/pygobject-3.0',
+                         '@datarootdir@': '${prefix}/share',
+                         '@LIBFFI_PC@': ''}
+
+    pkg_replace_items.update(base_pc.base_replace_items)
+
+    # Generate ..\pygobject-3.0.pc
+    replace_multi(base_pc.top_srcdir + '/pygobject-3.0.pc.in',
+                  base_pc.srcdir + '/pygobject-3.0.pc',
+                  pkg_replace_items)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))
diff --git a/win32/pythonconfig.mak b/win32/pythonconfig.mak
new file mode 100644
index 0000000..980ab65
--- /dev/null
+++ b/win32/pythonconfig.mak
@@ -0,0 +1,15 @@
+!if ![$(PYTHON) configpy.py]
+!endif
+
+!if !exists(configpy.mak)
+!error The path '$(PYTHON)' specified for PYTHON is invalid.
+!endif
+
+!include configpy.mak
+
+!if "$(PYTHONPREFIX)" == ""
+!error The path '$(PYTHON)' specified for PYTHON is not a valid Python installation.
+!endif
+
+!if ![del /f configpy.mak]
+!endif
diff --git a/win32/replace.py b/win32/replace.py
new file mode 100644
index 0000000..a81bab9
--- /dev/null
+++ b/win32/replace.py
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+#
+# Simple utility script to manipulate
+# certain types of strings in a file
+
+# This can be used in various projects where
+# there is the need to replace strings in files,
+# and is copied from GLib's $(srcroot)/build/win32
+
+# Author: Fan, Chun-wei
+# Date: September 03, 2014
+
+import os
+import sys
+import re
+import string
+import argparse
+
+valid_actions = ['remove-prefix',
+                 'replace-var',
+                 'replace-str',
+                 'remove-str']
+
+def replace_multi(src, dest, replace_items):
+    with open(src, 'r') as s:
+        with open(dest, 'w') as d:
+            for line in s:
+                replace_dict = dict((re.escape(key), value) \
+                               for key, value in replace_items.items())
+                replace_pattern = re.compile("|".join(replace_dict.keys()))
+                d.write(replace_pattern.sub(lambda m: \
+                        replace_dict[re.escape(m.group(0))], line))
+
+def replace(src, dest, instring, outstring):
+    replace_item = {instring: outstring}
+    replace_multi(src, dest, replace_item)
+
+def check_required_args(args, params):
+    for param in params:
+        if getattr(args, param, None) is None:
+            raise SystemExit('%s: error: --%s argument is required' % (__file__, param))
+
+def warn_ignored_args(args, params):
+    for param in params:
+        if getattr(args, param, None) is not None:
+            print('%s: warning: --%s argument is ignored' % (__file__, param))
+
+def main(argv):
+
+    parser = argparse.ArgumentParser(description='Process strings in a file.')
+    parser.add_argument('-a',
+                        '--action',
+                        help='Action to carry out.  Can be one of:\n'
+                             'remove-prefix\n'
+                             'replace-var\n'
+                             'replace-str\n'
+                             'remove-str',
+                        choices=valid_actions)
+    parser.add_argument('-i', '--input', help='Input file')
+    parser.add_argument('-o', '--output', help='Output file')
+    parser.add_argument('--instring', help='String to replace or remove')
+    parser.add_argument('--var', help='Autotools variable name to replace')
+    parser.add_argument('--outstring',
+                        help='New String to replace specified string or variable')
+    parser.add_argument('--removeprefix', help='Prefix of string to remove')
+
+    args = parser.parse_args()
+
+    input_string = ''
+    output_string = ''
+
+    # We must have action, input, output for all operations
+    check_required_args(args, ['action','input','output'])
+
+    # Build the arguments by the operation that is to be done,
+    # to be fed into replace()
+
+    # Get rid of prefixes from a string
+    if args.action == 'remove-prefix':
+        check_required_args(args, ['instring','removeprefix'])
+        warn_ignored_args(args, ['outstring','var'])
+        input_string = args.removeprefix + args.instring
+        output_string = args.instring
+
+    # Replace an m4-style variable (those surrounded by @...@)
+    if args.action == 'replace-var':
+        check_required_args(args, ['var','outstring'])
+        warn_ignored_args(args, ['instring','removeprefix'])
+        input_string = '@' + args.var + '@'
+        output_string = args.outstring
+
+    # Replace a string
+    if args.action == 'replace-str':
+        check_required_args(args, ['instring','outstring'])
+        warn_ignored_args(args, ['var','removeprefix'])
+        input_string = args.instring
+        output_string = args.outstring
+
+    # Remove a string
+    if args.action == 'remove-str':
+        check_required_args(args, ['instring'])
+        warn_ignored_args(args, ['var','outstring','removeprefix'])
+        input_string = args.instring
+        output_string = ''
+
+    replace(args.input, args.output, input_string, output_string)
+
+if __name__ == '__main__':
+    sys.exit(main(sys.argv))



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]