Package zeroinstall :: Package injector :: Module arch
[frames] | no frames]

Source Code for Module zeroinstall.injector.arch

  1  """ 
  2  Information about the current system's architecture. 
  3   
  4  This module provides information about the current system. It is used to determine 
  5  whether an implementation is suitable for this machine, and to compare different implementations. 
  6   
  7  For example, it will indicate that: 
  8   
  9   - An i486 machine cannot run an i686 binary. 
 10   - An i686 machine can run an i486 binary, but would prefer an i586 one. 
 11   - A Windows binary cannot run on a Linux machine. 
 12   
 13  Each dictionary maps from a supported architecture type to a preference level. Lower numbers are 
 14  better, Unsupported architectures are not listed at all. 
 15  """ 
 16   
 17  # Copyright (C) 2009, Thomas Leonard 
 18  # See the README file for details, or visit http://0install.net. 
 19   
 20  from zeroinstall import _ 
 21  import os 
 22   
 23  # TODO: "import platform"? 
 24   
 25  # os_ranks and mapping are mappings from names to how good they are. 
 26  # 1 => Native (best) 
 27  # Higher numbers are worse but usable. 
 28  try: 
 29          _uname = os.uname() 
 30          # On Darwin, machine is wrong. 
 31          if _uname[0] == 'Darwin' and _uname[-1] == 'i386': 
 32                  _cpu64 = os.popen('sysctl -n hw.cpu64bit_capable 2>&1').next().strip() 
 33                  if _cpu64 == '1': 
 34                          _uname = tuple(list(_uname[:-1])+['x86_64']) 
 35  except AttributeError: 
 36          # No uname. Probably Windows. 
 37          import sys 
 38          p = sys.platform 
 39          if p == 'win64': 
 40                  _uname = ('Windows', 'x86_64') 
 41          elif p == 'win32': 
 42                  from win32process import IsWow64Process 
 43                  if IsWow64Process(): 
 44                          _uname = ('Windows', 'x86_64') 
 45                  else: 
 46                          _uname = ('Windows', 'i486') 
 47          else: 
 48                  _uname = (p, 'i486') 
 49   
50 -def canonicalize_os(os_):
51 """@type os_: str 52 @rtype: str""" 53 if os_.startswith('CYGWIN_NT'): 54 os_ = 'Cygwin' 55 elif os_ == 'SunOS': 56 os_ = 'Solaris' 57 return os_
58
59 -def _get_os_ranks(target_os):
60 """@type target_os: str""" 61 target_os = canonicalize_os(target_os) 62 63 if target_os == 'Darwin': 64 # Special case Mac OS X, to separate it from Darwin/X 65 # (Mac OS X also includes the closed Apple frameworks) 66 if os.path.exists('/System/Library/Frameworks/Carbon.framework'): 67 target_os = 'MacOSX' 68 69 # Binaries compiled for _this_ OS are best... 70 os_ranks = {target_os : 1} 71 72 # Assume everything supports POSIX except Windows 73 # (but Cygwin is POSIX) 74 if target_os != 'Windows': 75 os_ranks['POSIX'] = len(os_ranks) + 1 76 77 # If target_os appears in the first column of this table, all 78 # following OS types on the line will also run on this one 79 # (earlier ones preferred): 80 _os_matrix = { 81 'Cygwin': ['Windows'], 82 'MacOSX': ['Darwin'], 83 } 84 85 for supported in _os_matrix.get(target_os, []): 86 os_ranks[supported] = len(os_ranks) + 1 87 88 # At the lowest priority, try an OS-independent implementation 89 os_ranks[None] = len(os_ranks) + 1 90 return os_ranks
91 92 os_ranks = _get_os_ranks(_uname[0]) 93 94 # All chosen machine-specific implementations must come from the same group 95 # Unlisted archs are in group 0 96 machine_groups = { 97 'x86_64': 64, 98 'ppc64': 64, 99 } 100
101 -def canonicalize_machine(machine_):
102 """@type machine_: str 103 @rtype: str""" 104 machine = machine_.lower() 105 if machine == 'x86': 106 machine = 'i386' 107 elif machine == 'amd64': 108 machine = 'x86_64' 109 elif machine == 'Power Macintosh': 110 machine = 'ppc' 111 elif machine == 'i86pc': 112 machine = 'i686' 113 return machine
114
115 -def _get_machine_ranks(target_machine):
116 """@type target_machine: str""" 117 target_machine = canonicalize_machine(target_machine) 118 119 # Binaries compiled for _this_machine are best... 120 machine_ranks = {target_machine : 0} 121 122 # If target_machine appears in the first column of this table, all 123 # following machine types on the line will also run on this one 124 # (earlier ones preferred): 125 _machine_matrix = { 126 'i486': ['i386'], 127 'i586': ['i486', 'i386'], 128 'i686': ['i586', 'i486', 'i386'], 129 'x86_64': ['i686', 'i586', 'i486', 'i386'], 130 'ppc': ['ppc32'], 131 'ppc64': ['ppc'], 132 } 133 for supported in _machine_matrix.get(target_machine, []): 134 machine_ranks[supported] = len(machine_ranks) 135 136 # At the lowest priority, try a machine-independant implementation 137 machine_ranks[None] = len(machine_ranks) 138 return machine_ranks
139 140 machine_ranks = _get_machine_ranks(_uname[-1]) 141
142 -class Architecture(object):
143 """A description of an architecture. Use by L{solver} to make sure it chooses 144 compatible versions. 145 @ivar os_ranks: supported operating systems and their desirability 146 @type os_ranks: {str: int} 147 @ivar machine_ranks: supported CPU types and their desirability 148 @type machine_ranks: {str: int} 149 @ivar child_arch: architecture for dependencies (usually C{self}) 150 @type child_arch: L{Architecture} 151 @ivar use: matching values for <requires use='...'>; otherwise the dependency is ignored 152 @type use: set(str) 153 """ 154 155 use = frozenset([None]) 156
157 - def __init__(self, os_ranks, machine_ranks):
158 self.os_ranks = os_ranks 159 self.machine_ranks = machine_ranks 160 self.child_arch = self
161
162 - def __str__(self):
163 """@rtype: str""" 164 return _("<Arch: %(os_ranks)s %(machine_ranks)s>") % {'os_ranks': self.os_ranks, 'machine_ranks': self.machine_ranks}
165
166 -class SourceArchitecture(Architecture):
167 """Matches source code that creates binaries for a particular architecture. 168 Note that the L{child_arch} here is the binary; source code depends on binary tools, 169 not on other source packages. 170 """
171 - def __init__(self, binary_arch):
172 """@type binary_arch: L{Architecture}""" 173 Architecture.__init__(self, binary_arch.os_ranks, {'src': 1}) 174 self.child_arch = binary_arch
175
176 -def get_host_architecture():
177 """Get an Architecture that matches implementations that will run on the host machine. 178 @rtype: L{Architecture}""" 179 return Architecture(os_ranks, machine_ranks)
180
181 -def get_architecture(os, machine):
182 """Get an Architecture that matches binaries that will work on the given system. 183 @param os: OS type, or None for host's type 184 @type os: str 185 @param machine: CPU type, or None for host's type 186 @type machine: str 187 @return: an Architecture object 188 @rtype: L{Architecture}""" 189 190 if os is None: 191 target_os_ranks = os_ranks 192 else: 193 target_os_ranks = _get_os_ranks(os) 194 if machine is None: 195 target_machine_ranks = machine_ranks 196 else: 197 target_machine_ranks = _get_machine_ranks(machine) 198 199 return Architecture(target_os_ranks, target_machine_ranks)
200