Skip to content
Draft
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
22 changes: 22 additions & 0 deletions cc/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ config_setting(
visibility = ["//visibility:public"],
)

bool_flag(
name = "strong_stack_protector",
build_setting_default = False,
visibility = ["//visibility:public"],
)

config_setting(
name = "_strong_stack_protector",
flag_values = {":strong_stack_protector": "true"},
visibility = ["//visibility:public"],
)

# Enable warnings in tests for deprecated declarations with --@rules_swiftnav//cc:tests_warn_deprecated_declarations=true
bool_flag(
name = "tests_warn_deprecated_declarations",
Expand Down Expand Up @@ -162,6 +174,7 @@ config_setting(
visibility = ["//visibility:public"],
)


selects.config_setting_group(
name = "enable_symbolizer_x86_64_linux",
match_all = [
Expand Down Expand Up @@ -224,3 +237,12 @@ py_binary(
],
visibility = ["//visibility:public"],
)

py_binary(
name = "checktags",
srcs = [
"checktags.py",
],
args = [],
visibility = ["//visibility:public"],
)
195 changes: 195 additions & 0 deletions cc/checktags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#!/bin/env python

import subprocess
import json
import os
import re

os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"])

targets = {}

def run_bazel(args):
#print(args)
proc = subprocess.run(["bazel"] + args, capture_output=True, text=True)
return str(proc.stdout)


def get_target_list(kind):
stdout = run_bazel(["cquery", f"kind(\"{kind}\", //...)", "--output=label"])
lines = stdout.split('\n')
ret = [l.split(' ')[0] for l in lines]
return ret


def maybe_add_target(json):
global targets
if 'target' not in json:
return
if 'rule' not in json['target']:
return
t = json['target']['rule']

if t['ruleClass'] not in ["cc_library", "cc_binary", "cc_test", "cmake"]:
return

name = t['name']


if name in targets:
return

#print(name)

targets[name] = {}
targets[name]['tags'] = []
targets[name]['deps'] = []

for a in t['attribute']:
if a['name'] == 'tags':
if 'stringListValue' in a:
targets[name]['tags'] = a['stringListValue']

if a['name'] == 'deps':
if 'stringListValue' in a:
targets[name]['deps'] = a['stringListValue']


def process_deps_for_target(name):
global targets
if name == '':
return
if name in targets:
return

stdout = run_bazel(["cquery", f"\"{name}\"", "--output=jsonproto"])
info = json.loads(stdout)
maybe_add_target(info['results'][0])

stdout = run_bazel(["cquery", f"kind(\"cc_library\", deps(\"{name}\"))", "--output=jsonproto"])
info = json.loads(stdout)

for lib in info['results']:
maybe_add_target(lib)

#for t in get_target_list("cc_binary"):
#process_deps_for_target(t)
#for t in get_target_list("cc_test"):
#process_deps_for_target(t)
#for t in get_target_list("cc_library"):
#process_deps_for_target(t)

def process_target_list(json):
if 'results' not in json:
return
for t in json['results']:
maybe_add_target(t)

def add_all_from_query(key):
stdout = run_bazel(["cquery", key, "--output=jsonproto"])
process_target_list(json.loads(stdout))

print("Loading targets")
add_all_from_query("kind(\"cc_binary\", //...)")
add_all_from_query("kind(\"cc_test\", //...)")
add_all_from_query("kind(\"cc_library\", //...)")
add_all_from_query("deps(kind(\"cc_binary\", //...))")
add_all_from_query("deps(kind(\"cc_test\", //...))")
add_all_from_query("deps(kind(\"cc_library\", //...))")

def get_level_as_num(name):
if 'internal' in targets[name]['tags']:
return 0
if 'prod' in targets[name]['tags']:
return 1
if 'safe' in targets[name]['tags']:
return 2
return None

def level_to_str(level):
if level == 0:
return "internal"
if level == 1:
return "prod"
if level == 2:
return "safe"
assert False

# Targets which don't belong to swift and won't follow the same tagging scheme in bazel
whitelist = [
r"@eigen//.*",
r"@g(oogle)*test//.*",
r"@rules_fuzzing//.*",
r"@benchmark//.*",
r"@benchmark//.*",
r"@rapidcheck//.*",
r"@gmock-global//.*",
r"@check//.*",
r"@nanopb//.*",
r"@@.*",
r"@bazel.*",
r"@gflags//.*",
r"@json//.*",
r"@fast_csv//.*",
r"@yaml-cpp//.*",
r"@nlopt//.*",
r"@com_google_protobuf//.*",
r"@hdf5//.*",
r"@netcdf.*",
r"@variant//.*",
r"@zlib//.*",
r"@zstd//.*",
r"@optional//.*",
r"@ionosphere_models//.*",
r"@rules_cc//.*",
r"@suitesparse//.*",
r"@ThreadPool//.*",
r"@cereal//.*",
r"@gzip//.*",
r"@boringssl//.*",
# libfuzzer targets
r".*_raw_",
]

def is_whitelisted(name):
for r in whitelist:
if re.match(r, name):
return True

return False

def validate_target(name):
if is_whitelisted(name):
return

level = get_level_as_num(name)
portable = False
if 'portable' in targets[name]['tags']:
portable = True

if level is None:
print(f"ERROR: Target {name} doesn't have a coding standard level")
else:
for d in targets[name]['deps']:
if d not in targets:
print(f"{d} not found in bazel....")
elif not is_whitelisted(d):
dep_level = get_level_as_num(d)
if dep_level is None:
print(f"ERROR: Target {name} has a coding standard level but depends on {d} which doesn't")
else:
if dep_level < level:
print(f"ERROR: Target {name} depends on {d} which has a lower coding standard level ({level_to_str(level)} vs {level_to_str(dep_level)}")

if portable:
if 'portable' not in targets[d]['tags']:
print(f"ERROR: Target {name} is a portable target but depends on {d} which is not portable")

for t in sorted(targets.keys()):
validate_target(t)






5 changes: 5 additions & 0 deletions cc/constraints/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ constraint_value(
constraint_setting = ":toolchain",
)

constraint_value(
name = "gcc_11_system_toolchain",
constraint_setting = ":toolchain",
)

constraint_value(
name = "yocto_generic_toolchain",
constraint_setting = ":toolchain",
Expand Down
Loading
Loading