Issue #2513: enable 64bit cross compilation on windows.

This commit is contained in:
Mark Hammond 2008-04-07 01:53:39 +00:00
parent aa63d0d4af
commit 495cf99aaf
16 changed files with 323 additions and 65 deletions

View File

@ -329,6 +329,42 @@ version number. This can be changed to another text by using the
The installer file will be written to the "distribution directory" --- normally The installer file will be written to the "distribution directory" --- normally
:file:`dist/`, but customizable with the :option:`--dist-dir` option. :file:`dist/`, but customizable with the :option:`--dist-dir` option.
.. _cross-compile-windows:
Cross-compiling on Windows
=====================
Starting with Python 2.6, distutils is capable of cross-compiling between
Windows platforms. In practice, this means that with the correct tools
installed, you can use a 32bit version of Windows to create 64bit extensions
and vice-versa.
To build for an alternate platform, specify the :option:`--plat-name` option
to the build command. Valid values are currently 'win32', 'win-amd64' and
'win-ia64'. For example, on a 32bit version of Windows, you could execute::
python setup.py build --plat-name=win-amd64
to build a 64bit version of your extension. The Windows Installers also
support this option, so the command::
python setup.py build --plat-name=win-amd64 bdist_wininst
would create a 64bit installation executable on your 32bit version of Windows.
To cross-compile, you must download the Python source code and cross-compile
Python itself for the platform you are targetting - it is not possible from a
binary installtion of Python (as the .lib etc file for other platforms are
not included.) In practice, this means the user of a 32 bit operating
system will need to use Visual Studio 2008 to open the
:file:`PCBuild/PCbuild.sln` solution in the Python source tree and build the
"x64" configuration of the 'pythoncore' project before cross-compiling
extensions is possible.
Note that by default, Visual Studio 2008 does not install 64bit compilers or
tools. You may need to reexecute the Visual Studio setup process and select
these tools (using Control Panel->[Add/Remove] Programs is a convenient way to
check or modify your existing install.)
.. _postinstallation-script: .. _postinstallation-script:

View File

@ -97,7 +97,10 @@ class bdist (Command):
def finalize_options (self): def finalize_options (self):
# have to finalize 'plat_name' before 'bdist_base' # have to finalize 'plat_name' before 'bdist_base'
if self.plat_name is None: if self.plat_name is None:
if self.skip_build:
self.plat_name = get_platform() self.plat_name = get_platform()
else:
self.plat_name = self.get_finalized_command('build').plat_name
# 'bdist_base' -- parent of per-built-distribution-format # 'bdist_base' -- parent of per-built-distribution-format
# temporary directories (eg. we'll probably have # temporary directories (eg. we'll probably have
@ -121,7 +124,6 @@ class bdist (Command):
# finalize_options() # finalize_options()
def run (self): def run (self):
# Figure out which sub-commands we need to run. # Figure out which sub-commands we need to run.

View File

@ -9,11 +9,11 @@ Implements the bdist_msi command.
import sys, os import sys, os
from distutils.core import Command from distutils.core import Command
from distutils.util import get_platform
from distutils.dir_util import remove_tree from distutils.dir_util import remove_tree
from distutils.sysconfig import get_python_version from distutils.sysconfig import get_python_version
from distutils.version import StrictVersion from distutils.version import StrictVersion
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
from distutils.util import get_platform
from distutils import log from distutils import log
import msilib import msilib
from msilib import schema, sequence, text from msilib import schema, sequence, text
@ -87,6 +87,9 @@ class bdist_msi (Command):
user_options = [('bdist-dir=', None, user_options = [('bdist-dir=', None,
"temporary directory for creating the distribution"), "temporary directory for creating the distribution"),
('plat-name=', 'p',
"platform name to embed in generated filenames "
"(default: %s)" % get_platform()),
('keep-temp', 'k', ('keep-temp', 'k',
"keep the pseudo-installation tree around after " + "keep the pseudo-installation tree around after " +
"creating the distribution archive"), "creating the distribution archive"),
@ -116,6 +119,7 @@ class bdist_msi (Command):
def initialize_options (self): def initialize_options (self):
self.bdist_dir = None self.bdist_dir = None
self.plat_name = None
self.keep_temp = 0 self.keep_temp = 0
self.no_target_compile = 0 self.no_target_compile = 0
self.no_target_optimize = 0 self.no_target_optimize = 0
@ -139,7 +143,10 @@ class bdist_msi (Command):
else: else:
self.target_version = short_version self.target_version = short_version
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) self.set_undefined_options('bdist',
('dist_dir', 'dist_dir'),
('plat_name', 'plat_name'),
)
if self.pre_install_script: if self.pre_install_script:
raise DistutilsOptionError, "the pre-install-script feature is not yet implemented" raise DistutilsOptionError, "the pre-install-script feature is not yet implemented"
@ -181,7 +188,7 @@ class bdist_msi (Command):
if not target_version: if not target_version:
assert self.skip_build, "Should have already checked this" assert self.skip_build, "Should have already checked this"
target_version = sys.version[0:3] target_version = sys.version[0:3]
plat_specifier = ".%s-%s" % (get_platform(), target_version) plat_specifier = ".%s-%s" % (self.plat_name, target_version)
build = self.get_finalized_command('build') build = self.get_finalized_command('build')
build.build_lib = os.path.join(build.build_base, build.build_lib = os.path.join(build.build_base,
'lib' + plat_specifier) 'lib' + plat_specifier)
@ -633,8 +640,7 @@ class bdist_msi (Command):
def get_installer_filename(self, fullname): def get_installer_filename(self, fullname):
# Factored out to allow overriding in subclasses # Factored out to allow overriding in subclasses
plat = get_platform() base_name = "%s.%s-py%s.msi" % (fullname, self.plat_name,
installer_name = os.path.join(self.dist_dir, self.target_version)
"%s.%s-py%s.msi" % installer_name = os.path.join(self.dist_dir, base_name)
(fullname, plat, self.target_version))
return installer_name return installer_name

View File

@ -21,6 +21,9 @@ class bdist_wininst (Command):
user_options = [('bdist-dir=', None, user_options = [('bdist-dir=', None,
"temporary directory for creating the distribution"), "temporary directory for creating the distribution"),
('plat-name=', 'p',
"platform name to embed in generated filenames "
"(default: %s)" % get_platform()),
('keep-temp', 'k', ('keep-temp', 'k',
"keep the pseudo-installation tree around after " + "keep the pseudo-installation tree around after " +
"creating the distribution archive"), "creating the distribution archive"),
@ -54,6 +57,7 @@ class bdist_wininst (Command):
def initialize_options (self): def initialize_options (self):
self.bdist_dir = None self.bdist_dir = None
self.plat_name = None
self.keep_temp = 0 self.keep_temp = 0
self.no_target_compile = 0 self.no_target_compile = 0
self.no_target_optimize = 0 self.no_target_optimize = 0
@ -82,7 +86,10 @@ class bdist_wininst (Command):
" option must be specified" % (short_version,) " option must be specified" % (short_version,)
self.target_version = short_version self.target_version = short_version
self.set_undefined_options('bdist', ('dist_dir', 'dist_dir')) self.set_undefined_options('bdist',
('dist_dir', 'dist_dir'),
('plat_name', 'plat_name'),
)
if self.install_script: if self.install_script:
for script in self.distribution.scripts: for script in self.distribution.scripts:
@ -110,6 +117,7 @@ class bdist_wininst (Command):
install.root = self.bdist_dir install.root = self.bdist_dir
install.skip_build = self.skip_build install.skip_build = self.skip_build
install.warn_dir = 0 install.warn_dir = 0
install.plat_name = self.plat_name
install_lib = self.reinitialize_command('install_lib') install_lib = self.reinitialize_command('install_lib')
# we do not want to include pyc or pyo files # we do not want to include pyc or pyo files
@ -127,7 +135,7 @@ class bdist_wininst (Command):
if not target_version: if not target_version:
assert self.skip_build, "Should have already checked this" assert self.skip_build, "Should have already checked this"
target_version = sys.version[0:3] target_version = sys.version[0:3]
plat_specifier = ".%s-%s" % (get_platform(), target_version) plat_specifier = ".%s-%s" % (self.plat_name, target_version)
build = self.get_finalized_command('build') build = self.get_finalized_command('build')
build.build_lib = os.path.join(build.build_base, build.build_lib = os.path.join(build.build_base,
'lib' + plat_specifier) 'lib' + plat_specifier)
@ -285,11 +293,11 @@ class bdist_wininst (Command):
# if we create an installer for a specific python version, # if we create an installer for a specific python version,
# it's better to include this in the name # it's better to include this in the name
installer_name = os.path.join(self.dist_dir, installer_name = os.path.join(self.dist_dir,
"%s.win32-py%s.exe" % "%s.%s-py%s.exe" %
(fullname, self.target_version)) (fullname, self.plat_name, self.target_version))
else: else:
installer_name = os.path.join(self.dist_dir, installer_name = os.path.join(self.dist_dir,
"%s.win32.exe" % fullname) "%s.%s.exe" % (fullname, self.plat_name))
return installer_name return installer_name
# get_installer_filename() # get_installer_filename()
@ -312,9 +320,9 @@ class bdist_wininst (Command):
bv = get_build_version() bv = get_build_version()
else: else:
if self.target_version < "2.4": if self.target_version < "2.4":
bv = "6" bv = 6.0
else: else:
bv = "7.1" bv = 7.1
else: else:
# for current version - use authoritative check. # for current version - use authoritative check.
bv = get_build_version() bv = get_build_version()
@ -323,6 +331,10 @@ class bdist_wininst (Command):
directory = os.path.dirname(__file__) directory = os.path.dirname(__file__)
# we must use a wininst-x.y.exe built with the same C compiler # we must use a wininst-x.y.exe built with the same C compiler
# used for python. XXX What about mingw, borland, and so on? # used for python. XXX What about mingw, borland, and so on?
filename = os.path.join(directory, "wininst-%.1f.exe" % bv) if self.plat_name == 'win32':
sfix = ''
else:
sfix = self.plat_name[3:] # strip 'win' - leaves eg '-amd64'
filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))
return open(filename, "rb").read() return open(filename, "rb").read()
# class bdist_wininst # class bdist_wininst

View File

@ -8,6 +8,7 @@ __revision__ = "$Id$"
import sys, os import sys, os
from distutils.core import Command from distutils.core import Command
from distutils.errors import DistutilsOptionError
from distutils.util import get_platform from distutils.util import get_platform
@ -34,6 +35,9 @@ class build (Command):
"build directory for scripts"), "build directory for scripts"),
('build-temp=', 't', ('build-temp=', 't',
"temporary build directory"), "temporary build directory"),
('plat-name=', 'p',
"platform name to build for, if supported "
"(default: %s)" % get_platform()),
('compiler=', 'c', ('compiler=', 'c',
"specify the compiler type"), "specify the compiler type"),
('debug', 'g', ('debug', 'g',
@ -61,13 +65,25 @@ class build (Command):
self.build_temp = None self.build_temp = None
self.build_scripts = None self.build_scripts = None
self.compiler = None self.compiler = None
self.plat_name = None
self.debug = None self.debug = None
self.force = 0 self.force = 0
self.executable = None self.executable = None
def finalize_options (self): def finalize_options (self):
plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3]) if self.plat_name is None:
self.plat_name = get_platform()
else:
# plat-name only supported for windows (other platforms are
# supported via ./configure flags, if at all). Avoid misleading
# other platforms.
if os.name != 'nt':
raise DistutilsOptionError(
"--plat-name only supported on Windows (try "
"using './configure --help' on your platform)")
plat_specifier = ".%s-%s" % (self.plat_name, sys.version[0:3])
# Make it so Python 2.x and Python 2.x with --with-pydebug don't # Make it so Python 2.x and Python 2.x with --with-pydebug don't
# share the same build directories. Doing so confuses the build # share the same build directories. Doing so confuses the build

View File

@ -15,6 +15,7 @@ from distutils.errors import *
from distutils.sysconfig import customize_compiler, get_python_version from distutils.sysconfig import customize_compiler, get_python_version
from distutils.dep_util import newer_group from distutils.dep_util import newer_group
from distutils.extension import Extension from distutils.extension import Extension
from distutils.util import get_platform
from distutils import log from distutils import log
if os.name == 'nt': if os.name == 'nt':
@ -60,6 +61,9 @@ class build_ext (Command):
"directory for compiled extension modules"), "directory for compiled extension modules"),
('build-temp=', 't', ('build-temp=', 't',
"directory for temporary files (build by-products)"), "directory for temporary files (build by-products)"),
('plat-name=', 'p',
"platform name to cross-compile for, if supported "
"(default: %s)" % get_platform()),
('inplace', 'i', ('inplace', 'i',
"ignore build-lib and put compiled extensions into the source " + "ignore build-lib and put compiled extensions into the source " +
"directory alongside your pure Python modules"), "directory alongside your pure Python modules"),
@ -101,6 +105,7 @@ class build_ext (Command):
def initialize_options (self): def initialize_options (self):
self.extensions = None self.extensions = None
self.build_lib = None self.build_lib = None
self.plat_name = None
self.build_temp = None self.build_temp = None
self.inplace = 0 self.inplace = 0
self.package = None self.package = None
@ -127,7 +132,9 @@ class build_ext (Command):
('build_temp', 'build_temp'), ('build_temp', 'build_temp'),
('compiler', 'compiler'), ('compiler', 'compiler'),
('debug', 'debug'), ('debug', 'debug'),
('force', 'force')) ('force', 'force'),
('plat_name', 'plat_name'),
)
if self.package is None: if self.package is None:
self.package = self.distribution.ext_package self.package = self.distribution.ext_package
@ -171,6 +178,9 @@ class build_ext (Command):
# for Release and Debug builds. # for Release and Debug builds.
# also Python's library directory must be appended to library_dirs # also Python's library directory must be appended to library_dirs
if os.name == 'nt': if os.name == 'nt':
# the 'libs' directory is for binary installs - we assume that
# must be the *native* platform. But we don't really support
# cross-compiling via a binary install anyway, so we let it go.
self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs')) self.library_dirs.append(os.path.join(sys.exec_prefix, 'libs'))
if self.debug: if self.debug:
self.build_temp = os.path.join(self.build_temp, "Debug") self.build_temp = os.path.join(self.build_temp, "Debug")
@ -181,8 +191,17 @@ class build_ext (Command):
# this allows distutils on windows to work in the source tree # this allows distutils on windows to work in the source tree
self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC')) self.include_dirs.append(os.path.join(sys.exec_prefix, 'PC'))
if MSVC_VERSION == 9: if MSVC_VERSION == 9:
self.library_dirs.append(os.path.join(sys.exec_prefix, # Use the .lib files for the correct architecture
'PCbuild')) if self.plat_name == 'win32':
suffix = ''
else:
# win-amd64 or win-ia64
suffix = self.plat_name[4:]
new_lib = os.path.join(sys.exec_prefix, 'PCbuild')
if suffix:
new_lib = os.path.join(new_lib, suffix)
self.library_dirs.append(new_lib)
elif MSVC_VERSION == 8: elif MSVC_VERSION == 8:
self.library_dirs.append(os.path.join(sys.exec_prefix, self.library_dirs.append(os.path.join(sys.exec_prefix,
'PC', 'VS8.0', 'win32release')) 'PC', 'VS8.0', 'win32release'))
@ -275,6 +294,11 @@ class build_ext (Command):
dry_run=self.dry_run, dry_run=self.dry_run,
force=self.force) force=self.force)
customize_compiler(self.compiler) customize_compiler(self.compiler)
# If we are cross-compiling, init the compiler now (if we are not
# cross-compiling, init would not hurt, but people may rely on
# late initialization of compiler even if they shouldn't...)
if os.name == 'nt' and self.plat_name != get_platform():
self.compiler.initialize(self.plat_name)
# And make sure that any compile/link-related options (which might # And make sure that any compile/link-related options (which might
# come from the command-line or from the setup script) are set in # come from the command-line or from the setup script) are set in

View File

@ -16,6 +16,7 @@ from distutils.sysconfig import get_config_vars
from distutils.errors import DistutilsPlatformError from distutils.errors import DistutilsPlatformError
from distutils.file_util import write_file from distutils.file_util import write_file
from distutils.util import convert_path, subst_vars, change_root from distutils.util import convert_path, subst_vars, change_root
from distutils.util import get_platform
from distutils.errors import DistutilsOptionError from distutils.errors import DistutilsOptionError
if sys.version < "2.2": if sys.version < "2.2":
@ -503,6 +504,14 @@ class install (Command):
# Obviously have to build before we can install # Obviously have to build before we can install
if not self.skip_build: if not self.skip_build:
self.run_command('build') self.run_command('build')
# If we built for any other platform, we can't install.
build_plat = self.distribution.get_command_obj('build').plat_name
# check warn_dir - it is a clue that the 'install' is happening
# internally, and not to sys.path, so we don't check the platform
# matches what we are running.
if self.warn_dir and build_plat != get_platform():
raise DistutilsPlatformError("Can't install when "
"cross-compiling")
# Run all sub-commands (at least those that need to be run) # Run all sub-commands (at least those that need to be run)
for cmd_name in self.get_sub_commands(): for cmd_name in self.get_sub_commands():

Binary file not shown.

View File

@ -22,6 +22,7 @@ from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
from distutils.ccompiler import (CCompiler, gen_preprocess_options, from distutils.ccompiler import (CCompiler, gen_preprocess_options,
gen_lib_options) gen_lib_options)
from distutils import log from distutils import log
from distutils.util import get_platform
import _winreg import _winreg
@ -38,13 +39,15 @@ HKEYS = (_winreg.HKEY_USERS,
VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f" VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows" WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
NET_BASE = r"Software\Microsoft\.NETFramework" NET_BASE = r"Software\Microsoft\.NETFramework"
ARCHS = {'DEFAULT' : 'x86',
'intel' : 'x86', 'x86' : 'x86',
'amd64' : 'x64', 'x64' : 'x64',
'itanium' : 'ia64', 'ia64' : 'ia64',
}
# The globals VERSION, ARCH, MACROS and VC_ENV are defined later # A map keyed by get_platform() return values to values accepted by
# 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is
# the param to cross-compile on x86 targetting amd64.)
PLAT_TO_VCVARS = {
'win32' : 'x86',
'win-amd64' : 'amd64',
'win-ia64' : 'ia64',
}
class Reg: class Reg:
"""Helper class to read values from the registry """Helper class to read values from the registry
@ -176,23 +179,6 @@ def get_build_version():
# else we don't know what version of the compiler this is # else we don't know what version of the compiler this is
return None return None
def get_build_architecture():
"""Return the processor architecture.
Possible results are "x86" or "amd64".
"""
prefix = " bit ("
i = sys.version.find(prefix)
if i == -1:
return "x86"
j = sys.version.find(")", i)
sysarch = sys.version[i+len(prefix):j].lower()
arch = ARCHS.get(sysarch, None)
if arch is None:
return ARCHS['DEFAULT']
else:
return arch
def normalize_and_reduce_paths(paths): def normalize_and_reduce_paths(paths):
"""Return a list of normalized paths with duplicates removed. """Return a list of normalized paths with duplicates removed.
@ -251,6 +237,7 @@ def query_vcvarsall(version, arch="x86"):
if vcvarsall is None: if vcvarsall is None:
raise IOError("Unable to find vcvarsall.bat") raise IOError("Unable to find vcvarsall.bat")
log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch), popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch),
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
@ -281,9 +268,7 @@ def query_vcvarsall(version, arch="x86"):
VERSION = get_build_version() VERSION = get_build_version()
if VERSION < 8.0: if VERSION < 8.0:
raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION) raise DistutilsPlatformError("VC %0.1f is not supported by this module" % VERSION)
ARCH = get_build_architecture()
# MACROS = MacroExpander(VERSION) # MACROS = MacroExpander(VERSION)
VC_ENV = query_vcvarsall(VERSION, ARCH)
class MSVCCompiler(CCompiler) : class MSVCCompiler(CCompiler) :
"""Concrete class that implements an interface to Microsoft Visual C++, """Concrete class that implements an interface to Microsoft Visual C++,
@ -318,13 +303,25 @@ class MSVCCompiler(CCompiler) :
def __init__(self, verbose=0, dry_run=0, force=0): def __init__(self, verbose=0, dry_run=0, force=0):
CCompiler.__init__ (self, verbose, dry_run, force) CCompiler.__init__ (self, verbose, dry_run, force)
self.__version = VERSION self.__version = VERSION
self.__arch = ARCH
self.__root = r"Software\Microsoft\VisualStudio" self.__root = r"Software\Microsoft\VisualStudio"
# self.__macros = MACROS # self.__macros = MACROS
self.__path = [] self.__path = []
# target platform (.plat_name is consistent with 'bdist')
self.plat_name = None
self.__arch = None # deprecated name
self.initialized = False self.initialized = False
def initialize(self): def initialize(self, plat_name=None):
# multi-init means we would need to check platform same each time...
assert not self.initialized, "don't init multiple times"
if plat_name is None:
plat_name = get_platform()
# sanity check for platforms to prevent obscure errors later.
ok_plats = 'win32', 'win-amd64', 'win-ia64'
if plat_name not in ok_plats:
raise DistutilsPlatformError("--plat-name must be one of %s" %
(ok_plats,))
if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"): if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
# Assume that the SDK set up everything alright; don't try to be # Assume that the SDK set up everything alright; don't try to be
# smarter # smarter
@ -334,9 +331,24 @@ class MSVCCompiler(CCompiler) :
self.rc = "rc.exe" self.rc = "rc.exe"
self.mc = "mc.exe" self.mc = "mc.exe"
else: else:
self.__paths = VC_ENV['path'].split(os.pathsep) # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
os.environ['lib'] = VC_ENV['lib'] # to cross compile, you use 'x86_amd64'.
os.environ['include'] = VC_ENV['include'] # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
# compile use 'x86' (ie, it runs the x86 compiler directly)
# No idea how itanium handles this, if at all.
if plat_name == get_platform() or plat_name == 'win32':
# native build or cross-compile to win32
plat_spec = PLAT_TO_VCVARS[plat_name]
else:
# cross compile from win32 -> some 64bit
plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \
PLAT_TO_VCVARS[plat_name]
vc_env = query_vcvarsall(VERSION, plat_spec)
self.__paths = vc_env['path'].split(os.pathsep)
os.environ['lib'] = vc_env['lib']
os.environ['include'] = vc_env['include']
if len(self.__paths) == 0: if len(self.__paths) == 0:
raise DistutilsPlatformError("Python was built with %s, " raise DistutilsPlatformError("Python was built with %s, "

View File

@ -656,5 +656,5 @@ if get_build_version() >= 8.0:
log.debug("Importing new compiler from distutils.msvc9compiler") log.debug("Importing new compiler from distutils.msvc9compiler")
OldMSVCCompiler = MSVCCompiler OldMSVCCompiler = MSVCCompiler
from distutils.msvc9compiler import MSVCCompiler from distutils.msvc9compiler import MSVCCompiler
from distutils.msvc9compiler import get_build_architecture # get_build_architecture not really relevant now we support cross-compile
from distutils.msvc9compiler import MacroExpander from distutils.msvc9compiler import MacroExpander

View File

@ -30,7 +30,7 @@ def get_platform ():
irix64-6.2 irix64-6.2
Windows will return one of: Windows will return one of:
win-x86_64 (64bit Windows on x86_64 (AMD64)) win-amd64 (64bit Windows on AMD64 (aka x86_64, Intel64, EM64T, etc)
win-ia64 (64bit Windows on Itanium) win-ia64 (64bit Windows on Itanium)
win32 (all others - specifically, sys.platform is returned) win32 (all others - specifically, sys.platform is returned)
@ -45,7 +45,7 @@ def get_platform ():
j = string.find(sys.version, ")", i) j = string.find(sys.version, ")", i)
look = sys.version[i+len(prefix):j].lower() look = sys.version[i+len(prefix):j].lower()
if look=='amd64': if look=='amd64':
return 'win-x86_64' return 'win-amd64'
if look=='itanium': if look=='itanium':
return 'win-ia64' return 'win-ia64'
return sys.platform return sys.platform

View File

@ -18,6 +18,10 @@ Extensions Modules
Library Library
------- -------
- Issue #2513: distutils on Windows is now capable of cross-compiling
extension modules between 32 and 64 bit platforms. See the distutls
build documentation for more information.
- Issue #815646: Individual file objects may now be used from multiple - Issue #815646: Individual file objects may now be used from multiple
threads at once without fear of crashing the Python interpreter. If threads at once without fear of crashing the Python interpreter. If
file.close() is called while an object is in use by another thread file.close() is called while an object is in use by another thread

View File

@ -2,12 +2,34 @@ Example Python extension for Windows NT
======================================= =======================================
This directory contains everything needed (except for the Python This directory contains everything needed (except for the Python
distribution!) to build a Python extension module using Microsoft VC++ distribution!) to build a Python extension module using Microsoft VC++.
("Developer Studio") version 7.1. It has been tested with VC++ 7.1 on Notice that you need to use the same compiler version that was used to build
Python 2.4. You can also use earlier versions of VC to build Python Python itself.
extensions, but the sample VC project file (example.dsw in this directory)
is in VC 7.1 format. Notice that you need to use the same compiler version The simplest way to build this example is to use the distutils script
that was used to build Python itself. 'setup.py'. To do this, simply execute:
% python setup.py install
after everything builds and installs, you can test it:
% python -c "import example; example.foo()"
Hello, world
See setup.py for more details. alternatively, see below for instructions on
how to build inside the Visual Studio environment.
Visual Studio Build Instructions
================================
These are instructions how to build an extension using Visual C++. The
instructions and project files have not been updated to the latest VC
version. In general, it is recommended you use the 'setup.py' instructions
above.
It has been tested with VC++ 7.1 on Python 2.4. You can also use earlier
versions of VC to build Python extensions, but the sample VC project file
(example.dsw in this directory) is in VC 7.1 format.
COPY THIS DIRECTORY! COPY THIS DIRECTORY!
-------------------- --------------------

22
PC/example_nt/setup.py Normal file
View File

@ -0,0 +1,22 @@
# This is an example of a distutils 'setup' script for the example_nt
# sample. This provides a simpler way of building your extension
# and means you can avoid keeping MSVC solution files etc in source-control.
# It also means it should magically build with all compilers supported by
# python.
# USAGE: you probably want 'setup.py install' - but execute 'setup.py --help'
# for all the details.
# NOTE: This is *not* a sample for distutils - it is just the smallest
# script that can build this. See distutils docs for more info.
from distutils.core import setup, Extension
example_mod = Extension('example', sources = ['example.c'])
setup(name = "example",
version = "1.0",
description = "A sample extension module",
ext_modules = [example_mod],
)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?> <?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject <VisualStudioProject
ProjectType="Visual C++" ProjectType="Visual C++"
Version="9,00" Version="9.00"
Name="bdist_wininst" Name="bdist_wininst"
ProjectGUID="{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}" ProjectGUID="{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}"
RootNamespace="wininst" RootNamespace="wininst"
@ -11,6 +11,9 @@
<Platform <Platform
Name="Win32" Name="Win32"
/> />
<Platform
Name="x64"
/>
</Platforms> </Platforms>
<ToolFiles> <ToolFiles>
</ToolFiles> </ToolFiles>
@ -104,6 +107,96 @@
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
/> />
</Configuration> </Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
InheritedPropertySheets=".\pyproject.vsprops;.\release.vsprops"
UseOfMFC="0"
ATLMinimizesCRunTimeLibraryUsage="false"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
PreprocessorDefinitions="NDEBUG"
MkTypLibCompatible="true"
SuppressStartupBanner="true"
TargetEnvironment="3"
TypeLibraryName=".\..\lib\distutils\command\wininst.tlb"
HeaderFileName=""
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
InlineFunctionExpansion="1"
AdditionalIncludeDirectories="..\PC\bdist_wininst;..\Include;..\Modules\zlib"
PreprocessorDefinitions="_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
StringPooling="true"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
WarningLevel="3"
SuppressStartupBanner="true"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
Culture="0"
AdditionalIncludeDirectories="..\PC;..\PC\bdist_wininst;..\Include"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="comctl32.lib imagehlp.lib"
OutputFile="..\lib\distutils\command\wininst-9.0-amd64.exe"
LinkIncremental="1"
SuppressStartupBanner="true"
IgnoreDefaultLibraryNames="LIBC"
ProgramDatabaseFile="..\lib\distutils\command\wininst-9.0-amd64.pdb"
SubSystem="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations> </Configurations>
<References> <References>
</References> </References>

View File

@ -482,13 +482,13 @@ Global
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.ActiveCfg = Release|x64 {D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.ActiveCfg = Release|x64
{D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.Build.0 = Release|x64 {D06B6426-4762-44CC-8BAD-D79052507F2F}.Release|x64.Build.0 = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|x64.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Debug|x64.ActiveCfg = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|x64.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGInstrument|x64.ActiveCfg = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|x64.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.PGUpdate|x64.ActiveCfg = Release|x64
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|Win32.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|Win32.ActiveCfg = Release|Win32
{EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|x64.ActiveCfg = Release|Win32 {EB1C19C1-1F18-421E-9735-CAEE69DC6A3C}.Release|x64.ActiveCfg = Release|x64
{447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|Win32.ActiveCfg = Debug|Win32 {447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|Win32.ActiveCfg = Debug|Win32
{447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|Win32.Build.0 = Debug|Win32 {447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|Win32.Build.0 = Debug|Win32
{447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|x64.ActiveCfg = Debug|x64 {447F05A8-F581-4CAC-A466-5AC7936E207E}.Debug|x64.ActiveCfg = Debug|x64