-
Notifications
You must be signed in to change notification settings - Fork 70
/
clang_format.py
125 lines (101 loc) · 3.84 KB
/
clang_format.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/python3
# SPDX-License-Identifier: Apache-2.0
# Copyright (C) ifm electronic gmbh
#
# THE PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
# Provides functions to format C/C++ files using clang-format
import shutil
import re
import subprocess
import os
import multiprocessing
import functools
import sys
assert sys.version_info > (3, 5), "python 3.5 or more required"
max_parallel_process = 10
# The bare Minimum clang-format version
minimum_required_clang_format_version = "10.0.0"
# Extension and folders to be excludes from formatting
apply_extensions = (".cxx", ".cpp", ".c", ".hxx", ".hh", ".cc", ".hpp", ".h")
include_folders = ["modules", "examples"]
exclude_folders = ["modules/device/include/ifm3d/contrib"]
#making path accorinding to OS
exclude_folders = list(map(lambda rel_path : os.path.normcase(os.path.join("", os.path.relpath(rel_path))), exclude_folders))
def format_file(clangf_exe, file, dry_run=False):
args = [clangf_exe, "-i", "-style=file"]
if dry_run:
args.append("--dry-run")
args.append("--Werror")
return subprocess.call([*args, file]) == 0
def clang_format(clangf_exe, dry_run=False):
"""
Function runs the clang formatter on the files
with extension mention in 'apply_extensions' and
in the folders mentioned in 'include_folders'
Return:
(bool) True if all files are formatted else
False.
"""
filelist = []
# walk all the folders from the current wotking directory
for dir in include_folders:
for root, dirs, files in os.walk(os.path.join(os.getcwd(), dir)):
if os.path.relpath(root, os.getcwd()) in exclude_folders:
files[:] = []
dirs[:] = []
# loop over files
for file in files:
# check for file extension
if file.endswith(apply_extensions):
filelist.append(os.path.join(root, file))
with multiprocessing.Pool(max_parallel_process) as p:
try:
return all(p.map(functools.partial(format_file, clangf_exe, dry_run=dry_run), filelist))
except Exception as e:
print("Error with formatting file", e)
return False
def check_clang_format_version(clangf_exe):
"""
Function checks the version of the clang-formatter
available with the host system
"""
try:
_minimum_version_num = int(
minimum_required_clang_format_version.replace('.', ''))
if shutil.which(clangf_exe):
ret = os.popen("{} --version".format(clangf_exe)).read()
tokens = re.search("^(\w+-\w+) (\w+) ([0-9.]+).*", ret)
if tokens.group(1) == "clang-format" and tokens.group(2) == "version":
_current_version_num = int(tokens.group(3).replace(".", ""))
if _current_version_num >= _minimum_version_num:
return True
else:
return False
else:
return False
else:
return False
except:
return False
# entry point
if __name__ == "__main__":
# build a list of possible clang-format versions
clang_executables = ['clang-format']
for i in range(10, 99):
clang_executables.append("clang-format-{}".format(i))
# check if the appropriate one is installed
clangf_exe = None
for i in clang_executables:
if check_clang_format_version(i):
clangf_exe = i
break
# bail out in case no clang-format was found
if clangf_exe is None:
print("Please install clang-format version {}".format(minimum_required_clang_format_version))
quit(1)
dry_run = "check" in sys.argv
# do the formatting
ok = clang_format(clangf_exe, dry_run=dry_run)
if ok:
print(f"{'Formatting' if not dry_run else 'Checking'} done!")
quit(0 if ok else 1)