Skip to content

Commit

Permalink
clang-format: Remove version check
Browse files Browse the repository at this point in the history
This commit also speeds up `clang-format` when installed from PyPI. It
detects whether the `clang-format` executable is a Python wrapper and
finds where the actual binary is location.

Co-authored-by: Zohar Malamant <[email protected]>
  • Loading branch information
berland and pinkwah committed Dec 23, 2022
1 parent 8e8a167 commit 41c2259
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
runs-on: "ubuntu-latest"

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

- name: Install dependencies
run: |
Expand Down
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,8 @@ if(MSVC)
add_definitions("/W3 /D_CRT_SECURE_NO_WARNINGS /wd4996")
endif()

list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules "${CMAKE_CURRENT_BINARY_DIR}")
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules
"${CMAKE_CURRENT_BINARY_DIR}")
find_package(CXX11Features)

# -----------------------------------------------------------------
Expand Down
66 changes: 46 additions & 20 deletions script/clang-format
Original file line number Diff line number Diff line change
@@ -1,26 +1,51 @@
#!/usr/bin/env python3
import shutil
import sys
import re
from typing import Generator
from pathlib import Path
from subprocess import check_output, CalledProcessError, STDOUT
from argparse import ArgumentParser
from pathlib import Path
from subprocess import STDOUT, CalledProcessError, check_output
from typing import Iterator, Optional


CLANG_VERSIONS = ("10", "11", "12")
DIRECTORIES = ["applications", "lib"]


def check_version(clang_format: str) -> None:
version_str = check_output([clang_format, "--version"]).decode()
version_res = re.search(r"version (\d+).(\d+).(\d+)", version_str)
assert version_res

major = version_res[1]
if major not in CLANG_VERSIONS:
sys.exit(
f"Version of clang-format ({clang_format}) is {major}, expected it to be one of {', '.join(CLANG_VERSIONS)}"
def find_clang_format_binary(clang_format: Optional[str]) -> Path:
"""
Looks for clang-format binary by searching the PATH environment
variable. Detect if clang-format was installed from PyPI and use the actual
binary rather than the incredibly slow Python wrapper.
"""
if clang_format is None:
clang_format = shutil.which("clang-format")
if clang_format is None:
sys.exit("No viable executable 'clang-format' found in PATH")

with open(clang_format, "rb") as f:
head = f.read(512)

if head[:2] != b"#!":
# File does not contain shebang, assuming real clang-format
print(f"Using clang-format: {clang_format}")
return Path(clang_format)

# Extract everything between '#!' and newline
python_path = head[2:].split(b"\n")[0].decode().strip()

# Locate the Python 'clang-format' module path
mod_path = (
check_output(
[python_path, "-c", "import clang_format;print(clang_format.__file__)"]
)
.decode()
.strip()
)

# We assume that the location of the actual binary is always in the same
# location
clang_format_path = Path(mod_path).parent / "data" / "bin" / "clang-format"

print(f"Using clang-format: {clang_format_path}")
return clang_format_path


def source_root() -> Path:
Expand All @@ -32,7 +57,7 @@ def source_root() -> Path:
return node


def enumerate_sources() -> Generator[Path, None, None]:
def enumerate_sources() -> Iterator[Path]:
root = source_root()
for directory in DIRECTORIES:
for extension in "c", "h", "cpp", "hpp":
Expand All @@ -41,7 +66,7 @@ def enumerate_sources() -> Generator[Path, None, None]:
yield path


def reformat(clang_format: str, dry_run: bool, verbose: bool) -> None:
def reformat(clang_format: Path, dry_run: bool, verbose: bool) -> None:
total = 0
need_reformat = 0
failed_reformat = 0
Expand Down Expand Up @@ -99,7 +124,7 @@ def main() -> None:
)
ap.add_argument(
"--clang-format",
default="clang-format",
type=str,
help="Name/path of the clang-format binary",
)
ap.add_argument(
Expand All @@ -111,8 +136,9 @@ def main() -> None:
)

args = ap.parse_args()
check_version(args.clang_format)
reformat(args.clang_format, args.check, args.verbose)

clang_format = find_clang_format_binary(args.clang_format)
reformat(clang_format, args.check, args.verbose)


if __name__ == "__main__":
Expand Down

0 comments on commit 41c2259

Please sign in to comment.