345 lines
13 KiB
Python
345 lines
13 KiB
Python
import sys
|
|
from distutils.core import setup, Extension
|
|
|
|
DEBUG = True
|
|
|
|
PLATFORM_IS_WINDOWS = sys.platform.lower().startswith('win')
|
|
|
|
if PLATFORM_IS_WINDOWS:
|
|
|
|
__doc__="""This is a distutils setup-script for the telldus extension
|
|
|
|
To build the telldus extensions, simply execute:
|
|
python setup.py -q build
|
|
or
|
|
python setup.py -q install
|
|
to build and install into your current Python installation.
|
|
|
|
These extensions require a number of libraries to build, some of which may
|
|
require you to install special SDKs or toolkits. This script will attempt
|
|
to build as many as it can, and at the end of the build will report any
|
|
extension modules that could not be built and why.
|
|
|
|
This has got complicated due to the various different versions of
|
|
Visual Studio used - some VS versions are not compatible with some SDK
|
|
versions. Below are the Windows SDK versions required (and the URL - although
|
|
these are subject to being changed by MS at any time:)
|
|
|
|
Python 2.6+:
|
|
|
|
Build using Microsoft Visual Studio 2008 Express Edition:
|
|
http://www.microsoft.com/en-us/download/details.aspx?id=6506
|
|
http://jenshuebel.wordpress.com/2009/02/12/visual-c-2008-express-edition-and-64-bit-targets/
|
|
http://www.cppblog.com/Files/xcpp/VCE64BIT_WIN7SDK.zip
|
|
|
|
For 32bit build:
|
|
Microsoft Windows SDK for Windows 7 and .NET Framework 3.5
|
|
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b
|
|
Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars32.bat to
|
|
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat
|
|
|
|
For 64bit build:
|
|
Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 (ISO) GRMSDKX_EN_DVD.iso
|
|
http://www.microsoft.com/en-us/download/details.aspx?id=18950
|
|
Copy C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvars64.bat to
|
|
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat
|
|
|
|
Python 2.3->2.5:
|
|
|
|
Microsoft Windows Software Development Kit Update for Windows Vista (version 6.0)
|
|
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4377f86d-c913-4b5c-b87e-ef72e5b4e065
|
|
** If you want to build Python 2.3, be sure to install the SDK compilers
|
|
too - although we don't use them, this setup option installs some .lib
|
|
files we do need.
|
|
**
|
|
|
|
If you multiple SDK versions on a single machine, set the MSSDK environment
|
|
variable to point at the one you want to use. Note that using the SDK for
|
|
a particular platform (eg, Windows 7) doesn't force you to use that OS as your
|
|
build environment. If the links above don't work, use google to find them.
|
|
|
|
Building:
|
|
---------
|
|
|
|
To install the telldus extension, execute:
|
|
python setup.py -q install
|
|
|
|
This will install the built extensions into your site-packages directory,
|
|
create an appropriate .pth file, and should leave everything ready to use.
|
|
There is no need to modify the registry.
|
|
|
|
To build or install debug (_d) versions of these extensions, ensure you have
|
|
built or installed a debug version of Python itself, then pass the "--debug"
|
|
flag to the build command - eg:
|
|
python setup.py -q build --debug
|
|
or to build and install a debug version:
|
|
python setup.py -q build --debug install
|
|
|
|
To build 64bit versions of this:
|
|
|
|
* py2.5 and earlier - sorry, I've given up in disgust. Using VS2003 with
|
|
the Vista SDK is just too painful to make work, and VS2005 is not used for
|
|
any released versions of Python. See revision 1.69 of this file for the
|
|
last version that attempted to support and document this process.
|
|
|
|
* 2.6 and later: On a 64bit OS, just build as you would on a 32bit platform.
|
|
On a 32bit platform (ie, to cross-compile), you must use VS2008 to
|
|
cross-compile Python itself. Note that by default, the 64bit tools are not
|
|
installed with VS2008, so you may need to adjust your VS2008 setup (see "For 64bit build"). Then
|
|
use:
|
|
vcs
|
|
setup.py build --plat-name=win-amd64
|
|
|
|
see the distutils cross-compilation documentation for more details.
|
|
"""
|
|
# Originally by Thomas Heller, started in 2000 or so.
|
|
import os
|
|
import shutil
|
|
|
|
is_py3k = sys.version_info > (3,) # get this out of the way early on...
|
|
# We have special handling for _winreg so our setup3.py script can avoid
|
|
# using the 'imports' fixer and therefore start much faster...
|
|
if is_py3k:
|
|
import winreg as _winreg
|
|
else:
|
|
import _winreg
|
|
|
|
try:
|
|
from distutils import log
|
|
except ImportError:
|
|
class Log:
|
|
def debug(self, msg, *args):
|
|
print msg % args
|
|
def info(self, msg, *args):
|
|
print msg % args
|
|
log = Log()
|
|
|
|
try:
|
|
this_file = __file__
|
|
except NameError:
|
|
this_file = sys.argv[0]
|
|
|
|
this_file = os.path.abspath(this_file)
|
|
# We get upset if the cwd is not our source dir, but it is a PITA to
|
|
# insist people manually CD there first!
|
|
if os.path.dirname(this_file):
|
|
os.chdir(os.path.dirname(this_file))
|
|
|
|
|
|
# We need to know the platform SDK dir before we can list the extensions.
|
|
def find_platform_sdk_dir():
|
|
# Finding the Platform SDK install dir is a treat. There can be some
|
|
# dead ends so we only consider the job done if we find the "windows.h"
|
|
# landmark.
|
|
landmark = "include\\windows.h"
|
|
# 1. The use might have their current environment setup for the
|
|
# SDK, in which case the "MSSdk" env var is set.
|
|
sdkdir = os.environ.get("MSSdk")
|
|
if sdkdir:
|
|
if DEBUG:
|
|
print "PSDK: try %%MSSdk%%: '%s'" % sdkdir
|
|
if os.path.isfile(os.path.join(sdkdir, landmark)):
|
|
return sdkdir
|
|
# 2. The "Install Dir" value in the
|
|
# HKLM\Software\Microsoft\MicrosoftSDK\Directories registry key
|
|
# sometimes points to the right thing. However, after upgrading to
|
|
# the "Platform SDK for Windows Server 2003 SP1" this is dead end.
|
|
try:
|
|
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
|
|
r"Software\Microsoft\MicrosoftSDK\Directories")
|
|
sdkdir, ignore = _winreg.QueryValueEx(key, "Install Dir")
|
|
except EnvironmentError:
|
|
pass
|
|
else:
|
|
if DEBUG:
|
|
print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\
|
|
"\Directories\Install Dir': '%s'" % sdkdir
|
|
if os.path.isfile(os.path.join(sdkdir, landmark)):
|
|
return sdkdir
|
|
# 3. Each installed SDK (not just the platform SDK) seems to have GUID
|
|
# subkey of HKLM\Software\Microsoft\MicrosoftSDK\InstalledSDKs and
|
|
# it *looks* like the latest installed Platform SDK will be the
|
|
# only one with an "Install Dir" sub-value.
|
|
try:
|
|
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
|
|
r"Software\Microsoft\MicrosoftSDK\InstalledSDKs")
|
|
i = 0
|
|
while True:
|
|
guid = _winreg.EnumKey(key, i)
|
|
guidkey = _winreg.OpenKey(key, guid)
|
|
try:
|
|
sdkdir, ignore = _winreg.QueryValueEx(guidkey, "Install Dir")
|
|
except EnvironmentError:
|
|
pass
|
|
else:
|
|
if DEBUG:
|
|
print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDK"\
|
|
"\InstallSDKs\%s\Install Dir': '%s'"\
|
|
% (guid, sdkdir)
|
|
if os.path.isfile(os.path.join(sdkdir, landmark)):
|
|
return sdkdir
|
|
i += 1
|
|
except EnvironmentError:
|
|
pass
|
|
# 4. Vista's SDK
|
|
try:
|
|
key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
|
|
r"Software\Microsoft\Microsoft SDKs\Windows")
|
|
sdkdir, ignore = _winreg.QueryValueEx(key, "CurrentInstallFolder")
|
|
except EnvironmentError:
|
|
pass
|
|
else:
|
|
if DEBUG:
|
|
print r"PSDK: try 'HKLM\Software\Microsoft\MicrosoftSDKs"\
|
|
"\Windows\CurrentInstallFolder': '%s'" % sdkdir
|
|
if os.path.isfile(os.path.join(sdkdir, landmark)):
|
|
return sdkdir
|
|
|
|
# 5. Failing this just try a few well-known default install locations.
|
|
progfiles = os.environ.get("ProgramFiles", r"C:\Program Files")
|
|
defaultlocs = [
|
|
os.path.join(progfiles, "Microsoft Platform SDK"),
|
|
os.path.join(progfiles, "Microsoft SDK"),
|
|
]
|
|
for sdkdir in defaultlocs:
|
|
if DEBUG:
|
|
print "PSDK: try default location: '%s'" % sdkdir
|
|
if os.path.isfile(os.path.join(sdkdir, landmark)):
|
|
return sdkdir
|
|
|
|
|
|
# Some nasty hacks to prevent most of our extensions using a manifest, as
|
|
# the manifest - even without a reference to the CRT assembly - is enough
|
|
# to prevent the extension from loading. For more details, see
|
|
# http://bugs.python.org/issue7833 - that issue has a patch, but it is
|
|
# languishing and will probably never be fixed for Python 2.6...
|
|
if sys.version_info > (2,6):
|
|
from distutils.spawn import spawn
|
|
from distutils.msvc9compiler import MSVCCompiler
|
|
MSVCCompiler._orig_spawn = MSVCCompiler.spawn
|
|
MSVCCompiler._orig_link = MSVCCompiler.link
|
|
|
|
# We need to override this method for versions where issue7833 *has* landed
|
|
# (ie, 2.7 and 3.2+)
|
|
def manifest_get_embed_info(self, target_desc, ld_args):
|
|
_want_assembly_kept = getattr(self, '_want_assembly_kept', False)
|
|
if not _want_assembly_kept:
|
|
return None
|
|
for arg in ld_args:
|
|
if arg.startswith("/MANIFESTFILE:"):
|
|
orig_manifest = arg.split(":", 1)[1]
|
|
if target_desc==self.EXECUTABLE:
|
|
rid = 1
|
|
else:
|
|
rid = 2
|
|
return orig_manifest, rid
|
|
return None
|
|
# always monkeypatch it in even though it will only be called in 2.7
|
|
# and 3.2+.
|
|
MSVCCompiler.manifest_get_embed_info = manifest_get_embed_info
|
|
|
|
def monkeypatched_spawn(self, cmd):
|
|
is_link = cmd[0].endswith("link.exe") or cmd[0].endswith('"link.exe"')
|
|
is_mt = cmd[0].endswith("mt.exe") or cmd[0].endswith('"mt.exe"')
|
|
_want_assembly_kept = getattr(self, '_want_assembly_kept', False)
|
|
if not _want_assembly_kept and is_mt:
|
|
# We don't want mt.exe run...
|
|
return
|
|
if not _want_assembly_kept and is_link:
|
|
# remove /MANIFESTFILE:... and add MANIFEST:NO
|
|
# (but note that for winxpgui, which specifies a manifest via a
|
|
# .rc file, this is ignored by the linker - the manifest specified
|
|
# in the .rc file is still added)
|
|
for i in range(len(cmd)):
|
|
if cmd[i].startswith("/MANIFESTFILE:"):
|
|
cmd[i] = "/MANIFEST:NO"
|
|
break
|
|
if _want_assembly_kept and is_mt:
|
|
# We want mt.exe run with the original manifest
|
|
for i in range(len(cmd)):
|
|
if cmd[i] == "-manifest":
|
|
cmd[i+1] = cmd[i+1] + ".orig"
|
|
break
|
|
self._orig_spawn(cmd)
|
|
if _want_assembly_kept and is_link:
|
|
# We want a copy of the original manifest so we can use it later.
|
|
for i in range(len(cmd)):
|
|
if cmd[i].startswith("/MANIFESTFILE:"):
|
|
mfname = cmd[i][14:]
|
|
shutil.copyfile(mfname, mfname + ".orig")
|
|
break
|
|
|
|
def monkeypatched_link(self, target_desc, objects, output_filename, *args, **kw):
|
|
# no manifests for 3.3+
|
|
self._want_assembly_kept = sys.version_info < (3,3) and \
|
|
(os.path.basename(output_filename).startswith("PyISAPI_loader.dll") or \
|
|
os.path.basename(output_filename).startswith("perfmondata.dll") or \
|
|
os.path.basename(output_filename).startswith("win32ui.pyd") or \
|
|
target_desc==self.EXECUTABLE)
|
|
try:
|
|
return self._orig_link(target_desc, objects, output_filename, *args, **kw)
|
|
finally:
|
|
delattr(self, '_want_assembly_kept')
|
|
MSVCCompiler.spawn = monkeypatched_spawn
|
|
MSVCCompiler.link = monkeypatched_link
|
|
|
|
def find_telldus_dev_dir():
|
|
landmark = "telldus-core.h"
|
|
dev_dir = os.environ.get("TELLDUS_DEVDIR")
|
|
if dev_dir:
|
|
if DEBUG:
|
|
print "Telldus dev dir:" % dev_dir
|
|
if os.path.isfile(os.path.join(dev_dir, landmark)):
|
|
return dev_dir
|
|
|
|
progfiles = os.environ.get("ProgramFiles", r"C:\Program Files")
|
|
defaultlocs = [
|
|
os.path.join(progfiles + ' (x86)', "Telldus", "Development"),
|
|
os.path.join(progfiles, "Telldus", "Development"),
|
|
]
|
|
for dev_dir in defaultlocs:
|
|
if DEBUG:
|
|
print "Telldus dev dir: '%s'" % dev_dir
|
|
if os.path.isfile(os.path.join(dev_dir, landmark)):
|
|
return dev_dir
|
|
if DEBUG:
|
|
print "Telldus dev dir not found, make sure dev code is installed. Or set TELLDUS_DEVDIR."
|
|
|
|
sdk_dir = find_platform_sdk_dir()
|
|
sdk_include_dir = os.path.join(sdk_dir, 'Include')
|
|
|
|
telldus_dev_dir = find_telldus_dev_dir()
|
|
telldus_platform = os.environ.get("TELLDUS_PLATFORM", 'x86_64')
|
|
telldus_library_dir = os.path.join(telldus_dev_dir, telldus_platform)
|
|
|
|
include_dirs = [sdk_include_dir, telldus_dev_dir]
|
|
library_dirs = [telldus_library_dir]
|
|
libraries = ['python%i%i' % (sys.version_info[0], sys.version_info[1]) , 'TelldusCore']
|
|
define_macros = [('_WINDOWS', 1)]
|
|
|
|
else:
|
|
include_dirs = ['/usr/include', '/usr/local/include']
|
|
library_dirs = ['/usr/lib', '/usr/local/lib']
|
|
libraries = ['telldus-core']
|
|
define_macros = []
|
|
|
|
define_macros.extend([('DATA_LENGTH', 20), ('CALLBACK_LENGTH', 20)])
|
|
|
|
telldus = Extension(
|
|
'telldus',
|
|
include_dirs = include_dirs,
|
|
libraries = libraries,
|
|
library_dirs = library_dirs,
|
|
define_macros = define_macros,
|
|
sources = ['telldus.c']
|
|
)
|
|
|
|
setup(
|
|
name = 'telldus',
|
|
version = '1.0',
|
|
description = 'Python bindings for telldus',
|
|
author='Oyvind Saltvik',
|
|
author_email='oyvind.saltvik@gmail.com',
|
|
url='http://github.com/fivethreeo/telldus/',
|
|
ext_modules = [telldus]
|
|
)
|