mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
fix(idf_tools): Fix platform detection for arm64 machine but arm32 environment
This commit is contained in:
parent
13dd2c9aae
commit
c2d6a9e700
@ -162,6 +162,42 @@ class Platforms:
|
||||
'Linux-arm': PLATFORM_LINUX_ARM32,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def detect_linux_arm_platform(supposed_platform): # type: (Optional[str]) -> Optional[str]
|
||||
"""
|
||||
We probe the python binary to check exactly what environment the script is running in.
|
||||
|
||||
ARM platform may run on armhf hardware but having armel installed packages.
|
||||
To avoid possible armel/armhf libraries mixing need to define user's
|
||||
packages architecture to use the same
|
||||
See note section in https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-mfloat-abi
|
||||
|
||||
ARM platform may run on aarch64 hardware but having armhf installed packages
|
||||
(it happens if a docker container is running on arm64 hardware, but using an armhf image).
|
||||
|
||||
"""
|
||||
if supposed_platform not in (PLATFORM_LINUX_ARM32, PLATFORM_LINUX_ARMHF, PLATFORM_LINUX_ARM64):
|
||||
return supposed_platform
|
||||
|
||||
# suppose that installed python was built with the right ABI
|
||||
with open(sys.executable, 'rb') as f:
|
||||
# see ELF header description in https://man7.org/linux/man-pages/man5/elf.5.html, offsets depend on ElfN size
|
||||
if int.from_bytes(f.read(4), sys.byteorder) != int.from_bytes(b'\x7fELF', sys.byteorder):
|
||||
return supposed_platform # ELF magic not found. Use the default platform name from PLATFORM_FROM_NAME
|
||||
f.seek(18) # seek to e_machine
|
||||
e_machine = int.from_bytes(f.read(2), sys.byteorder)
|
||||
if e_machine == 183: # EM_AARCH64, https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst
|
||||
supposed_platform = PLATFORM_LINUX_ARM64
|
||||
elif e_machine == 40: # EM_ARM, https://github.com/ARM-software/abi-aa/blob/main/aaelf32/aaelf32.rst
|
||||
f.seek(36) # seek to e_flags
|
||||
e_flags = int.from_bytes(f.read(4), sys.byteorder)
|
||||
if e_flags & 0x400:
|
||||
supposed_platform = PLATFORM_LINUX_ARMHF
|
||||
else:
|
||||
supposed_platform = PLATFORM_LINUX_ARM32
|
||||
|
||||
return supposed_platform
|
||||
|
||||
@staticmethod
|
||||
def get(platform_alias): # type: (Optional[str]) -> Optional[str]
|
||||
if platform_alias is None:
|
||||
@ -169,21 +205,8 @@ class Platforms:
|
||||
|
||||
if platform_alias == 'any' and CURRENT_PLATFORM:
|
||||
platform_alias = CURRENT_PLATFORM
|
||||
|
||||
platform_name = Platforms.PLATFORM_FROM_NAME.get(platform_alias, None)
|
||||
|
||||
# ARM platform may run on armhf hardware but having armel installed packages.
|
||||
# To avoid possible armel/armhf libraries mixing need to define user's
|
||||
# packages architecture to use the same
|
||||
# See note section in https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html#index-mfloat-abi
|
||||
if platform_name in (PLATFORM_LINUX_ARM32, PLATFORM_LINUX_ARMHF) and 'arm' in platform.machine():
|
||||
# suppose that installed python was built with a right ABI
|
||||
with open(sys.executable, 'rb') as f:
|
||||
if int.from_bytes(f.read(4), sys.byteorder) != int.from_bytes(b'\x7fELF', sys.byteorder):
|
||||
return platform_name # ELF magic not found. Use default platform name from PLATFORM_FROM_NAME
|
||||
f.seek(36) # seek to e_flags (https://man7.org/linux/man-pages/man5/elf.5.html)
|
||||
e_flags = int.from_bytes(f.read(4), sys.byteorder)
|
||||
platform_name = PLATFORM_LINUX_ARMHF if e_flags & 0x400 else PLATFORM_LINUX_ARM32
|
||||
platform_name = Platforms.detect_linux_arm_platform(platform_name)
|
||||
return platform_name
|
||||
|
||||
@staticmethod
|
||||
@ -832,7 +855,7 @@ class IDFTool(object):
|
||||
else:
|
||||
self.versions_installed.append(version)
|
||||
if tool_error:
|
||||
raise ToolBinaryError;
|
||||
raise ToolBinaryError
|
||||
|
||||
def latest_installed_version(self): # type: () -> Optional[str]
|
||||
"""
|
||||
@ -1776,7 +1799,7 @@ def process_tool(
|
||||
|
||||
try:
|
||||
tool.find_installed_versions()
|
||||
except:
|
||||
except ToolBinaryError:
|
||||
tool_found = False
|
||||
recommended_version_to_use = tool.get_preferred_installed_version()
|
||||
|
||||
|
BIN
tools/test_idf_tools/platform_detection/arm32_header.elf
Normal file
BIN
tools/test_idf_tools/platform_detection/arm32_header.elf
Normal file
Binary file not shown.
BIN
tools/test_idf_tools/platform_detection/arm64_header.elf
Normal file
BIN
tools/test_idf_tools/platform_detection/arm64_header.elf
Normal file
Binary file not shown.
BIN
tools/test_idf_tools/platform_detection/armhf_header.elf
Normal file
BIN
tools/test_idf_tools/platform_detection/armhf_header.elf
Normal file
Binary file not shown.
@ -10,6 +10,7 @@ import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
try:
|
||||
from contextlib import redirect_stdout
|
||||
@ -606,5 +607,30 @@ class TestMaintainer(unittest.TestCase):
|
||||
self.assertEqual(json.load(f1), expected_json, "Please check 'tools/tools.new.json' to find a cause!")
|
||||
|
||||
|
||||
class TestArmDetection(unittest.TestCase):
|
||||
|
||||
ELF_HEADERS = {
|
||||
idf_tools.PLATFORM_LINUX_ARM64: 'platform_detection/arm64_header.elf',
|
||||
idf_tools.PLATFORM_LINUX_ARMHF: 'platform_detection/armhf_header.elf',
|
||||
idf_tools.PLATFORM_LINUX_ARM32: 'platform_detection/arm32_header.elf',
|
||||
}
|
||||
|
||||
ARM_PLATFORMS = {
|
||||
idf_tools.PLATFORM_LINUX_ARM64,
|
||||
idf_tools.PLATFORM_LINUX_ARMHF,
|
||||
idf_tools.PLATFORM_LINUX_ARM32,
|
||||
}
|
||||
|
||||
def test_arm_detection(self):
|
||||
for platform in idf_tools.Platforms.PLATFORM_FROM_NAME.values():
|
||||
with patch('sys.executable', __file__): # use invalid ELF as executable. In this case passed parameter must return
|
||||
self.assertEqual(idf_tools.Platforms.detect_linux_arm_platform(platform), platform)
|
||||
# detect_linux_arm_platform() intended to return arch that detected in sys.executable ELF
|
||||
for exec_platform in (idf_tools.PLATFORM_LINUX_ARM64, idf_tools.PLATFORM_LINUX_ARMHF, idf_tools.PLATFORM_LINUX_ARM32):
|
||||
with patch('sys.executable', TestArmDetection.ELF_HEADERS[exec_platform]):
|
||||
for platform in TestArmDetection.ARM_PLATFORMS:
|
||||
self.assertEqual(idf_tools.Platforms.detect_linux_arm_platform(platform), exec_platform)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user