Upgrade clang-tidy on CI. (#5469)
* Correct all clang-tidy errors. * Upgrade clang-tidy to 10 on CI. Co-authored-by: Hyunsu Cho <chohyu01@cs.washington.edu>
This commit is contained in:
@@ -7,14 +7,19 @@ ENV DEBIAN_FRONTEND noninteractive
|
||||
# Install all basic requirements
|
||||
RUN \
|
||||
apt-get update && \
|
||||
apt-get install -y tar unzip wget git build-essential python3 python3-pip llvm-7 clang-tidy-7 clang-7 && \
|
||||
apt-get install -y tar unzip wget git build-essential python3 python3-pip software-properties-common \
|
||||
apt-transport-https ca-certificates gnupg-agent && \
|
||||
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - && \
|
||||
add-apt-repository -u 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' && \
|
||||
apt-get update && \
|
||||
apt-get install -y llvm-10 clang-tidy-10 clang-10 && \
|
||||
wget -nv -nc https://cmake.org/files/v3.12/cmake-3.12.0-Linux-x86_64.sh --no-check-certificate && \
|
||||
bash cmake-3.12.0-Linux-x86_64.sh --skip-license --prefix=/usr
|
||||
|
||||
# Set default clang-tidy version
|
||||
RUN \
|
||||
update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-7 100 && \
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100
|
||||
update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-10 100 && \
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 100
|
||||
|
||||
# Install Python packages
|
||||
RUN \
|
||||
|
||||
@@ -8,6 +8,7 @@ import os
|
||||
import sys
|
||||
import re
|
||||
import argparse
|
||||
from time import time
|
||||
|
||||
|
||||
def call(args):
|
||||
@@ -16,7 +17,10 @@ def call(args):
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
error_msg = completed.stdout.decode('utf-8')
|
||||
matched = re.search('(src|tests)/.*warning:', error_msg,
|
||||
# `workspace` is a name used in Jenkins CI. Normally we should keep the
|
||||
# dir as `xgboost`.
|
||||
matched = re.search('(workspace|xgboost)/.*(src|tests|include)/.*warning:',
|
||||
error_msg,
|
||||
re.MULTILINE)
|
||||
if matched is None:
|
||||
return_code = 0
|
||||
@@ -38,6 +42,11 @@ class ClangTidy(object):
|
||||
self.cuda_lint = args.cuda
|
||||
self.use_dmlc_gtest = args.use_dmlc_gtest
|
||||
|
||||
if args.tidy_version:
|
||||
self.exe = 'clang-tidy-' + str(args.tidy_version)
|
||||
else:
|
||||
self.exe = 'clang-tidy'
|
||||
|
||||
print('Run linter on CUDA: ', self.cuda_lint)
|
||||
print('Run linter on C++:', self.cpp_lint)
|
||||
print('Use dmlc gtest:', self.use_dmlc_gtest)
|
||||
@@ -49,6 +58,7 @@ class ClangTidy(object):
|
||||
self.cdb_path = os.path.join(self.root_path, 'cdb')
|
||||
|
||||
def __enter__(self):
|
||||
self.start = time()
|
||||
if os.path.exists(self.cdb_path):
|
||||
shutil.rmtree(self.cdb_path)
|
||||
self._generate_cdb()
|
||||
@@ -57,6 +67,8 @@ class ClangTidy(object):
|
||||
def __exit__(self, *args):
|
||||
if os.path.exists(self.cdb_path):
|
||||
shutil.rmtree(self.cdb_path)
|
||||
self.end = time()
|
||||
print('Finish running clang-tidy:', self.end - self.start)
|
||||
|
||||
def _generate_cdb(self):
|
||||
'''Run CMake to generate compilation database.'''
|
||||
@@ -84,7 +96,7 @@ class ClangTidy(object):
|
||||
# check each component in a command
|
||||
converted_components = [compiler]
|
||||
|
||||
for i in range(len(components)):
|
||||
for i in range(1, len(components)):
|
||||
if components[i] == '-lineinfo':
|
||||
continue
|
||||
elif components[i] == '-fuse-ld=gold':
|
||||
@@ -119,6 +131,8 @@ class ClangTidy(object):
|
||||
else:
|
||||
converted_components.append(components[i])
|
||||
|
||||
converted_components.append('-isystem /usr/local/cuda/include/')
|
||||
|
||||
command = ''
|
||||
for c in converted_components:
|
||||
command = command + ' ' + c
|
||||
@@ -126,8 +140,14 @@ class ClangTidy(object):
|
||||
return command
|
||||
|
||||
def _configure_flags(self, path, command):
|
||||
common_args = ['clang-tidy',
|
||||
"-header-filter='(xgboost\\/src|xgboost\\/include)'",
|
||||
src = os.path.join(self.root_path, 'src')
|
||||
src = src.replace('/', '\\/')
|
||||
include = os.path.join(self.root_path, 'include')
|
||||
include = include.replace('/', '\\/')
|
||||
|
||||
header_filter = '(' + src + '|' + include + ')'
|
||||
common_args = [self.exe,
|
||||
"-header-filter=" + header_filter,
|
||||
'-config='+self.clang_tidy]
|
||||
common_args.append(path)
|
||||
common_args.append('--')
|
||||
@@ -166,6 +186,7 @@ class ClangTidy(object):
|
||||
isxgb = isxgb and path.find('dmlc-core') == -1
|
||||
isxgb = isxgb and (not path.startswith(self.cdb_path))
|
||||
if isxgb:
|
||||
print(path)
|
||||
return True
|
||||
|
||||
cdb_file = os.path.join(self.cdb_path, 'compile_commands.json')
|
||||
@@ -179,7 +200,6 @@ class ClangTidy(object):
|
||||
for entry in self.compile_commands:
|
||||
path = entry['file']
|
||||
if should_lint(path):
|
||||
print(path)
|
||||
args = self._configure_flags(path, entry['command'])
|
||||
all_files.extend(args)
|
||||
return all_files
|
||||
@@ -191,7 +211,7 @@ class ClangTidy(object):
|
||||
BAR = '-'*32
|
||||
with Pool(cpu_count()) as pool:
|
||||
results = pool.map(call, all_files)
|
||||
for (process_status, tidy_status, msg) in results:
|
||||
for i, (process_status, tidy_status, msg) in enumerate(results):
|
||||
# Don't enforce clang-tidy to pass for now due to namespace
|
||||
# for cub in thrust is not correct.
|
||||
if tidy_status == 1:
|
||||
@@ -202,11 +222,12 @@ class ClangTidy(object):
|
||||
'Message:\n', msg,
|
||||
BAR, '\n')
|
||||
if not passed:
|
||||
print('Please correct clang-tidy warnings.')
|
||||
print('Errors in `thrust` namespace can be safely ignored.',
|
||||
'Please address rest of the clang-tidy warnings.')
|
||||
return passed
|
||||
|
||||
|
||||
def test_tidy():
|
||||
def test_tidy(args):
|
||||
'''See if clang-tidy and our regex is working correctly. There are
|
||||
many subtleties we need to be careful. For instances:
|
||||
|
||||
@@ -233,7 +254,11 @@ right keywords?
|
||||
tidy_config = fd.read()
|
||||
tidy_config = str(tidy_config)
|
||||
tidy_config = '-config='+tidy_config
|
||||
args = ['clang-tidy', tidy_config, test_file_path]
|
||||
if not args.tidy_version:
|
||||
tidy = 'clang-tidy'
|
||||
else:
|
||||
tidy = 'clang-tidy-' + str(args.tidy_version)
|
||||
args = [tidy, tidy_config, test_file_path]
|
||||
(proc_code, tidy_status, error_msg) = call(args)
|
||||
assert proc_code == 0
|
||||
assert tidy_status == 1
|
||||
@@ -243,12 +268,14 @@ right keywords?
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Run clang-tidy.')
|
||||
parser.add_argument('--cpp', type=int, default=1)
|
||||
parser.add_argument('--tidy-version', type=int, default=None,
|
||||
help='Specify the version of preferred clang-tidy.')
|
||||
parser.add_argument('--cuda', type=int, default=1)
|
||||
parser.add_argument('--use-dmlc-gtest', type=int, default=1,
|
||||
help='Whether to use gtest bundled in dmlc-core.')
|
||||
args = parser.parse_args()
|
||||
|
||||
test_tidy()
|
||||
test_tidy(args)
|
||||
|
||||
with ClangTidy(args) as linter:
|
||||
passed = linter.run()
|
||||
|
||||
Reference in New Issue
Block a user