forked from espressif/esp-idf
feat(tools): Add standalone Clang libraries to tools.json
This commit is contained in:
@@ -43,6 +43,11 @@ On Linux and macOS, it is recommended to install CMake using the OS-specific pac
|
||||
.. tool-esp-clang-notes
|
||||
|
||||
|
||||
---
|
||||
|
||||
.. tool-esp-clang-libs-notes
|
||||
|
||||
|
||||
---
|
||||
|
||||
.. tool-ninja-notes
|
||||
|
@@ -43,6 +43,11 @@ On Linux and macOS, it is recommended to install CMake using the OS-specific pac
|
||||
.. tool-esp-clang-notes
|
||||
|
||||
|
||||
---
|
||||
|
||||
.. tool-esp-clang-libs-notes
|
||||
|
||||
|
||||
---
|
||||
|
||||
.. tool-ninja-notes
|
||||
|
@@ -82,7 +82,7 @@ TOOLS_FILE = 'tools/tools.json'
|
||||
TOOLS_SCHEMA_FILE = 'tools/tools_schema.json'
|
||||
TOOLS_FILE_NEW = 'tools/tools.new.json'
|
||||
IDF_ENV_FILE = 'idf-env.json'
|
||||
TOOLS_FILE_VERSION = 2
|
||||
TOOLS_FILE_VERSION = 3
|
||||
IDF_TOOLS_PATH_DEFAULT = os.path.join('~', '.espressif')
|
||||
UNKNOWN_VERSION = 'unknown'
|
||||
SUBST_TOOL_PATH_REGEX = re.compile(r'\${TOOL_PATH}')
|
||||
@@ -789,6 +789,7 @@ IDFToolOptions = namedtuple('IDFToolOptions', [
|
||||
'version_regex',
|
||||
'version_regex_replace',
|
||||
'is_executable',
|
||||
'tool_info_file',
|
||||
'export_paths',
|
||||
'export_vars',
|
||||
'install',
|
||||
@@ -818,7 +819,8 @@ class IDFTool(object):
|
||||
supported_targets: List[str],
|
||||
version_regex_replace: Optional[str] = None,
|
||||
strip_container_dirs: int = 0,
|
||||
is_executable: bool = True) -> None:
|
||||
is_executable: bool = True,
|
||||
tool_info_file: str = '') -> None:
|
||||
self.name = name
|
||||
self.description = description
|
||||
self.drop_versions()
|
||||
@@ -826,12 +828,13 @@ class IDFTool(object):
|
||||
self.versions_installed: List[str] = []
|
||||
if version_regex_replace is None:
|
||||
version_regex_replace = VERSION_REGEX_REPLACE_DEFAULT
|
||||
self.options = IDFToolOptions(version_cmd, version_regex, version_regex_replace, is_executable,
|
||||
self.options = IDFToolOptions(version_cmd, version_regex, version_regex_replace, is_executable, tool_info_file,
|
||||
[], OrderedDict(), install, info_url, license, strip_container_dirs, supported_targets) # type: ignore
|
||||
self.platform_overrides: List[Dict[str, str]] = []
|
||||
self._platform = CURRENT_PLATFORM
|
||||
self._update_current_options()
|
||||
self.is_executable = is_executable
|
||||
self.tool_info_file = tool_info_file
|
||||
|
||||
def copy_for_platform(self, platform: str) -> 'IDFTool':
|
||||
"""
|
||||
@@ -905,6 +908,16 @@ class IDFTool(object):
|
||||
result[k] = v_repl
|
||||
return result
|
||||
|
||||
def parse_tool_version(self, ver_str: str) -> str:
|
||||
"""
|
||||
Extract the version string from the provided input and return it as a result.
|
||||
Returns 'unknown' if version string can not be extracted..
|
||||
"""
|
||||
match = re.search(self._current_options.version_regex, ver_str) # type: ignore
|
||||
if not match:
|
||||
return UNKNOWN_VERSION
|
||||
return re.sub(self._current_options.version_regex, self._current_options.version_regex_replace, match.group(0)) # type: ignore
|
||||
|
||||
def get_version(self, extra_paths: Optional[List[str]] = None, executable_path: Optional[str] = None) -> str:
|
||||
"""
|
||||
Execute the tool, optionally prepending extra_paths to PATH,
|
||||
@@ -934,17 +947,39 @@ class IDFTool(object):
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise ToolExecError(f'non-zero exit code ({e.returncode}) with message: {e.stderr.decode("utf-8",errors="ignore")}') # type: ignore
|
||||
|
||||
in_str = version_cmd_result.decode('utf-8')
|
||||
match = re.search(self._current_options.version_regex, in_str) # type: ignore
|
||||
if not match:
|
||||
return UNKNOWN_VERSION
|
||||
return re.sub(self._current_options.version_regex, self._current_options.version_regex_replace, match.group(0)) # type: ignore
|
||||
return self.parse_tool_version(version_cmd_result.decode('utf-8'))
|
||||
|
||||
def get_version_from_file(self, version: str) -> str:
|
||||
"""
|
||||
Extract the version string from tool info file and return it as a result.
|
||||
Returns 'unknown' if version string can not be extracted.
|
||||
"""
|
||||
# this function can not be called for a different platform
|
||||
assert self._platform == CURRENT_PLATFORM
|
||||
# Replace '/' with OS specific path separator
|
||||
info_file_path = os.path.join(*self.tool_info_file.split('/'))
|
||||
info_file_path = os.path.join(self.get_path_for_version(version), info_file_path)
|
||||
if not os.path.exists(info_file_path):
|
||||
raise ToolNotFoundError(f'Tool {self.name} not found: No info file.')
|
||||
with open(info_file_path, 'r', encoding='utf-8') as f:
|
||||
try:
|
||||
tool_info = json.load(f)
|
||||
except (json.JSONDecodeError, UnicodeDecodeError):
|
||||
raise ToolNotFoundError(f'Tool {self.name} not found: Bad info file.')
|
||||
|
||||
if 'version' not in tool_info:
|
||||
raise ToolNotFoundError(f'Tool {self.name} not found: No version in info file.')
|
||||
|
||||
return self.parse_tool_version(tool_info['version'])
|
||||
|
||||
def check_binary_valid(self, version: str) -> bool:
|
||||
if not self.is_executable:
|
||||
return True
|
||||
try:
|
||||
ver_str = self.get_version(self.get_export_paths(version))
|
||||
if self.tool_info_file:
|
||||
ver_str = self.get_version_from_file(version)
|
||||
else:
|
||||
ver_str = self.get_version(self.get_export_paths(version))
|
||||
except (ToolNotFoundError, ToolExecError) as e:
|
||||
fatal(f'tool {self.name} version {version} is installed, but getting error: {e}')
|
||||
return False
|
||||
@@ -1028,17 +1063,18 @@ class IDFTool(object):
|
||||
# this function can not be called for a different platform
|
||||
assert self._platform == CURRENT_PLATFORM
|
||||
tool_error = False
|
||||
# First check if the tool is in system PATH
|
||||
try:
|
||||
ver_str = self.get_version()
|
||||
except ToolNotFoundError:
|
||||
# not in PATH
|
||||
pass
|
||||
except ToolExecError as e:
|
||||
fatal(f'tool {self.name} is found in PATH, but has failed: {e}')
|
||||
tool_error = True
|
||||
else:
|
||||
self.version_in_path = ver_str
|
||||
if not self.tool_info_file:
|
||||
# First check if the tool is in system PATH
|
||||
try:
|
||||
ver_str = self.get_version()
|
||||
except ToolNotFoundError:
|
||||
# not in PATH
|
||||
pass
|
||||
except ToolExecError as e:
|
||||
fatal(f'tool {self.name} is found in PATH, but has failed: {e}')
|
||||
tool_error = True
|
||||
else:
|
||||
self.version_in_path = ver_str
|
||||
|
||||
# Now check all the versions installed in GlobalVarsStore.idf_tools_path
|
||||
self.versions_installed = []
|
||||
@@ -1053,7 +1089,10 @@ class IDFTool(object):
|
||||
self.versions_installed.append(version)
|
||||
continue
|
||||
try:
|
||||
ver_str = self.get_version(self.get_export_paths(version))
|
||||
if self.tool_info_file:
|
||||
ver_str = self.get_version_from_file(version)
|
||||
else:
|
||||
ver_str = self.get_version(self.get_export_paths(version))
|
||||
except ToolNotFoundError as e:
|
||||
warn(f'directory for tool {self.name} version {version} is present, but the tool has not been found: {e}')
|
||||
except ToolExecError as e:
|
||||
@@ -1083,7 +1122,10 @@ class IDFTool(object):
|
||||
# export paths list directly here.
|
||||
paths = [os.path.join(tool_path, version, *p) for p in self._current_options.export_paths]
|
||||
try:
|
||||
ver_str = self.get_version(paths)
|
||||
if self.tool_info_file:
|
||||
ver_str = self.get_version_from_file(version)
|
||||
else:
|
||||
ver_str = self.get_version(paths)
|
||||
except (ToolNotFoundError, ToolExecError):
|
||||
continue
|
||||
if ver_str != version:
|
||||
@@ -1191,6 +1233,10 @@ class IDFTool(object):
|
||||
if not isinstance(is_executable, bool):
|
||||
raise RuntimeError(f'is_executable for tool {tool_name} is not a bool')
|
||||
|
||||
tool_info_file = tool_dict.get('tool_info_file', '')
|
||||
if not isinstance(tool_info_file, str):
|
||||
raise RuntimeError(f'tool_info_file for tool {tool_name} is not a string')
|
||||
|
||||
version_cmd = tool_dict.get('version_cmd')
|
||||
if type(version_cmd) is not list:
|
||||
raise RuntimeError(f'version_cmd for tool {tool_name} is not a list of strings')
|
||||
@@ -1242,7 +1288,7 @@ class IDFTool(object):
|
||||
# Create the object
|
||||
tool_obj: 'IDFTool' = cls(tool_name, description, install, info_url, license, # type: ignore
|
||||
version_cmd, version_regex, supported_targets, version_regex_replace, # type: ignore
|
||||
strip_container_dirs, is_executable) # type: ignore
|
||||
strip_container_dirs, is_executable, tool_info_file) # type: ignore
|
||||
|
||||
for path in export_paths: # type: ignore
|
||||
tool_obj.options.export_paths.append(path) # type: ignore
|
||||
@@ -1371,6 +1417,8 @@ class IDFTool(object):
|
||||
tool_json['strip_container_dirs'] = self.options.strip_container_dirs
|
||||
if self.options.is_executable is False:
|
||||
tool_json['is_executable'] = self.options.is_executable
|
||||
if self.options.tool_info_file:
|
||||
tool_json['tool_info_file'] = self.options.tool_info_file
|
||||
return tool_json
|
||||
|
||||
|
||||
|
@@ -300,6 +300,67 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Standalone Clang shared libraries distribution",
|
||||
"export_paths": [],
|
||||
"export_vars": {},
|
||||
"info_url": "https://github.com/espressif/llvm-project",
|
||||
"install": "on_request",
|
||||
"license": "Apache-2.0",
|
||||
"name": "esp-clang-libs",
|
||||
"supported_targets": [
|
||||
"esp32",
|
||||
"esp32s2",
|
||||
"esp32s3",
|
||||
"esp32c3",
|
||||
"esp32c2",
|
||||
"esp32c6",
|
||||
"esp32c5",
|
||||
"esp32h2",
|
||||
"esp32p4",
|
||||
"esp32c61",
|
||||
"esp32h21"
|
||||
],
|
||||
"tool_info_file": "esp-clang/esp-clang-libs.info",
|
||||
"version_cmd": [],
|
||||
"version_regex": "([0-9a-zA-Z\\.\\-_]+)",
|
||||
"versions": [
|
||||
{
|
||||
"linux-amd64": {
|
||||
"sha256": "c13b8a731beec0c2af56f94073ca17202c9e5047de4c6e61f5e3ed319d231962",
|
||||
"size": 76164612,
|
||||
"url": "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312/libs-clang-esp-19.1.2_20250312-x86_64-linux-gnu.tar.xz"
|
||||
},
|
||||
"linux-arm64": {
|
||||
"sha256": "dcf356d2a12eaf9660aa5e91cd70df14486d4bd45f47a8025327255b2fe3ece8",
|
||||
"size": 69938392,
|
||||
"url": "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312/libs-clang-esp-19.1.2_20250312-aarch64-linux-gnu.tar.xz"
|
||||
},
|
||||
"linux-armhf": {
|
||||
"sha256": "e9e110841ffdd43c7fcc57de24f501eec917a02e54f6dbf3a2069fed1017f8a8",
|
||||
"size": 72698812,
|
||||
"url": "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312/libs-clang-esp-19.1.2_20250312-arm-linux-gnueabihf.tar.xz"
|
||||
},
|
||||
"macos": {
|
||||
"sha256": "0ac4cf2340e766a240ae40519f404fceaea4262d5ab89292aa3a4118e6402492",
|
||||
"size": 58104496,
|
||||
"url": "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312/libs-clang-esp-19.1.2_20250312-x86_64-apple-darwin.tar.xz"
|
||||
},
|
||||
"macos-arm64": {
|
||||
"sha256": "d723ce5ae431b44305c888c989e7f405446a23c13f179edc1b6939f9ba437498",
|
||||
"size": 48707440,
|
||||
"url": "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312/libs-clang-esp-19.1.2_20250312-aarch64-apple-darwin.tar.xz"
|
||||
},
|
||||
"name": "esp-19.1.2_20250312",
|
||||
"status": "recommended",
|
||||
"win64": {
|
||||
"sha256": "29e5c945f601b85dd88c29bfabfd8c592d8064e3aba01d946e0ff475e5810c17",
|
||||
"size": 59681772,
|
||||
"url": "https://github.com/espressif/llvm-project/releases/download/esp-19.1.2_20250312/libs-clang-esp-19.1.2_20250312-x86_64-w64-mingw32.tar.xz"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Toolchain for 32-bit RISC-V based on GCC",
|
||||
"export_paths": [
|
||||
@@ -985,5 +1046,5 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 2
|
||||
"version": 3
|
||||
}
|
||||
|
@@ -72,6 +72,10 @@
|
||||
"description": "If given, this will be used as substitute expression for the regex defined in version_regex, to obtain the version string. Not specifying this is equivalent to setting it to '\\1' (i.e. return the first capture group).",
|
||||
"type": "string"
|
||||
},
|
||||
"tool_info_file": {
|
||||
"description": "Tools info file path. Relative to tool install folder. If present tool version will be read from it instead of invoking the binary.",
|
||||
"type": "string"
|
||||
},
|
||||
"strip_container_dirs": {
|
||||
"type": "integer",
|
||||
"description": "If specified, this number of top directory levels will removed when extracting. E.g. if strip_container_dirs=2, archive path a/b/c/d.txt will be extracted as c/d.txt"
|
||||
@@ -286,5 +290,26 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"$comment": "Condition verifying that version <=2 of tools.json must not contain 'tool_info_file' keyword in any of #/definitions/toolInfo properties.",
|
||||
"if": {
|
||||
"properties": {
|
||||
"version": {
|
||||
"maximum": 2
|
||||
}
|
||||
}
|
||||
},
|
||||
"then": {
|
||||
"properties": {
|
||||
"tools": {
|
||||
"items": {
|
||||
"not": {
|
||||
"required": [
|
||||
"tool_info_file"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user