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] )