mirror of https://github.com/mongodb/mongo
SERVER-89878 add support for bazel with coverity (#21587)
GitOrigin-RevId: 4224f8170307bb0288d349c308368127734c7537
This commit is contained in:
parent
d1db0d8291
commit
933cf012ef
4
.bazelrc
4
.bazelrc
|
|
@ -1,5 +1,9 @@
|
|||
# Reference docs: https://bazel.build/run/bazelrc
|
||||
|
||||
# coverity need to use the local command without remote execution auto
|
||||
# enabled.
|
||||
info --config=local
|
||||
|
||||
# This automatically sets a config based on host platform, ex: --config=macos if the host is macos
|
||||
build --enable_platform_specific_config=true
|
||||
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ buildifier
|
|||
.bazelrc.local
|
||||
.bazel_info_for_ninja.txt
|
||||
.ninja_last_command_line_targets.txt
|
||||
bazel/coverity/analysis/BUILD.bazel
|
||||
|
||||
# generated configs for external fixture suites
|
||||
docker_compose/
|
||||
|
|
|
|||
|
|
@ -393,6 +393,15 @@ add_option(
|
|||
help="Compress debug sections",
|
||||
)
|
||||
|
||||
add_option(
|
||||
'coverity-build',
|
||||
action="store_true",
|
||||
default=False,
|
||||
help=(
|
||||
"Enable coverity build mode, which only means the bazel build will not run. "
|
||||
"The bazel build is expected to be run in a prior separate coverity enabled bazel build."),
|
||||
)
|
||||
|
||||
add_option(
|
||||
'sanitize',
|
||||
help='enable selected sanitizers',
|
||||
|
|
|
|||
|
|
@ -20,6 +20,16 @@ load("//bazel/toolchains:python_toolchain.bzl", "setup_mongo_python_toolchains")
|
|||
|
||||
[register_toolchains(toolchain) for toolchain in setup_mongo_python_toolchains()]
|
||||
|
||||
load("//bazel/coverity:coverity_toolchain.bzl", "coverity_toolchain")
|
||||
|
||||
coverity_toolchain(
|
||||
name = "rules_coverity",
|
||||
)
|
||||
|
||||
load("@rules_coverity//coverity:repositories.bzl", "rules_coverity_toolchains")
|
||||
|
||||
rules_coverity_toolchains()
|
||||
|
||||
http_archive(
|
||||
name = "rules_python",
|
||||
sha256 = "8c8fe44ef0a9afc256d1e75ad5f448bb59b81aba149b8958f02f7b3a98f5d9b4",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
def _coverity_toolchain(ctx):
|
||||
result = ctx.execute([
|
||||
"ls",
|
||||
"/data/cov-sa/bin/cov-build",
|
||||
])
|
||||
|
||||
if result.return_code == 0:
|
||||
ctx.report_progress("extracting coverity rules...")
|
||||
result = ctx.download_and_extract("file:///data/cov-sa/bazel/rules_coverity.tar.gz")
|
||||
else:
|
||||
ctx.template(
|
||||
"coverity/BUILD.bazel",
|
||||
ctx.attr.build_tpl,
|
||||
)
|
||||
ctx.template(
|
||||
"coverity/repositories.bzl",
|
||||
ctx.attr.repositories_tpl,
|
||||
)
|
||||
|
||||
coverity_toolchain = repository_rule(
|
||||
implementation = _coverity_toolchain,
|
||||
attrs = {
|
||||
"build_tpl": attr.label(
|
||||
default = "//bazel/coverity:coverity_toolchain.BUILD",
|
||||
doc = "Label denoting the BUILD file template that gets installed in the repo.",
|
||||
),
|
||||
"repositories_tpl": attr.label(
|
||||
default = "//bazel/coverity:repositories.bzl",
|
||||
doc = "Label denoting the repositories files the gets installed to the repo.",
|
||||
),
|
||||
},
|
||||
)
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import io
|
||||
|
||||
# assume we are always running from project root to find buildscripts
|
||||
sys.path.append('.')
|
||||
|
||||
from buildscripts.install_bazel import install_bazel
|
||||
|
||||
bazel_bin_dir = os.path.expanduser("~/.local/bin")
|
||||
if not os.path.exists(bazel_bin_dir):
|
||||
os.makedirs(bazel_bin_dir)
|
||||
|
||||
|
||||
fake_out = io.StringIO()
|
||||
orig_stdout = sys.stdout
|
||||
orig_stderr = sys.stderr
|
||||
sys.stdout = fake_out
|
||||
sys.stderr = fake_out
|
||||
bazel_executable = install_bazel(bazel_bin_dir)
|
||||
sys.stdout = orig_stdout
|
||||
sys.stderr = orig_stderr
|
||||
|
||||
# coverity requires a single target which has dependencies on all
|
||||
# the cc_library and cc_binaries in our build. There is not a good way from
|
||||
# within the build to get all those targets, so we will generate the list via query
|
||||
# https://sig-product-docs.synopsys.com/bundle/coverity-docs/page/coverity-analysis/topics/building_with_bazel.html#build_with_bazel
|
||||
proc = subprocess.run([
|
||||
bazel_executable,
|
||||
"aquery",
|
||||
'--config=local',
|
||||
'mnemonic("CppCompile|LinkCompile", //src/mongo/...)'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
|
||||
targets = []
|
||||
for line in proc.stdout.splitlines():
|
||||
if line.startswith(" Target: "):
|
||||
targets.append(line.split()[-1])
|
||||
|
||||
coverity_dir = os.path.dirname(__file__)
|
||||
analysis_dir = os.path.join(coverity_dir, "analysis")
|
||||
os.makedirs(analysis_dir, exist_ok=True)
|
||||
|
||||
with open(os.path.join(coverity_dir, "analysis", "BUILD.bazel"), 'w') as buildfile:
|
||||
buildfile.write("""\
|
||||
load("@rules_coverity//coverity:defs.bzl", "cov_gen_script")
|
||||
cov_gen_script(
|
||||
name="coverity_build",
|
||||
deps=[
|
||||
""")
|
||||
for target in targets:
|
||||
buildfile.write("""\
|
||||
"%s",
|
||||
""" % target)
|
||||
|
||||
buildfile.write("""\
|
||||
],
|
||||
)
|
||||
""")
|
||||
|
||||
cmd = [
|
||||
sys.executable,
|
||||
"./buildscripts/scons.py",
|
||||
] + sys.argv + [
|
||||
"BAZEL_INTEGRATION_DEBUG=1",
|
||||
"\\$BUILD_ROOT/scons/\\$VARIANT_DIR/sconf_temp"]
|
||||
|
||||
# Run a lightwieght scons build to generate the bazel command.
|
||||
proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
for line in proc.stdout.splitlines():
|
||||
if "BAZEL_COMMAND:" in line:
|
||||
# The script is intended to be have output placed into a bash variable, so we should
|
||||
# only ever print the bazel build command
|
||||
cmd = line.split('BAZEL_COMMAND:')[-1].strip().split()[:-1] + ["//bazel/coverity/analysis:coverity_build"]
|
||||
print(' '.join(cmd))
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
def rules_coverity_toolchains():
|
||||
return None
|
||||
|
|
@ -265,7 +265,7 @@ def ninja_bazel_builder(env: SCons.Environment.Environment, _dup_env: SCons.Envi
|
|||
}
|
||||
|
||||
|
||||
def bazel_build_thread_func(log_dir: str, verbose: bool) -> None:
|
||||
def bazel_build_thread_func(env, log_dir: str, verbose: bool) -> None:
|
||||
"""This thread runs the bazel build up front."""
|
||||
|
||||
done_with_temp = False
|
||||
|
|
@ -277,6 +277,12 @@ def bazel_build_thread_func(log_dir: str, verbose: bool) -> None:
|
|||
|
||||
bazel_cmd = Globals.bazel_base_build_command + extra_args + ['//src/...']
|
||||
bazel_debug(f"BAZEL_COMMAND: {' '.join(bazel_cmd)}")
|
||||
if env.GetOption("coverity-build"):
|
||||
print(
|
||||
"--coverity-build selected, assuming bazel targets were built in a previous coverity run. Not running bazel build."
|
||||
)
|
||||
return
|
||||
|
||||
print("Starting bazel build thread...")
|
||||
|
||||
try:
|
||||
|
|
@ -841,7 +847,8 @@ def generate(env: SCons.Environment.Environment) -> None:
|
|||
|
||||
# ninja will handle the build so do not launch the bazel batch thread
|
||||
bazel_build_thread = threading.Thread(target=bazel_build_thread_func,
|
||||
args=(log_dir, env["VERBOSE"]))
|
||||
args=(env, log_dir, env["VERBOSE"]))
|
||||
|
||||
bazel_build_thread.start()
|
||||
|
||||
def wait_for_bazel(env):
|
||||
|
|
|
|||
Loading…
Reference in New Issue