[920] | 1 | diff --git a/py2exe/distutils_buildexe.py b/py2exe/distutils_buildexe.py
|
---|
| 2 | index ae8aca3..d809641 100644
|
---|
| 3 | --- a/py2exe/distutils_buildexe.py
|
---|
| 4 | +++ b/py2exe/distutils_buildexe.py
|
---|
| 5 | @@ -154,6 +154,7 @@ class py2exe(Command):
|
---|
| 6 | self.ascii = 0
|
---|
| 7 | self.custom_boot_script = None
|
---|
| 8 | self.use_assembly = False
|
---|
| 9 | + self.gi_namespaces = []
|
---|
| 10 |
|
---|
| 11 | def finalize_options (self):
|
---|
| 12 | self.optimize = int(self.optimize)
|
---|
| 13 | @@ -239,6 +240,7 @@ class py2exe(Command):
|
---|
| 14 | excludes = self.excludes,
|
---|
| 15 | ignores = self.ignores,
|
---|
| 16 | packages = self.packages,
|
---|
| 17 | + gi_namespaces = self.gi_namespaces,
|
---|
| 18 | dist_dist = self.dist_dir,
|
---|
| 19 | dll_excludes = self.dll_excludes,
|
---|
| 20 | typelibs = self.typelibs,
|
---|
| 21 | diff --git a/py2exe/dllfinder.py b/py2exe/dllfinder.py
|
---|
| 22 | index 4e5e76c..bb43f9e 100644
|
---|
| 23 | --- a/py2exe/dllfinder.py
|
---|
| 24 | +++ b/py2exe/dllfinder.py
|
---|
| 25 | @@ -68,7 +68,8 @@ class DllFinder:
|
---|
| 26 | if dll in self._loaded_dlls:
|
---|
| 27 | continue
|
---|
| 28 | for dep_dll in self.bind_image(dll):
|
---|
| 29 | - if dep_dll in self._loaded_dlls:
|
---|
| 30 | + bname = os.path.basename(dep_dll).lower()
|
---|
| 31 | + if bname in self._loaded_dlls:
|
---|
| 32 | continue
|
---|
| 33 | dll_type = self.determine_dll_type(dep_dll)
|
---|
| 34 | if dll_type is None:
|
---|
| 35 | @@ -144,7 +145,8 @@ class DllFinder:
|
---|
| 36 | deps = self.bind_image(imagename)
|
---|
| 37 | if pydll in [d.lower() for d in deps]:
|
---|
| 38 | return "EXT"
|
---|
| 39 | - if fnm.startswith(windir + os.sep) or fnm.startswith(sysdir + os.sep):
|
---|
| 40 | + if fnm.startswith(windir + os.sep) or fnm.startswith(sysdir + os.sep) or \
|
---|
| 41 | + fnm.startswith(windir + '\\') or fnm.startswith(sysdir + '\\'):
|
---|
| 42 | return None
|
---|
| 43 | return "DLL"
|
---|
| 44 |
|
---|
| 45 | diff --git a/py2exe/gihelper.py b/py2exe/gihelper.py
|
---|
| 46 | index e69de29..f597692 100644
|
---|
| 47 | --- a/py2exe/gihelper.py
|
---|
| 48 | +++ b/py2exe/gihelper.py
|
---|
| 49 | @@ -0,0 +1,58 @@
|
---|
| 50 | +
|
---|
| 51 | +import cffi
|
---|
| 52 | +
|
---|
| 53 | +class GIHelper(object):
|
---|
| 54 | + _cdef="""
|
---|
| 55 | + typedef char gchar;
|
---|
| 56 | + typedef int gint;
|
---|
| 57 | + typedef uint32_t guint32;
|
---|
| 58 | + typedef guint32 GQuark;
|
---|
| 59 | +
|
---|
| 60 | + typedef struct {
|
---|
| 61 | + GQuark domain;
|
---|
| 62 | + gint code;
|
---|
| 63 | + gchar *message;
|
---|
| 64 | + } GError;
|
---|
| 65 | +
|
---|
| 66 | + typedef struct _GITypelib GITypelib;
|
---|
| 67 | + typedef struct _GIRepository GIRepository;
|
---|
| 68 | +
|
---|
| 69 | + typedef enum
|
---|
| 70 | + {
|
---|
| 71 | + G_IREPOSITORY_LOAD_FLAG_LAZY = 1
|
---|
| 72 | + } GIRepositoryLoadFlags;
|
---|
| 73 | +
|
---|
| 74 | + GIRepository *g_irepository_get_default (void);
|
---|
| 75 | +
|
---|
| 76 | + GITypelib * g_irepository_require (GIRepository *repository,
|
---|
| 77 | + const gchar *namespace_,
|
---|
| 78 | + const gchar *version,
|
---|
| 79 | + GIRepositoryLoadFlags flags,
|
---|
| 80 | + GError **error);
|
---|
| 81 | +
|
---|
| 82 | + const gchar * g_irepository_get_shared_library (GIRepository *repository,
|
---|
| 83 | + const gchar *namespace_);
|
---|
| 84 | + """
|
---|
| 85 | +
|
---|
| 86 | + def __init__(self):
|
---|
| 87 | + self._ffi = cffi.FFI()
|
---|
| 88 | + self._ffi.cdef(self._cdef)
|
---|
| 89 | +
|
---|
| 90 | + self._lib = self._ffi.dlopen("libgirepository-1.0-1.dll")
|
---|
| 91 | +
|
---|
| 92 | + self._repo=self._lib.g_irepository_get_default()
|
---|
| 93 | +
|
---|
| 94 | + self._error = self._ffi.new("GError**")
|
---|
| 95 | +
|
---|
| 96 | + def getSharedLibraries(self, namespace, version):
|
---|
| 97 | + typelib = self._lib.g_irepository_require(self._repo,
|
---|
| 98 | + bytes(namespace, "utf-8"),
|
---|
| 99 | + bytes(version, "utf-8"),
|
---|
| 100 | + 0, self._error)
|
---|
| 101 | + if typelib == self._ffi.NULL:
|
---|
| 102 | + return []
|
---|
| 103 | + else:
|
---|
| 104 | + return str(
|
---|
| 105 | + self._ffi.string(
|
---|
| 106 | + self._lib.g_irepository_get_shared_library(
|
---|
| 107 | + self._repo, bytes(namespace, "utf-8"))), "utf-8").split(",")
|
---|
| 108 | diff --git a/py2exe/mf3.py b/py2exe/mf3.py
|
---|
| 109 | index f645740..ec1f261 100644
|
---|
| 110 | --- a/py2exe/mf3.py
|
---|
| 111 | +++ b/py2exe/mf3.py
|
---|
| 112 | @@ -5,6 +5,7 @@
|
---|
| 113 |
|
---|
| 114 | # XXX XXX XXX Does not yet support PEP 452 namespace packages!
|
---|
| 115 |
|
---|
| 116 | +from . import gihelper
|
---|
| 117 | from collections import defaultdict
|
---|
| 118 | import dis
|
---|
| 119 | import importlib
|
---|
| 120 | @@ -21,6 +22,9 @@ LOAD_CONST = dis.opname.index('LOAD_CONST')
|
---|
| 121 | IMPORT_NAME = dis.opname.index('IMPORT_NAME')
|
---|
| 122 | STORE_NAME = dis.opname.index('STORE_NAME')
|
---|
| 123 | STORE_GLOBAL = dis.opname.index('STORE_GLOBAL')
|
---|
| 124 | +LOAD_NAME = dis.opname.index('LOAD_NAME')
|
---|
| 125 | +LOAD_METHOD = dis.opname.index('LOAD_METHOD')
|
---|
| 126 | +CALL_METHOD = dis.opname.index('CALL_METHOD')
|
---|
| 127 | STORE_OPS = [STORE_NAME, STORE_GLOBAL]
|
---|
| 128 | HAVE_ARGUMENT = dis.HAVE_ARGUMENT
|
---|
| 129 |
|
---|
| 130 | @@ -63,7 +67,7 @@ class ModuleFinder:
|
---|
| 131 | self._depgraph = defaultdict(set)
|
---|
| 132 | self._indent = ""
|
---|
| 133 | self._package_paths = defaultdict(list)
|
---|
| 134 | -
|
---|
| 135 | + self._gihelper = gihelper.GIHelper()
|
---|
| 136 |
|
---|
| 137 | def add_packagepath(self, packagename, path):
|
---|
| 138 | """ModuleFinder can not handle __path__ modifications packages
|
---|
| 139 | @@ -416,7 +420,6 @@ class ModuleFinder:
|
---|
| 140 | We also take note of 'static' global symbols in the module and
|
---|
| 141 | add them to __globalnames__.
|
---|
| 142 | """
|
---|
| 143 | -
|
---|
| 144 | for what, args in self._scan_opcodes(code):
|
---|
| 145 | if what == "store":
|
---|
| 146 | name, = args
|
---|
| 147 | @@ -424,6 +427,11 @@ class ModuleFinder:
|
---|
| 148 | elif what == "import":
|
---|
| 149 | level, fromlist, name = args
|
---|
| 150 | self.safe_import_hook(name, mod, fromlist, level)
|
---|
| 151 | + elif what == "gi_request":
|
---|
| 152 | + for sharedLibrary in \
|
---|
| 153 | + self._gihelper.getSharedLibraries(args[0], args[1]):
|
---|
| 154 | + from . dllfinder import SearchPath
|
---|
| 155 | + self.add_dll(SearchPath(sharedLibrary))
|
---|
| 156 | else:
|
---|
| 157 | # We don't expect anything else from the generator.
|
---|
| 158 | raise RuntimeError(what)
|
---|
| 159 | @@ -442,10 +450,15 @@ class ModuleFinder:
|
---|
| 160 | # dis.get_instructions() is only available in python 3.4
|
---|
| 161 | # and higher
|
---|
| 162 | instructions = []
|
---|
| 163 | +
|
---|
| 164 | + requireCallLevel = 0
|
---|
| 165 | + requiredNamespace = None
|
---|
| 166 | + requiredVersion = None
|
---|
| 167 | for inst in dis.get_instructions(co):
|
---|
| 168 | instructions.append(inst)
|
---|
| 169 | c = inst.opcode
|
---|
| 170 | if c == IMPORT_NAME:
|
---|
| 171 | + requireCallLevel = 0
|
---|
| 172 | assert instructions[-3].opcode == LOAD_CONST
|
---|
| 173 | level = instructions[-3].argval
|
---|
| 174 | assert instructions[-2].opcode == LOAD_CONST
|
---|
| 175 | @@ -453,7 +466,34 @@ class ModuleFinder:
|
---|
| 176 | name = inst.argval
|
---|
| 177 | yield "import", (level, fromlist, name)
|
---|
| 178 | elif c in STORE_OPS:
|
---|
| 179 | + requireCallLevel = 0
|
---|
| 180 | yield "store", (inst.argval,)
|
---|
| 181 | + elif c == LOAD_NAME:
|
---|
| 182 | + if requireCallLevel==0 and inst.argval=="gi":
|
---|
| 183 | + requireCallLevel += 1
|
---|
| 184 | + else:
|
---|
| 185 | + requireCallLevel = 0
|
---|
| 186 | + elif c == LOAD_METHOD:
|
---|
| 187 | + if requireCallLevel==1 and inst.argval=="require_version":
|
---|
| 188 | + requireCallLevel += 1
|
---|
| 189 | + else:
|
---|
| 190 | + requireCallLevel = 0
|
---|
| 191 | + elif c==LOAD_CONST:
|
---|
| 192 | + if requireCallLevel==2:
|
---|
| 193 | + requiredNamespace = inst.argval
|
---|
| 194 | + requireCallLevel += 1
|
---|
| 195 | + elif requireCallLevel==3:
|
---|
| 196 | + requiredVersion = inst.argval
|
---|
| 197 | + requireCallLevel += 1
|
---|
| 198 | + else:
|
---|
| 199 | + requireCallLevel = 0
|
---|
| 200 | + elif c==CALL_METHOD:
|
---|
| 201 | + if requireCallLevel==4:
|
---|
| 202 | + yield ("gi_request", (requiredNamespace, requiredVersion))
|
---|
| 203 | + requireCallLevel = 0
|
---|
| 204 | + requiredNamespace = None
|
---|
| 205 | + requiredVersion = None
|
---|
| 206 | +
|
---|
| 207 | else:
|
---|
| 208 | code = co.co_code
|
---|
| 209 | names = co.co_names
|
---|
| 210 | diff --git a/py2exe/py2exe_distutils.py b/py2exe/py2exe_distutils.py
|
---|
| 211 | index 3918849..fe97b90 100644
|
---|
| 212 | --- a/py2exe/py2exe_distutils.py
|
---|
| 213 | +++ b/py2exe/py2exe_distutils.py
|
---|
| 214 | @@ -1,5 +1,5 @@
|
---|
| 215 | # This file is only used when BUILDING py2exe.
|
---|
| 216 | -import os, sys
|
---|
| 217 | +import os, sys, types, copy
|
---|
| 218 |
|
---|
| 219 | from distutils.core import Extension
|
---|
| 220 | from distutils.dist import Distribution
|
---|
| 221 | @@ -8,12 +8,17 @@ from distutils.sysconfig import customize_compiler
|
---|
| 222 | from distutils.dep_util import newer_group
|
---|
| 223 | from distutils.errors import DistutilsError, DistutilsSetupError, DistutilsPlatformError
|
---|
| 224 | from distutils.errors import CCompilerError, CompileError
|
---|
| 225 | +from distutils.file_util import write_file
|
---|
| 226 | from distutils.util import get_platform
|
---|
| 227 | from distutils import log
|
---|
| 228 |
|
---|
| 229 | -# We don't need a manifest in the executable, so monkeypatch the code away:
|
---|
| 230 | -from distutils.msvc9compiler import MSVCCompiler
|
---|
| 231 | -MSVCCompiler.manifest_setup_ldargs = lambda *args: None
|
---|
| 232 | +from distutils import ccompiler
|
---|
| 233 | +isMingw32 = ccompiler.get_default_compiler()=='mingw32'
|
---|
| 234 | +
|
---|
| 235 | +if not isMingw32:
|
---|
| 236 | + # We don't need a manifest in the executable, so monkeypatch the code away:
|
---|
| 237 | + from distutils.msvc9compiler import MSVCCompiler
|
---|
| 238 | + MSVCCompiler.manifest_setup_ldargs = lambda *args: None
|
---|
| 239 |
|
---|
| 240 | class Interpreter(Extension):
|
---|
| 241 | def __init__(self, *args, **kw):
|
---|
| 242 | @@ -38,6 +43,82 @@ class Dist(Distribution):
|
---|
| 243 | def has_extensions(self):
|
---|
| 244 | return False
|
---|
| 245 |
|
---|
| 246 | +def mingw32_link(self, target_desc, objects, output_filename, output_dir=None,
|
---|
| 247 | + libraries=None, library_dirs=None, runtime_library_dirs=None,
|
---|
| 248 | + export_symbols=None, debug=0, extra_preargs=None,
|
---|
| 249 | + extra_postargs=None, build_temp=None, target_lang=None):
|
---|
| 250 | + """Link the objects."""
|
---|
| 251 | + from distutils.unixccompiler import UnixCCompiler
|
---|
| 252 | +
|
---|
| 253 | + # use separate copies, so we can modify the lists
|
---|
| 254 | + extra_preargs = copy.copy(extra_preargs or [])
|
---|
| 255 | + libraries = copy.copy(libraries or [])
|
---|
| 256 | + objects = copy.copy(objects or [])
|
---|
| 257 | +
|
---|
| 258 | + # Additional libraries
|
---|
| 259 | + libraries.extend(self.dll_libraries)
|
---|
| 260 | +
|
---|
| 261 | + # handle export symbols by creating a def-file
|
---|
| 262 | + # with executables this only works with gcc/ld as linker
|
---|
| 263 | + if ((export_symbols is not None) and
|
---|
| 264 | + (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
|
---|
| 265 | + # (The linker doesn't do anything if output is up-to-date.
|
---|
| 266 | + # So it would probably better to check if we really need this,
|
---|
| 267 | + # but for this we had to insert some unchanged parts of
|
---|
| 268 | + # UnixCCompiler, and this is not what we want.)
|
---|
| 269 | +
|
---|
| 270 | + # we want to put some files in the same directory as the
|
---|
| 271 | + # object files are, build_temp doesn't help much
|
---|
| 272 | + # where are the object files
|
---|
| 273 | + temp_dir = os.path.dirname(objects[0])
|
---|
| 274 | + # name of dll to give the helper files the same base name
|
---|
| 275 | + (dll_name, dll_extension) = os.path.splitext(
|
---|
| 276 | + os.path.basename(output_filename))
|
---|
| 277 | +
|
---|
| 278 | + # generate the filenames for these files
|
---|
| 279 | + def_file = os.path.join(temp_dir, dll_name + ".def")
|
---|
| 280 | + lib_file = os.path.join(temp_dir, 'lib' + dll_name + ".a")
|
---|
| 281 | +
|
---|
| 282 | + # Generate .def file
|
---|
| 283 | + contents = ["EXPORTS"]
|
---|
| 284 | + for sym in export_symbols:
|
---|
| 285 | + contents.append(sym)
|
---|
| 286 | + self.execute(write_file, (def_file, contents),
|
---|
| 287 | + "writing %s" % def_file)
|
---|
| 288 | +
|
---|
| 289 | + # next add options for def-file and to creating import libraries
|
---|
| 290 | +
|
---|
| 291 | + # dllwrap uses different options than gcc/ld
|
---|
| 292 | + if self.linker_dll == "dllwrap":
|
---|
| 293 | + extra_preargs.extend(["--output-lib", lib_file])
|
---|
| 294 | + # for dllwrap we have to use a special option
|
---|
| 295 | + extra_preargs.extend(["--def", def_file])
|
---|
| 296 | + # we use gcc/ld here and can be sure ld is >= 2.9.10
|
---|
| 297 | + else:
|
---|
| 298 | + # doesn't work: bfd_close build\...\libfoo.a: Invalid operation
|
---|
| 299 | + #extra_preargs.extend(["-Wl,--out-implib,%s" % lib_file])
|
---|
| 300 | + # for gcc/ld the def-file is specified as any object files
|
---|
| 301 | + objects.append(def_file)
|
---|
| 302 | +
|
---|
| 303 | + #end: if ((export_symbols is not None) and
|
---|
| 304 | + # (target_desc != self.EXECUTABLE or self.linker_dll == "gcc")):
|
---|
| 305 | +
|
---|
| 306 | + # who wants symbols and a many times larger output file
|
---|
| 307 | + # should explicitly switch the debug mode on
|
---|
| 308 | + # otherwise we let dllwrap/ld strip the output file
|
---|
| 309 | + # (On my machine: 10KiB < stripped_file < ??100KiB
|
---|
| 310 | + # unstripped_file = stripped_file + XXX KiB
|
---|
| 311 | + # ( XXX=254 for a typical python extension))
|
---|
| 312 | + if not debug and not hasattr(sys, 'gettotalrefcount'):
|
---|
| 313 | + extra_preargs.append("-s")
|
---|
| 314 | +
|
---|
| 315 | + UnixCCompiler.link(self, target_desc, objects, output_filename,
|
---|
| 316 | + output_dir, libraries, library_dirs,
|
---|
| 317 | + runtime_library_dirs,
|
---|
| 318 | + None, # export_symbols, we do this in our def-file
|
---|
| 319 | + debug, extra_preargs, extra_postargs, build_temp,
|
---|
| 320 | + target_lang)
|
---|
| 321 | +
|
---|
| 322 | class BuildInterpreters(build_ext.build_ext):
|
---|
| 323 | description = "build special python interpreter stubs"
|
---|
| 324 |
|
---|
| 325 | @@ -67,6 +148,9 @@ class BuildInterpreters(build_ext.build_ext):
|
---|
| 326 | if os.name == 'nt' and self.plat_name != get_platform():
|
---|
| 327 | self.compiler.initialize(self.plat_name)
|
---|
| 328 |
|
---|
| 329 | + if isMingw32:
|
---|
| 330 | + self.compiler.link = types.MethodType(mingw32_link, self.compiler)
|
---|
| 331 | +
|
---|
| 332 | # And make sure that any compile/link-related options (which might
|
---|
| 333 | # come from the command-line or from the setup script) are set in
|
---|
| 334 | # that CCompiler object -- that way, they automatically apply to
|
---|
| 335 | @@ -190,7 +274,7 @@ class BuildInterpreters(build_ext.build_ext):
|
---|
| 336 | libraries=self.get_libraries(ext),
|
---|
| 337 | library_dirs=ext.library_dirs,
|
---|
| 338 | runtime_library_dirs=ext.runtime_library_dirs,
|
---|
| 339 | - export_symbols=ext.export_symbols,
|
---|
| 340 | + export_symbols=ext.export_symbols if ext.export_symbols else None,
|
---|
| 341 | extra_postargs=extra_args,
|
---|
| 342 | debug=self.debug)
|
---|
| 343 |
|
---|
| 344 | diff --git a/py2exe/runtime.py b/py2exe/runtime.py
|
---|
| 345 | index 10b0fa9..d154ff7 100644
|
---|
| 346 | --- a/py2exe/runtime.py
|
---|
| 347 | +++ b/py2exe/runtime.py
|
---|
| 348 | @@ -19,8 +19,8 @@ from .icons import BuildIcons
|
---|
| 349 |
|
---|
| 350 | logger = logging.getLogger("runtime")
|
---|
| 351 |
|
---|
| 352 | -#from importlib.machinery import EXTENSION_SUFFIXES
|
---|
| 353 | -EXTENSION_SUFFIXES = ['.pyd']
|
---|
| 354 | +from importlib.machinery import EXTENSION_SUFFIXES
|
---|
| 355 | +#EXTENSION_SUFFIXES = ['.pyd']
|
---|
| 356 | from importlib.machinery import DEBUG_BYTECODE_SUFFIXES, OPTIMIZED_BYTECODE_SUFFIXES
|
---|
| 357 |
|
---|
| 358 | RT_MANIFEST = 24
|
---|
| 359 | @@ -248,12 +248,15 @@ class Runtime(object):
|
---|
| 360 | if os.path.isfile(libpath):
|
---|
| 361 | os.remove(libpath)
|
---|
| 362 |
|
---|
| 363 | - if not os.path.exists(os.path.dirname(libpath)):
|
---|
| 364 | - os.mkdir(os.path.dirname(libpath))
|
---|
| 365 | -
|
---|
| 366 | - dll_bytes = pkgutil.get_data("py2exe", "resources.dll")
|
---|
| 367 | - with open(libpath, "wb") as ofi:
|
---|
| 368 | - ofi.write(dll_bytes)
|
---|
| 369 | + if self.options.skip_archive:
|
---|
| 370 | + if not os.path.exists(libpath):
|
---|
| 371 | + os.makedirs(libpath)
|
---|
| 372 | + else:
|
---|
| 373 | + if not os.path.exists(os.path.dirname(libpath)):
|
---|
| 374 | + os.mkdir(os.path.dirname(libpath))
|
---|
| 375 | + dll_bytes = pkgutil.get_data("py2exe", "resources.dll")
|
---|
| 376 | + with open(libpath, "wb") as ofi:
|
---|
| 377 | + ofi.write(dll_bytes)
|
---|
| 378 | if options.verbose:
|
---|
| 379 | print("Building shared code archive '%s'." % libpath)
|
---|
| 380 | # Archive is appended to resources.dll; remove the icon
|
---|
[971] | 381 | @@ -274,11 +277,12 @@ class Runtime(object):
|
---|
[920] | 382 | else:
|
---|
| 383 | raise RuntimeError("not yet supported")
|
---|
[971] | 384 |
|
---|
| 385 | # data files from modulefinder
|
---|
| 386 | for name, src in self.mf._data_files.items():
|
---|
| 387 | dst = os.path.join(destdir, name)
|
---|
| 388 | + os.makedirs(dst, exist_ok=True)
|
---|
| 389 | shutil.copy2(src, dst)
|
---|
| 390 |
|
---|
[920] | 391 | # other data files
|
---|
| 392 | if self.options.data_files:
|
---|
| 393 | for subdir, files in self.options.data_files:
|
---|
| 394 | @@ -410,46 +413,38 @@ class Runtime(object):
|
---|
| 395 | compression = zipfile.ZIP_STORED
|
---|
| 396 |
|
---|
| 397 | # Create a zipfile and append it to the library file
|
---|
| 398 | - arc = zipfile.ZipFile(libpath, "a",
|
---|
| 399 | - compression=compression)
|
---|
| 400 | -
|
---|
| 401 | - # The same modules may be in self.ms.modules under different
|
---|
| 402 | - # keys; we only need one of them in the archive.
|
---|
| 403 | - for mod in set(self.mf.modules.values()):
|
---|
| 404 | - if mod.__code__:
|
---|
| 405 | - if hasattr(mod, "__path__"):
|
---|
| 406 | - path = mod.__name__.replace(".", "\\") + "\\__init__" + bytecode_suffix
|
---|
| 407 | - else:
|
---|
| 408 | - path = mod.__name__.replace(".", "\\") + bytecode_suffix
|
---|
| 409 | - stream = io.BytesIO()
|
---|
| 410 | - stream.write(imp.get_magic())
|
---|
| 411 | - if sys.version_info >= (3,7,0):
|
---|
| 412 | - stream.write(b"\0\0\0\0") # null flags
|
---|
| 413 | - stream.write(b"\0\0\0\0") # null timestamp
|
---|
| 414 | - stream.write(b"\0\0\0\0") # null size
|
---|
| 415 | - marshal.dump(mod.__code__, stream)
|
---|
| 416 | - arc.writestr(path, stream.getvalue())
|
---|
| 417 | -
|
---|
| 418 | - elif hasattr(mod, "__file__"):
|
---|
| 419 | - #assert mod.__file__.endswith(EXTENSION_SUFFIXES[0])
|
---|
| 420 | - if self.options.bundle_files <= 2:
|
---|
| 421 | - # put .pyds into the archive
|
---|
| 422 | - arcfnm = mod.__name__.replace(".", "\\") + EXTENSION_SUFFIXES[0]
|
---|
| 423 | - if self.options.verbose > 1:
|
---|
| 424 | - print("Add %s to %s" % (os.path.basename(mod.__file__), libpath))
|
---|
| 425 | - arc.write(mod.__file__, arcfnm)
|
---|
| 426 | - else:
|
---|
| 427 | - # The extension modules will be copied into
|
---|
| 428 | - # dlldir. To be able to import it without dlldir
|
---|
| 429 | - # being on sys.path, create a loader module and
|
---|
| 430 | - # put that into the archive.
|
---|
| 431 | - pydfile = mod.__name__ + EXTENSION_SUFFIXES[0]
|
---|
| 432 | - if self.options.verbose > 1:
|
---|
| 433 | - print("Add Loader for %s to %s" % (os.path.basename(mod.__file__), libpath))
|
---|
| 434 | - loader = LOAD_FROM_DIR.format(pydfile)
|
---|
| 435 | -
|
---|
| 436 | - code = compile(loader, "<loader>", "exec",
|
---|
| 437 | - optimize=self.options.optimize)
|
---|
| 438 | + if self.options.skip_archive:
|
---|
| 439 | + for mod in set(self.mf.modules.values()):
|
---|
| 440 | + if hasattr(mod, "__file__"):
|
---|
| 441 | + path = os.path.join(*mod.__name__.split("."))
|
---|
| 442 | + if hasattr(mod, "__path__"):
|
---|
| 443 | + path = os.path.join(path, "__init__")
|
---|
| 444 | + path += bytecode_suffix if mod.__code__ else EXTENSION_SUFFIXES[0]
|
---|
| 445 | + path = os.path.join(libpath, path)
|
---|
| 446 | + dirpath = os.path.dirname(path)
|
---|
| 447 | + if not os.path.isdir(dirpath):
|
---|
| 448 | + os.makedirs(dirpath)
|
---|
| 449 | + if mod.__code__:
|
---|
| 450 | + with open(mod.__file__, "rt") as fin:
|
---|
| 451 | + code = compile(fin.read(), mod.__file__, "exec",
|
---|
| 452 | + optimize=self.options.optimize)
|
---|
| 453 | + with open(path, "wb") as fout:
|
---|
| 454 | + fout.write(imp.get_magic())
|
---|
| 455 | + if sys.version_info >= (3,7,0):
|
---|
| 456 | + fout.write(b"\0\0\0\0") # null flags
|
---|
| 457 | + fout.write(b"\0\0\0\0") # null timestamp
|
---|
| 458 | + fout.write(b"\0\0\0\0") # null size
|
---|
| 459 | + marshal.dump(code, fout)
|
---|
| 460 | + else:
|
---|
| 461 | + shutil.copy2(mod.__file__, path)
|
---|
| 462 | + else:
|
---|
| 463 | + arc = zipfile.ZipFile(libpath, "a",
|
---|
| 464 | + compression=compression)
|
---|
| 465 | +
|
---|
| 466 | + # The same modules may be in self.ms.modules under different
|
---|
| 467 | + # keys; we only need one of them in the archive.
|
---|
| 468 | + for mod in set(self.mf.modules.values()):
|
---|
| 469 | + if mod.__code__:
|
---|
| 470 | if hasattr(mod, "__path__"):
|
---|
| 471 | path = mod.__name__.replace(".", "\\") + "\\__init__" + bytecode_suffix
|
---|
| 472 | else:
|
---|
| 473 | @@ -457,28 +452,61 @@ class Runtime(object):
|
---|
| 474 | stream = io.BytesIO()
|
---|
| 475 | stream.write(imp.get_magic())
|
---|
| 476 | if sys.version_info >= (3,7,0):
|
---|
| 477 | - stream.write(b"\0\0\0\0") # null flags
|
---|
| 478 | + stream.write(b"\0\0\0\0") # null flags
|
---|
| 479 | stream.write(b"\0\0\0\0") # null timestamp
|
---|
| 480 | stream.write(b"\0\0\0\0") # null size
|
---|
| 481 | - marshal.dump(code, stream)
|
---|
| 482 | + marshal.dump(mod.__code__, stream)
|
---|
| 483 | arc.writestr(path, stream.getvalue())
|
---|
| 484 |
|
---|
| 485 | - if self.options.bundle_files == 0:
|
---|
| 486 | - # put everything into the arc
|
---|
| 487 | - files = self.mf.all_dlls()
|
---|
| 488 | - elif self.options.bundle_files in (1, 2):
|
---|
| 489 | - # put only extension dlls into the arc
|
---|
| 490 | - files = self.mf.extension_dlls()
|
---|
| 491 | - else:
|
---|
| 492 | - arc.close()
|
---|
| 493 | - return
|
---|
| 494 | + elif hasattr(mod, "__file__"):
|
---|
| 495 | + #assert mod.__file__.endswith(EXTENSION_SUFFIXES[0])
|
---|
| 496 | + if self.options.bundle_files <= 2:
|
---|
| 497 | + # put .pyds into the archive
|
---|
| 498 | + arcfnm = mod.__name__.replace(".", "\\") + EXTENSION_SUFFIXES[0]
|
---|
| 499 | + if self.options.verbose > 1:
|
---|
| 500 | + print("Add %s to %s" % (os.path.basename(mod.__file__), libpath))
|
---|
| 501 | + arc.write(mod.__file__, arcfnm)
|
---|
| 502 | + else:
|
---|
| 503 | + # The extension modules will be copied into
|
---|
| 504 | + # dlldir. To be able to import it without dlldir
|
---|
| 505 | + # being on sys.path, create a loader module and
|
---|
| 506 | + # put that into the archive.
|
---|
| 507 | + pydfile = mod.__name__ + EXTENSION_SUFFIXES[0]
|
---|
| 508 | + if self.options.verbose > 1:
|
---|
| 509 | + print("Add Loader for %s to %s" % (os.path.basename(mod.__file__), libpath))
|
---|
| 510 | + loader = LOAD_FROM_DIR.format(pydfile)
|
---|
| 511 | +
|
---|
| 512 | + code = compile(loader, "<loader>", "exec",
|
---|
| 513 | + optimize=self.options.optimize)
|
---|
| 514 | + if hasattr(mod, "__path__"):
|
---|
| 515 | + path = mod.__name__.replace(".", "\\") + "\\__init__" + bytecode_suffix
|
---|
| 516 | + else:
|
---|
| 517 | + path = mod.__name__.replace(".", "\\") + bytecode_suffix
|
---|
| 518 | + stream = io.BytesIO()
|
---|
| 519 | + stream.write(imp.get_magic())
|
---|
| 520 | + if sys.version_info >= (3,7,0):
|
---|
| 521 | + stream.write(b"\0\0\0\0") # null flags
|
---|
| 522 | + stream.write(b"\0\0\0\0") # null timestamp
|
---|
| 523 | + stream.write(b"\0\0\0\0") # null size
|
---|
| 524 | + marshal.dump(code, stream)
|
---|
| 525 | + arc.writestr(path, stream.getvalue())
|
---|
| 526 | +
|
---|
| 527 | + if self.options.bundle_files == 0:
|
---|
| 528 | + # put everything into the arc
|
---|
| 529 | + files = self.mf.all_dlls()
|
---|
| 530 | + elif self.options.bundle_files in (1, 2):
|
---|
| 531 | + # put only extension dlls into the arc
|
---|
| 532 | + files = self.mf.extension_dlls()
|
---|
| 533 | + else:
|
---|
| 534 | + arc.close()
|
---|
| 535 | + return
|
---|
| 536 |
|
---|
| 537 | - for src in files:
|
---|
| 538 | - if self.options.verbose > 1:
|
---|
| 539 | - print("Add DLL %s to %s" % (os.path.basename(src), libpath))
|
---|
| 540 | - arc.write(src, os.path.basename(src))
|
---|
| 541 | + for src in files:
|
---|
| 542 | + if self.options.verbose > 1:
|
---|
| 543 | + print("Add DLL %s to %s" % (os.path.basename(src), libpath))
|
---|
| 544 | + arc.write(src, os.path.basename(src))
|
---|
| 545 |
|
---|
| 546 | - arc.close()
|
---|
| 547 | + arc.close()
|
---|
| 548 |
|
---|
| 549 | def copy_files(self, destdir):
|
---|
| 550 | """Copy files (pyds, dlls, depending on the bundle_files value,
|
---|
| 551 | @@ -498,17 +526,19 @@ class Runtime(object):
|
---|
| 552 | with UpdateResources(dst, delete_existing=False) as resource:
|
---|
| 553 | resource.add_string(1000, "py2exe")
|
---|
| 554 |
|
---|
| 555 | - if self.options.bundle_files == 3:
|
---|
| 556 | + if not self.options.skip_archive and self.options.bundle_files == 3:
|
---|
| 557 | # copy extension modules; they go to libdir
|
---|
| 558 | for mod in self.mf.modules.values():
|
---|
| 559 | if mod.__code__:
|
---|
| 560 | # nothing to do for python modules.
|
---|
| 561 | continue
|
---|
| 562 | if hasattr(mod, "__file__"):
|
---|
| 563 | - assert mod.__file__.endswith(EXTENSION_SUFFIXES[0])
|
---|
| 564 | - pydfile = mod.__name__ + EXTENSION_SUFFIXES[0]
|
---|
| 565 | + if mod.__file__.endswith(EXTENSION_SUFFIXES[0]):
|
---|
| 566 | + pydfile = mod.__name__ + EXTENSION_SUFFIXES[0]
|
---|
| 567 |
|
---|
| 568 | - dst = os.path.join(libdir, pydfile)
|
---|
| 569 | + dst = os.path.join(libdir, pydfile)
|
---|
| 570 | + else:
|
---|
| 571 | + dst = os.path.join(libdir, os.path.basename(mod.__file__))
|
---|
| 572 | if self.options.verbose:
|
---|
| 573 | print("Copy %s to %s" % (mod.__file__, dst))
|
---|
| 574 | shutil.copy2(mod.__file__, dst)
|
---|
| 575 | @@ -638,9 +668,11 @@ def __load():
|
---|
| 576 | dllpath = os.path.join(os.path.dirname(__loader__.archive), r'{0}')
|
---|
| 577 | try:
|
---|
| 578 | mod = imp.load_dynamic(__name__, dllpath)
|
---|
| 579 | + mod.frozen = 1
|
---|
| 580 | except ImportError as details:
|
---|
| 581 | raise ImportError('(%s) %r' % (details, dllpath)) from None
|
---|
| 582 | - mod.frozen = 1
|
---|
| 583 | + except AttributeError:
|
---|
| 584 | + pass
|
---|
| 585 | __load()
|
---|
| 586 | del __load
|
---|
| 587 | """
|
---|
| 588 | diff --git a/setup.py b/setup.py
|
---|
| 589 | index 342d194..5fb5a9a 100644
|
---|
| 590 | --- a/setup.py
|
---|
| 591 | +++ b/setup.py
|
---|
| 592 | @@ -12,6 +12,8 @@ if sys.version_info < (3, 3):
|
---|
| 593 | ############################################################################
|
---|
| 594 |
|
---|
| 595 | from setuptools import setup
|
---|
| 596 | +from distutils import ccompiler
|
---|
| 597 | +isMingw32 = ccompiler.get_default_compiler()=='mingw32'
|
---|
| 598 | ##from distutils.core import setup
|
---|
| 599 |
|
---|
| 600 | from py2exe.py2exe_distutils import Dist, Interpreter, BuildInterpreters
|
---|
| 601 | @@ -26,11 +28,11 @@ def _is_debug_build():
|
---|
| 602 | return False
|
---|
| 603 |
|
---|
| 604 | if _is_debug_build():
|
---|
| 605 | - macros = [("PYTHONDLL", '\\"python%d%d_d.dll\\"' % sys.version_info[:2]),
|
---|
| 606 | + macros = [("PYTHONDLL", ('"libpython%d.%dm_d.dll"' if isMingw32 else '"\\python%d%d_d.dll\\"') % sys.version_info[:2]),
|
---|
| 607 | ## ("PYTHONCOM", '\\"pythoncom%d%d_d.dll\\"' % sys.version_info[:2]),
|
---|
| 608 | ("_CRT_SECURE_NO_WARNINGS", '1')]
|
---|
| 609 | else:
|
---|
| 610 | - macros = [("PYTHONDLL", '\\"python%d%d.dll\\"' % sys.version_info[:2]),
|
---|
| 611 | + macros = [("PYTHONDLL", ('"libpython%d.%dm.dll"' if isMingw32 else '"\\python%d%d.dll\\"') % sys.version_info[:2]),
|
---|
| 612 | ## ("PYTHONCOM", '\\"pythoncom%d%d.dll\\"' % sys.version_info[:2]),
|
---|
| 613 | ("_CRT_SECURE_NO_WARNINGS", '1'),]
|
---|
| 614 |
|
---|
| 615 | @@ -39,9 +41,10 @@ macros.append(("Py_BUILD_CORE", '1'))
|
---|
| 616 | extra_compile_args = []
|
---|
| 617 | extra_link_args = []
|
---|
| 618 |
|
---|
| 619 | -extra_compile_args.append("-IC:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Include")
|
---|
| 620 | -extra_compile_args.append("-IC:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\include")
|
---|
| 621 | -extra_compile_args.append("-IC:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.10586.0\\ucrt")
|
---|
| 622 | +if not isMingw32:
|
---|
| 623 | + extra_compile_args.append("-IC:\\Program Files\\Microsoft SDKs\\Windows\\v7.0\\Include")
|
---|
| 624 | + extra_compile_args.append("-IC:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\include")
|
---|
| 625 | + extra_compile_args.append("-IC:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.10586.0\\ucrt")
|
---|
| 626 |
|
---|
| 627 | if 0:
|
---|
| 628 | # enable this to debug a release build
|
---|
| 629 | @@ -63,7 +66,11 @@ run_ctypes_dll = Interpreter("py2exe.run_ctypes_dll",
|
---|
| 630 | "source/python-dynload.c",
|
---|
| 631 | ],
|
---|
| 632 | libraries=["user32", "shell32"],
|
---|
| 633 | - export_symbols=["DllCanUnloadNow,PRIVATE",
|
---|
| 634 | + export_symbols=["DllCanUnloadNow",
|
---|
| 635 | + "DllGetClassObject",
|
---|
| 636 | + "DllRegisterServer",
|
---|
| 637 | + "DllUnregisterServer",
|
---|
| 638 | + ] if isMingw32 else ["DllCanUnloadNow,PRIVATE",
|
---|
| 639 | "DllGetClassObject,PRIVATE",
|
---|
| 640 | "DllRegisterServer,PRIVATE",
|
---|
| 641 | "DllUnregisterServer,PRIVATE",
|
---|
| 642 | @@ -71,7 +78,7 @@ run_ctypes_dll = Interpreter("py2exe.run_ctypes_dll",
|
---|
| 643 | target_desc = "shared_library",
|
---|
| 644 | define_macros=macros,
|
---|
| 645 | extra_compile_args=extra_compile_args,
|
---|
| 646 | - extra_link_args=extra_link_args + ["/DLL"],
|
---|
| 647 | + extra_link_args=extra_link_args + ([] if isMingw32 else ["/DLL"]),
|
---|
| 648 | )
|
---|
| 649 |
|
---|
| 650 | run = Interpreter("py2exe.run",
|
---|
| 651 | @@ -123,7 +130,7 @@ resource_dll = Interpreter("py2exe.resources",
|
---|
| 652 | ["source/dll.c",
|
---|
| 653 | "source/icon.rc"],
|
---|
| 654 | target_desc = "shared_library",
|
---|
| 655 | - extra_link_args=["/DLL"],
|
---|
| 656 | + extra_link_args=[] if isMingw32 else ["/DLL"],
|
---|
| 657 | )
|
---|
| 658 |
|
---|
| 659 | interpreters = [run, run_w, resource_dll,
|
---|
| 660 | diff --git a/source/python-dynload.c b/source/python-dynload.c
|
---|
| 661 | index 2a60b86..373bb62 100644
|
---|
| 662 | --- a/source/python-dynload.c
|
---|
| 663 | +++ b/source/python-dynload.c
|
---|
| 664 | @@ -31,7 +31,7 @@ static HMODULE hmod_pydll;
|
---|
| 665 |
|
---|
| 666 | #define FUNC(res, name, args) \
|
---|
| 667 | static res(*proc)args; \
|
---|
| 668 | - if (!proc) (FARPROC)proc = MyGetProcAddress(hmod_pydll, #name)
|
---|
| 669 | + if (!proc) proc = (res (*)args)MyGetProcAddress(hmod_pydll, #name)
|
---|
| 670 |
|
---|
| 671 | #define DATA(type, name) \
|
---|
| 672 | static type pflag; \
|
---|
| 673 | @@ -158,7 +158,7 @@ void PyErr_Print(void)
|
---|
| 674 | proc();
|
---|
| 675 | }
|
---|
| 676 |
|
---|
| 677 | -void Py_SetProgramName(wchar_t *name)
|
---|
| 678 | +void Py_SetProgramName(const wchar_t *name)
|
---|
| 679 | {
|
---|
| 680 | FUNC(void, Py_SetProgramName, (wchar_t *));
|
---|
| 681 | proc(name);
|
---|
| 682 | diff --git a/source/run.c b/source/run.c
|
---|
| 683 | index e1f630e..933ae77 100644
|
---|
| 684 | --- a/source/run.c
|
---|
| 685 | +++ b/source/run.c
|
---|
| 686 | @@ -54,7 +54,11 @@ extern int start(int argc, wchar_t **argv);
|
---|
| 687 | /*
|
---|
| 688 | The main function for our exe.
|
---|
| 689 | */
|
---|
| 690 | +#if defined(__MINGW32__)
|
---|
| 691 | +int main (int argc, wchar_t **argv)
|
---|
| 692 | +#else
|
---|
| 693 | int wmain (int argc, wchar_t **argv)
|
---|
| 694 | +#endif
|
---|
| 695 | {
|
---|
| 696 | int result;
|
---|
| 697 | result = init("console_exe");
|
---|
| 698 | diff --git a/source/start.c b/source/start.c
|
---|
| 699 | index e894ae6..6b61624 100644
|
---|
| 700 | --- a/source/start.c
|
---|
| 701 | +++ b/source/start.c
|
---|
| 702 | @@ -128,7 +128,7 @@ BOOL locate_script(HMODULE hmod)
|
---|
| 703 | SystemError(GetLastError(), "Could not load script resource:");
|
---|
| 704 | return FALSE;
|
---|
| 705 | }
|
---|
| 706 | - p_script_info = (struct scriptinfo *)pScript = LockResource(hgbl);
|
---|
| 707 | + p_script_info = (struct scriptinfo *)(pScript = LockResource(hgbl));
|
---|
| 708 | if (!pScript) {
|
---|
| 709 | SystemError(GetLastError(), "Could not lock script resource:");
|
---|
| 710 | return FALSE;
|
---|
[936] | 711 | diff --git a/setup.py b/setup.py
|
---|
| 712 | index 342d194..1fe1e43 100644
|
---|
| 713 | --- a/setup.py
|
---|
| 714 | +++ b/setup.py
|
---|
| 715 | @@ -107,7 +107,7 @@ run_w = Interpreter("py2exe.run_w",
|
---|
| 716 | libraries=["user32", "shell32"],
|
---|
| 717 | define_macros=macros,
|
---|
| 718 | extra_compile_args=extra_compile_args,
|
---|
| 719 | - extra_link_args=extra_link_args,
|
---|
| 720 | + extra_link_args=extra_link_args + (["-Wl,--subsystem,windows"] if isMingw32 else []),
|
---|
| 721 | )
|
---|
| 722 |
|
---|
| 723 | # The py2exe.resources name is special handled in BuildInterpreters;
|
---|