Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# clang-tools

[![PyPI](https://img.shields.io/pypi/v/clang-tools)](https://pypi.org/project/clang-tools/) [![Python test](https://github.com/shenxianpeng/clang-tools-pip/actions/workflows/python-test.yml/badge.svg)](https://github.com/shenxianpeng/clang-tools-pip/actions/workflows/python-test.yml) [![codecov](https://codecov.io/gh/shenxianpeng/clang-tools-pip/branch/master/graph/badge.svg?token=40G5ZOIRRR)](https://codecov.io/gh/shenxianpeng/clang-tools-pip) [![Platfrom](https://img.shields.io/badge/platform-linux--64%20%7C%20win--64%20%7C%20osx--64%20-blue)](https://pypi.org/project/clang-tools/)
[![PyPI](https://img.shields.io/pypi/v/clang-tools)](https://pypi.org/project/clang-tools/) [![Python test](https://github.com/shenxianpeng/clang-tools-pip/actions/workflows/python-test.yml/badge.svg)](https://github.com/shenxianpeng/clang-tools-pip/actions/workflows/python-test.yml) [![codecov](https://codecov.io/gh/shenxianpeng/clang-tools-pip/branch/master/graph/badge.svg?token=40G5ZOIRRR)](https://codecov.io/gh/shenxianpeng/clang-tools-pip) [![Platfrom](https://img.shields.io/badge/platform-linux--64%20%7C%20win--64%20%7C%20osx--64%20-blue)](https://pypi.org/project/clang-tools/) ![PyPI - Downloads](https://img.shields.io/pypi/dw/clang-tools)


Install clang-tools binaries (clang-format, clang-tidy) with pip.

Expand Down Expand Up @@ -45,7 +46,21 @@ LLVM (http://llvm.org/):

## Supported versions

| verions | 14 | 13 | 12.0.1 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3.9 |
|:------------:|:--:|:--:|:------:|:--:|:--:|:--:|:-:|:-:|:-:|:-:|:-:|:-:|:---:|
| clang-format | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| clang-tidy | ❌ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
### clang-format
| Version | 14 | 13 | 12.0.1 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3.9 |
|:-------:|:--:|:--:|:------:|:--:|:--:|:--:|:-:|:-:|:-:|:-:|:-:|:-:|:---:|
| Linux | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Windows | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| macOS | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |

### clang-tidy

| Version | 14 | 13 | 12.0.1 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3.9 |
|:-------:|:--:|:--:|:------:|:--:|:--:|:--:|:-:|:-:|:-:|:-:|:-:|:-:|:---:|
| Linux | ❌ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Windows | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| macOS | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |

Know issue: clang-tidy version 14 has Segmentation fault (core dumped).

Thanks to the project [clang-tools-static-binaries](https://github.com/muttleyxd/clang-tools-static-binaries) for all the binaries.
8 changes: 4 additions & 4 deletions clang_tools/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ def move_and_chmod_binary(old_file_name, new_file_name, directory) -> None:
if directory:
install_dir = directory
else:
install_os = check_install_os()
if install_os not in ['linux', 'macosx', 'windows']:
raise SystemExit(f"Not support {install_os}")
install_dir = os.path.dirname(sys.executable)
try:
if not os.path.isdir(install_dir):
os.makedirs(install_dir)
shutil.move(old_file_name, f"{install_dir}/{new_file_name}")
os.chmod(os.path.join(install_dir, new_file_name), 0o755)
except PermissionError:
raise SystemExit("You don't have permission. Try to run with the appropriate permissions.")
raise SystemExit(
f"Don't have permission to install {new_file_name} to {install_dir}. \
Try to run with the appropriate permissions."
)


def install_clang_tools(version, directory) -> None:
Expand Down
16 changes: 10 additions & 6 deletions clang_tools/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import sys
import argparse
from clang_tools.install import install_clang_tools


def main() -> int:
def parse_args(args):
parser = argparse.ArgumentParser(prog='clang-tools')

parser.add_argument(
"-i",
"--install",
default="12",
help="Install clang-tools with specific version. default is 12.",
default="13",
help="Install clang-tools with specific version. default is 13.",
)

parser.add_argument(
Expand All @@ -18,13 +19,16 @@ def main() -> int:
default="",
help="The directory where is the clang-tools install.",
)
args = parser.parse_args()
return parser.parse_args()


def main():
args = parse_args(sys.argv[1:])

version = args.install
directory = args.directory

install_clang_tools(version, directory)


if __name__ == '__main__':
raise SystemExit(main())
main()
18 changes: 7 additions & 11 deletions clang_tools/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import string
import subprocess
from urllib.error import HTTPError
import urllib.request
import platform

Expand All @@ -9,23 +8,20 @@ def check_install_os() -> string:
os = platform.system().lower()
if os == "darwin":
os = "macosx"
if os not in ['linux', 'macosx', 'windows']:
raise SystemExit(f"Not support {os}")
return os


def download_file(url, file_name) -> None:
def download_file(url, file_name) -> string:
try:
urllib.request.urlretrieve(url, file_name)
except HTTPError:
raise SystemExit(f"Not found {file_name}, exit!")
file, _ = urllib.request.urlretrieve(url, file_name)
except ValueError:
return None
return file


def unpack_file(file_name) -> int:
command = ["tar", "-xvf", file_name]
result = subprocess.run(command, stdout=subprocess.PIPE)
return result.returncode


def cmake_and_build():
command = []
result = subprocess.run(command, stdout=subprocess.PIPE)
print(result.stdout.decode("utf-8"))
23 changes: 23 additions & 0 deletions tests/test_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import pytest
from clang_tools.install import check_install_os
from clang_tools.install import clang_format_exist
from clang_tools.install import clang_tidy_exist
from clang_tools.install import clang_tools_binary_url


@pytest.mark.parametrize(('version', 'expected'), (('12', True), ('100', False)))
def test_clang_tools_exist(version, expected):
assert clang_format_exist(version) == expected
assert clang_tidy_exist(version) == expected


def test_clang_tools_binary_url():
tools = ['clang-format', 'clang-tidy']
version = 12
os = check_install_os()
for tool in tools:
ret = clang_tools_binary_url(tool, version)
if os == 'windows':
assert(f"{tool}-{version}_{os}-amd64.exe" in ret)
else:
assert(f"{tool}-{version}_{os}-amd64" in ret)
13 changes: 13 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest
from unittest import mock
from clang_tools.main import main


@pytest.mark.parametrize("argv, called, response", [(['-i'], True, False), (['-d'], True, False)])
def test_main_install(argv, called, response):
with mock.patch('sys.argv', [''] + argv):
if called and not response:
with pytest.raises(SystemExit):
main()
else:
main()
35 changes: 16 additions & 19 deletions tests/test_util.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import os
import shutil
from unittest import mock
from clang_tools.util import check_install_os, download_file, unpack_file

TEST_REPO = "https://github.com/shenxianpeng/clang-tools-pip"


def test_check_install_os():
install_os = check_install_os()
assert install_os in ("linux", "windos", "macosx")


def test_download_file():
url = f"{TEST_REPO}/blob/master/README.md"
file_name = "test_file"
download_file(url, file_name)
assert os.path.exists(file_name)
os.remove(file_name)
assert not os.path.exists(file_name)
@mock.patch('clang_tools.util.urllib.request.urlretrieve')
def test_fail_download_file(mock_request):
mock_result = mock.MagicMock()
attrs = {'mock_result.return_value': 'file.tar.gz'}
mock_result.configure_mock(**attrs)
mock_request.return_value = mock_result
file_name = download_file('https://www.google.com', 'file.tar.gz')
assert file_name is None


def test_unpack_file():
url = f"{TEST_REPO}/archive/refs/tags/v0.1.0.tar.gz"
file_name = "test_file.tar.gz"
download_file(url, file_name)
status = unpack_file(file_name)
assert status == 0
os.remove(file_name)
shutil.rmtree("clang-tools-pip-0.1.0")
@mock.patch('clang_tools.util.subprocess.run')
def test_unpack_file(mock_run):
mock_stdout = mock.Mock()
mock_stdout.configure_mock(**{"returncode": '0'})
mock_run.return_value = mock_stdout
result = unpack_file('file.tar.gz')
assert result == '0'