2 Information about the current system's architecture.
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.
7 For example, it will indicate that:
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.
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.
17 # Copyright (C) 2009, Thomas Leonard
18 # See the README file for details, or visit http://0install.net.
20 from zeroinstall
import _
23 # TODO: "import platform"?
25 # os_ranks and mapping are mappings from names to how good they are.
27 # Higher numbers are worse but usable.
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()
34 _uname
= tuple(list(_uname
[:-1])+['x86_64'])
35 except AttributeError:
36 # No uname. Probably Windows.
40 _uname
= ('Windows', 'x86_64')
42 from win32process
import IsWow64Process
44 _uname
= ('Windows', 'x86_64')
46 _uname
= ('Windows', 'i486')
50 def canonicalize_os(os_
):
51 if os_
.startswith('CYGWIN_NT'):
57 def _get_os_ranks(target_os
):
58 target_os
= canonicalize_os(target_os
)
60 if target_os
== 'Darwin':
61 # Special case Mac OS X, to separate it from Darwin/X
62 # (Mac OS X also includes the closed Apple frameworks)
63 if os
.path
.exists('/System/Library/Frameworks/Carbon.framework'):
66 # Binaries compiled for _this_ OS are best...
67 os_ranks
= {target_os
: 1}
69 # Assume everything supports POSIX except Windows
70 # (but Cygwin is POSIX)
71 if target_os
!= 'Windows':
72 os_ranks
['POSIX'] = len(os_ranks
) + 1
74 # If target_os appears in the first column of this table, all
75 # following OS types on the line will also run on this one
76 # (earlier ones preferred):
78 'Cygwin': ['Windows'],
82 for supported
in _os_matrix
.get(target_os
, []):
83 os_ranks
[supported
] = len(os_ranks
) + 1
85 # At the lowest priority, try an OS-independent implementation
86 os_ranks
[None] = len(os_ranks
) + 1
89 os_ranks
= _get_os_ranks(_uname
[0])
91 # All chosen machine-specific implementations must come from the same group
92 # Unlisted archs are in group 0
98 def canonicalize_machine(machine
):
101 elif machine
== 'amd64':
103 elif machine
== 'Power Macintosh':
105 elif machine
== 'i86pc':
109 def _get_machine_ranks(target_machine
):
110 target_machine
= canonicalize_machine(target_machine
)
112 # Binaries compiled for _this_machine are best...
113 machine_ranks
= {target_machine
: 0}
115 # If target_machine appears in the first column of this table, all
116 # following machine types on the line will also run on this one
117 # (earlier ones preferred):
120 'i586': ['i486', 'i386'],
121 'i686': ['i586', 'i486', 'i386'],
122 'x86_64': ['i686', 'i586', 'i486', 'i386'],
126 for supported
in _machine_matrix
.get(target_machine
, []):
127 machine_ranks
[supported
] = len(machine_ranks
)
129 # At the lowest priority, try a machine-independant implementation
130 machine_ranks
[None] = len(machine_ranks
)
133 machine_ranks
= _get_machine_ranks(_uname
[-1])
136 """A description of an architecture. Use by L{solver} to make sure it chooses
138 @ivar os_ranks: supported operating systems and their desirability
139 @type os_ranks: {str: int}
140 @ivar machine_ranks: supported CPU types and their desirability
141 @type machine_ranks: {str: int}
142 @ivar child_arch: architecture for dependencies (usually C{self})
143 @type child_arch: L{Architecture}
144 @ivar use: matching values for <requires use='...'>; otherwise the dependency is ignored
148 use
= frozenset([None])
150 def __init__(self
, os_ranks
, machine_ranks
):
151 self
.os_ranks
= os_ranks
152 self
.machine_ranks
= machine_ranks
153 self
.child_arch
= self
156 return _("<Arch: %(os_ranks)s %(machine_ranks)s>") % {'os_ranks': self
.os_ranks
, 'machine_ranks': self
.machine_ranks
}
158 class SourceArchitecture(Architecture
):
159 """Matches source code that creates binaries for a particular architecture.
160 Note that the L{child_arch} here is the binary; source code depends on binary tools,
161 not on other source packages.
163 def __init__(self
, binary_arch
):
164 Architecture
.__init
__(self
, binary_arch
.os_ranks
, {'src': 1})
165 self
.child_arch
= binary_arch
167 def get_host_architecture():
168 """Get an Architecture that matches implementations that will run on the host machine.
169 @rtype: L{Architecture}"""
170 return Architecture(os_ranks
, machine_ranks
)
172 def get_architecture(os
, machine
):
173 """Get an Architecture that matches binaries that will work on the given system.
174 @param os: OS type, or None for host's type
175 @param machine: CPU type, or None for host's type
176 @return: an Architecture object
177 @rtype: L{Architecture}"""
180 target_os_ranks
= os_ranks
182 target_os_ranks
= _get_os_ranks(os
)
184 target_machine_ranks
= machine_ranks
186 target_machine_ranks
= _get_machine_ranks(machine
)
188 return Architecture(target_os_ranks
, target_machine_ranks
)