| |
@@ -0,0 +1,372 @@
|
| |
+ #!/usr/bin/python
|
| |
+
|
| |
+ # A copy of some necessary parts from yum.rpmUtils.arch, with slightly changes:
|
| |
+ # 1. _ppc64_native_is_best changed to True
|
| |
+ # 2. code style fixes for flake8 reported errors
|
| |
+
|
| |
+ import os
|
| |
+ import rpm
|
| |
+ import ctypes
|
| |
+ import struct
|
| |
+
|
| |
+ # _ppc64_native_is_best is False in yum's source code, but patched with a
|
| |
+ # seperate patch when built from source rpm, so we set it to True here.
|
| |
+ _ppc64_native_is_best = True
|
| |
+
|
| |
+ # dict mapping arch -> ( multicompat, best personality, biarch personality )
|
| |
+ multilibArches = {"x86_64": ("athlon", "x86_64", "athlon"),
|
| |
+ "sparc64v": ("sparcv9v", "sparcv9v", "sparc64v"),
|
| |
+ "sparc64": ("sparcv9", "sparcv9", "sparc64"),
|
| |
+ "ppc64": ("ppc", "ppc", "ppc64"),
|
| |
+ "s390x": ("s390", "s390x", "s390"),
|
| |
+ }
|
| |
+ if _ppc64_native_is_best:
|
| |
+ multilibArches["ppc64"] = ("ppc", "ppc64", "ppc64")
|
| |
+
|
| |
+ arches = {
|
| |
+ # ia32
|
| |
+ "athlon": "i686",
|
| |
+ "i686": "i586",
|
| |
+ "geode": "i586",
|
| |
+ "i586": "i486",
|
| |
+ "i486": "i386",
|
| |
+ "i386": "noarch",
|
| |
+
|
| |
+ # amd64
|
| |
+ "x86_64": "athlon",
|
| |
+ "amd64": "x86_64",
|
| |
+ "ia32e": "x86_64",
|
| |
+
|
| |
+ # ppc64le
|
| |
+ "ppc64le": "noarch",
|
| |
+
|
| |
+ # ppc
|
| |
+ "ppc64p7": "ppc64",
|
| |
+ "ppc64pseries": "ppc64",
|
| |
+ "ppc64iseries": "ppc64",
|
| |
+ "ppc64": "ppc",
|
| |
+ "ppc": "noarch",
|
| |
+
|
| |
+ # s390{,x}
|
| |
+ "s390x": "s390",
|
| |
+ "s390": "noarch",
|
| |
+
|
| |
+ # sparc
|
| |
+ "sparc64v": "sparcv9v",
|
| |
+ "sparc64": "sparcv9",
|
| |
+ "sparcv9v": "sparcv9",
|
| |
+ "sparcv9": "sparcv8",
|
| |
+ "sparcv8": "sparc",
|
| |
+ "sparc": "noarch",
|
| |
+
|
| |
+ # alpha
|
| |
+ "alphaev7": "alphaev68",
|
| |
+ "alphaev68": "alphaev67",
|
| |
+ "alphaev67": "alphaev6",
|
| |
+ "alphaev6": "alphapca56",
|
| |
+ "alphapca56": "alphaev56",
|
| |
+ "alphaev56": "alphaev5",
|
| |
+ "alphaev5": "alphaev45",
|
| |
+ "alphaev45": "alphaev4",
|
| |
+ "alphaev4": "alpha",
|
| |
+ "alpha": "noarch",
|
| |
+
|
| |
+ # arm
|
| |
+ "armv7l": "armv6l",
|
| |
+ "armv6l": "armv5tejl",
|
| |
+ "armv5tejl": "armv5tel",
|
| |
+ "armv5tel": "noarch",
|
| |
+
|
| |
+ # arm hardware floating point
|
| |
+ "armv7hnl": "armv7hl",
|
| |
+ "armv7hl": "armv6hl",
|
| |
+ "armv6hl": "noarch",
|
| |
+
|
| |
+ # arm64
|
| |
+ "arm64": "noarch",
|
| |
+
|
| |
+ # aarch64
|
| |
+ "aarch64": "noarch",
|
| |
+
|
| |
+ # super-h
|
| |
+ "sh4a": "sh4",
|
| |
+ "sh4": "noarch",
|
| |
+ "sh3": "noarch",
|
| |
+
|
| |
+ # itanium
|
| |
+ "ia64": "noarch",
|
| |
+ }
|
| |
+
|
| |
+ # Will contain information parsed from /proc/self/auxv via _parse_auxv().
|
| |
+ # Should move into rpm really.
|
| |
+ _aux_vector = {
|
| |
+ "platform": "",
|
| |
+ "hwcap": 0,
|
| |
+ }
|
| |
+
|
| |
+
|
| |
+ def isMultiLibArch(arch=None):
|
| |
+ """returns true if arch is a multilib arch, false if not"""
|
| |
+ if arch is None:
|
| |
+ arch = canonArch
|
| |
+
|
| |
+ if arch not in arches: # or we could check if it is noarch
|
| |
+ return 0
|
| |
+
|
| |
+ if arch in multilibArches:
|
| |
+ return 1
|
| |
+
|
| |
+ if arches[arch] in multilibArches:
|
| |
+ return 1
|
| |
+
|
| |
+ return 0
|
| |
+
|
| |
+
|
| |
+ def getArchList(thisarch=None):
|
| |
+ # this returns a list of archs that are compatible with arch given
|
| |
+ if not thisarch:
|
| |
+ thisarch = canonArch
|
| |
+
|
| |
+ archlist = [thisarch]
|
| |
+ while thisarch in arches:
|
| |
+ thisarch = arches[thisarch]
|
| |
+ archlist.append(thisarch)
|
| |
+
|
| |
+ # hack hack hack
|
| |
+ # sparc64v is also sparc64 compat
|
| |
+ if archlist[0] == "sparc64v":
|
| |
+ archlist.insert(1, "sparc64")
|
| |
+
|
| |
+ # if we're a weirdo arch - add noarch on there.
|
| |
+ if len(archlist) == 1 and archlist[0] == thisarch:
|
| |
+ archlist.append('noarch')
|
| |
+ return archlist
|
| |
+
|
| |
+
|
| |
+ def _try_read_cpuinfo():
|
| |
+ """ Try to read /proc/cpuinfo ... if we can't ignore errors (ie. proc not
|
| |
+ mounted). """
|
| |
+ try:
|
| |
+ return open("/proc/cpuinfo", "r")
|
| |
+ except:
|
| |
+ return []
|
| |
+
|
| |
+
|
| |
+ def _parse_auxv():
|
| |
+ """ Read /proc/self/auxv and parse it into global dict for easier access
|
| |
+ later on, very similar to what rpm does. """
|
| |
+ # In case we can't open and read /proc/self/auxv, just return
|
| |
+ try:
|
| |
+ data = open("/proc/self/auxv", "rb").read()
|
| |
+ except:
|
| |
+ return
|
| |
+
|
| |
+ # Define values from /usr/include/elf.h
|
| |
+ AT_PLATFORM = 15
|
| |
+ AT_HWCAP = 16
|
| |
+ fmtlen = struct.calcsize("LL")
|
| |
+ offset = 0
|
| |
+ platform = ctypes.c_char_p()
|
| |
+
|
| |
+ # Parse the data and fill in _aux_vector dict
|
| |
+ while offset <= len(data) - fmtlen:
|
| |
+ at_type, at_val = struct.unpack_from("LL", data, offset)
|
| |
+ if at_type == AT_PLATFORM:
|
| |
+ platform.value = at_val
|
| |
+ _aux_vector["platform"] = platform.value
|
| |
+ if at_type == AT_HWCAP:
|
| |
+ _aux_vector["hwcap"] = at_val
|
| |
+ offset = offset + fmtlen
|
| |
+
|
| |
+
|
| |
+ def getCanonX86Arch(arch):
|
| |
+ if arch == "i586":
|
| |
+ for line in _try_read_cpuinfo():
|
| |
+ if line.startswith("model name"):
|
| |
+ if line.find("Geode(TM)") != -1:
|
| |
+ return "geode"
|
| |
+ break
|
| |
+ return arch
|
| |
+ # only athlon vs i686 isn't handled with uname currently
|
| |
+ if arch != "i686":
|
| |
+ return arch
|
| |
+
|
| |
+ # if we're i686 and AuthenticAMD, then we should be an athlon
|
| |
+ for line in _try_read_cpuinfo():
|
| |
+ if line.startswith("vendor") and line.find("AuthenticAMD") != -1:
|
| |
+ return "athlon"
|
| |
+ # i686 doesn't guarantee cmov, but we depend on it
|
| |
+ elif line.startswith("flags"):
|
| |
+ if line.find("cmov") == -1:
|
| |
+ return "i586"
|
| |
+ break
|
| |
+
|
| |
+ return arch
|
| |
+
|
| |
+
|
| |
+ def getCanonARMArch(arch):
|
| |
+ # the %{_target_arch} macro in rpm will let us know the abi we are using
|
| |
+ target = rpm.expandMacro('%{_target_cpu}')
|
| |
+ if target.startswith('armv6h'):
|
| |
+ return target
|
| |
+ if target.startswith('armv7h'):
|
| |
+ return target
|
| |
+ return arch
|
| |
+
|
| |
+
|
| |
+ def getCanonPPCArch(arch):
|
| |
+ # FIXME: should I do better handling for mac, etc?
|
| |
+ if arch != "ppc64":
|
| |
+ return arch
|
| |
+
|
| |
+ machine = None
|
| |
+ for line in _try_read_cpuinfo():
|
| |
+ if line.find("machine") != -1:
|
| |
+ machine = line.split(':')[1]
|
| |
+ break
|
| |
+
|
| |
+ platform = _aux_vector["platform"]
|
| |
+ if machine is None and not platform:
|
| |
+ return arch
|
| |
+
|
| |
+ try:
|
| |
+ if platform.startswith("power") and int(platform[5:].rstrip('+')) >= 7:
|
| |
+ return "ppc64p7"
|
| |
+ except:
|
| |
+ pass
|
| |
+
|
| |
+ if machine is None:
|
| |
+ return arch
|
| |
+
|
| |
+ if machine.find("CHRP IBM") != -1:
|
| |
+ return "ppc64pseries"
|
| |
+ if machine.find("iSeries") != -1:
|
| |
+ return "ppc64iseries"
|
| |
+ return arch
|
| |
+
|
| |
+
|
| |
+ def getCanonSPARCArch(arch):
|
| |
+ # Deal with sun4v, sun4u, sun4m cases
|
| |
+ SPARCtype = None
|
| |
+ for line in _try_read_cpuinfo():
|
| |
+ if line.startswith("type"):
|
| |
+ SPARCtype = line.split(':')[1]
|
| |
+ break
|
| |
+ if SPARCtype is None:
|
| |
+ return arch
|
| |
+
|
| |
+ if SPARCtype.find("sun4v") != -1:
|
| |
+ if arch.startswith("sparc64"):
|
| |
+ return "sparc64v"
|
| |
+ else:
|
| |
+ return "sparcv9v"
|
| |
+ if SPARCtype.find("sun4u") != -1:
|
| |
+ if arch.startswith("sparc64"):
|
| |
+ return "sparc64"
|
| |
+ else:
|
| |
+ return "sparcv9"
|
| |
+ if SPARCtype.find("sun4m") != -1:
|
| |
+ return "sparcv8"
|
| |
+ return arch
|
| |
+
|
| |
+
|
| |
+ def getCanonX86_64Arch(arch):
|
| |
+ if arch != "x86_64":
|
| |
+ return arch
|
| |
+
|
| |
+ vendor = None
|
| |
+ for line in _try_read_cpuinfo():
|
| |
+ if line.startswith("vendor_id"):
|
| |
+ vendor = line.split(':')[1]
|
| |
+ break
|
| |
+ if vendor is None:
|
| |
+ return arch
|
| |
+
|
| |
+ if vendor.find("Authentic AMD") != -1 or vendor.find("AuthenticAMD") != -1:
|
| |
+ return "amd64"
|
| |
+ if vendor.find("GenuineIntel") != -1:
|
| |
+ return "ia32e"
|
| |
+ return arch
|
| |
+
|
| |
+
|
| |
+ def getCanonArch(skipRpmPlatform=0):
|
| |
+ if not skipRpmPlatform and os.access("/etc/rpm/platform", os.R_OK):
|
| |
+ try:
|
| |
+ f = open("/etc/rpm/platform", "r")
|
| |
+ line = f.readline()
|
| |
+ f.close()
|
| |
+ (arch, vendor, opersys) = line.split("-", 2)
|
| |
+ return arch
|
| |
+ except:
|
| |
+ pass
|
| |
+
|
| |
+ arch = os.uname()[4]
|
| |
+
|
| |
+ _parse_auxv()
|
| |
+
|
| |
+ if (len(arch) == 4 and arch[0] == "i" and arch[2:4] == "86"):
|
| |
+ return getCanonX86Arch(arch)
|
| |
+
|
| |
+ if arch.startswith("arm"):
|
| |
+ return getCanonARMArch(arch)
|
| |
+ if arch.startswith("ppc"):
|
| |
+ return getCanonPPCArch(arch)
|
| |
+ if arch.startswith("sparc"):
|
| |
+ return getCanonSPARCArch(arch)
|
| |
+ if arch == "x86_64":
|
| |
+ return getCanonX86_64Arch(arch)
|
| |
+
|
| |
+ return arch
|
| |
+
|
| |
+ canonArch = getCanonArch()
|
| |
+
|
| |
+
|
| |
+ # this gets you the "compat" arch of a biarch pair
|
| |
+ def getMultiArchInfo(arch=canonArch):
|
| |
+ if arch in multilibArches:
|
| |
+ return multilibArches[arch]
|
| |
+ if arch in arches and arches[arch] != "noarch":
|
| |
+ return getMultiArchInfo(arch=arches[arch])
|
| |
+ return None
|
| |
+
|
| |
+
|
| |
+ def getBaseArch(myarch=None):
|
| |
+ """returns 'base' arch for myarch, if specified, or canonArch if not.
|
| |
+ base arch is the arch before noarch in the arches dict if myarch is not
|
| |
+ a key in the multilibArches."""
|
| |
+
|
| |
+ if not myarch:
|
| |
+ myarch = canonArch
|
| |
+
|
| |
+ if myarch not in arches: # this is dumb, but <shrug>
|
| |
+ return myarch
|
| |
+
|
| |
+ if myarch.startswith("sparc64"):
|
| |
+ return "sparc"
|
| |
+ elif myarch == "ppc64le":
|
| |
+ return "ppc64le"
|
| |
+ elif myarch.startswith("ppc64") and not _ppc64_native_is_best:
|
| |
+ return "ppc"
|
| |
+ elif myarch.startswith("arm64"):
|
| |
+ return "arm64"
|
| |
+ elif myarch.startswith("armv6h"):
|
| |
+ return "armhfp"
|
| |
+ elif myarch.startswith("armv7h"):
|
| |
+ return "armhfp"
|
| |
+ elif myarch.startswith("arm"):
|
| |
+ return "arm"
|
| |
+
|
| |
+ if isMultiLibArch(arch=myarch):
|
| |
+ if myarch in multilibArches:
|
| |
+ return myarch
|
| |
+ else:
|
| |
+ return arches[myarch]
|
| |
+
|
| |
+ if myarch in arches:
|
| |
+ basearch = myarch
|
| |
+ value = arches[basearch]
|
| |
+ while value != 'noarch':
|
| |
+ basearch = value
|
| |
+ value = arches[basearch]
|
| |
+
|
| |
+ return basearch
|
| |
In case of the absenence of rpmUtils in new version of systems, we need to
drop the dependency of rpmUtils. DNF doesn't provide the mapping APIs in
rpmUtils, the only one available in dnf is getBaseArch and doesn't
support getting current system's arch, dnf detects the os with hawkey.
Since the most tricky part in rpmUtils.arch is detecting the current
system's arch and we can't easy test this to ensure no regression will be
introduced by using hawkey, it would be much safer to just copy the necessary
parts from rpmUtils.arch to pungi to remove the dependency.
FIXES: #533
Signed-off-by: Qixiang Wan qwan@redhat.com