[PATCH 2 of 2 V2] setup: use libpythonX.Y as library name when building with MinGW
Adrian Buehlmann
adrian at cadifra.com
Wed Apr 27 14:14:30 EDT 2016
On 2016-04-27 18:46, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc at gmail.com>
> # Date 1461775344 25200
> # Wed Apr 27 09:42:24 2016 -0700
> # Branch stable
> # Node ID 9d064dc961587258355c53333002a763da460f2a
> # Parent 5b7f85ccc5851871997f0383331f2982c6db1f43
> setup: use libpythonX.Y as library name when building with MinGW
>
> Attempting to build Mercurial from source using MinGW from
> msys2 on Windows produces a hg.exe that attempts to load e.g.
> python27.dll. MinGW prefixes its library name with "lib" and
> adds a period between the major and minor versions. e.g.
> "libpython2.7.dll."
>
> Before this patch, hg.exe files in a MinGW environment would
> either fail to find a Python DLL or would attempt to load a
> non-MinGW DLL, which would summarily explode. Either way,
> hg.exe wouldn't work.
>
> This patch changes builds performed with a MinGW Python to detect
> "libpythonX.Y" and use it in hg.exe.
>
> If building with non-MinGW Python, we should continue to use
> "pythonXY" as the library name, as there should not be a
> "libpythonX.Y.dll" file next to sys.executable. This will enable
> people to use MinGW as a dev/shell environment while continuing
> to use a non-MinGW Python.
>
> diff --git a/setup.py b/setup.py
> --- a/setup.py
> +++ b/setup.py
> @@ -364,18 +364,38 @@ class buildhgexe(build_ext):
> description = 'compile hg.exe from mercurial/exewrapper.c'
>
> def build_extensions(self):
> if os.name != 'nt':
> return
> if isinstance(self.compiler, HackedMingw32CCompiler):
> self.compiler.compiler_so = self.compiler.compiler # no -mdll
> self.compiler.dll_libraries = [] # no -lmsrvc90
> +
> hv = sys.hexversion
> - pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
> + maj = '%s' % (hv >> 24,)
> + min = '%s' % ((hv >> 16) & 0xff,)
> +
> + # Most installs (including the official CPython distribution) have a
> + # pythonXY.dll somewhere (probably on the PATH).
> + libpattern = 'python%s%s'
> +
> + # MinGW puts a libpythonX.Y.dll in the same directory as python.exe.
> + # If it exists, we use it.
> + libpythonpath = os.path.join(os.path.dirname(sys.executable),
> + 'libpython%s.%s.dll' % (maj, min))
> + if os.path.exists(libpythonpath):
> + libpattern = 'libpython%s.%s'
> +
> + # We don't search for libpythonX.Y.dll on PATH because it is valid to
> + # run non-MinGW Python from within MinGW and we don't want false
> + # positives.
> +
> + pythonlib = libpattern % (maj, min)
> + log.info('using %s as Python library name' % pythonlib)
> with open('mercurial/hgpythonlib.h', 'wb') as f:
> f.write('/* this file is autogenerated by setup.py */\n')
> f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
> objects = self.compiler.compile(['mercurial/exewrapper.c'],
> output_dir=self.build_temp)
> dir = os.path.dirname(self.get_ext_fullpath('dummy'))
> target = os.path.join(dir, 'hg')
> self.compiler.link_executable(objects, target,
Perhaps, we can be even more clever. See for example:
$ python
Python 2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.dllhandle
503316480L
>>> import ctypes
>>> _kernel32 = ctypes.windll.kernel32
>>> size = 600
>>> buf = ctypes.create_string_buffer(size + 1)
>>> len = _kernel32.GetModuleFileNameA(sys.dllhandle, ctypes.byref(buf), size)
>>> len
32
>>> buf.value
'C:\\Windows\\system32\\python27.dll'
>>>
Would it be possible to extract the name of the python dll this way?
(see also executablepath in mercurial/win32.py for an example call of
GetModuleFileNameA)
More information about the Mercurial-devel
mailing list