From c6e86604be48995ad4c58965053ce447062b6b56 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Tue, 8 Jul 2025 20:03:57 +0200 Subject: [PATCH] Implement Bazel Clang toolchain --- .bazelrc | 29 +- BUILD.bazel | 11 - MODULE.bazel | 10 +- MODULE.bazel.lock | 16 + asl/base/annotations.hpp | 4 +- asl/base/assert.hpp | 4 +- asl/base/bit_tests.cpp | 5 + asl/base/integers.hpp | 8 +- asl/memory/allocator.cpp | 12 +- bazel/clang_toolchain/BUILD.bazel | 4 + bazel/clang_toolchain/clang_config.bzl.tpl | 8 + .../clang_toolchain.BUILD.bazel | 18 + bazel/clang_toolchain/config_detection.bzl | 113 ++++ bazel/clang_toolchain/toolchain_config.bzl | 596 ++++++++++++++++++ refresh_clangd.sh | 2 +- todo.txt | 7 +- tools/fix_line_endings.py | 1 + 17 files changed, 794 insertions(+), 54 deletions(-) create mode 100644 bazel/clang_toolchain/BUILD.bazel create mode 100644 bazel/clang_toolchain/clang_config.bzl.tpl create mode 100644 bazel/clang_toolchain/clang_toolchain.BUILD.bazel create mode 100644 bazel/clang_toolchain/config_detection.bzl create mode 100644 bazel/clang_toolchain/toolchain_config.bzl diff --git a/.bazelrc b/.bazelrc index 81e46ce..e373b30 100644 --- a/.bazelrc +++ b/.bazelrc @@ -7,15 +7,8 @@ build:windows --enable_runfiles=true build --enable_platform_specific_config build --build_python_zip=false -build:windows --extra_execution_platforms=//:x64_windows-clang-cl -build:windows --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl - -build:linux --repo_env=CC=clang - -build:windows --cxxopt=-Xclang=-std=c++23 -build:linux --cxxopt=-std=c++23 - -build --cxxopt=-Wall +build --features=c++23 +build --cxxopt=-Weverything build --cxxopt=-Wno-c++98-compat build --cxxopt=-Wno-c++98-compat-pedantic build --cxxopt=-Wno-pre-c++17-compat @@ -28,21 +21,7 @@ build --cxxopt=-Wno-global-constructors build --cxxopt=-Wno-unsafe-buffer-usage build --cxxopt=-Wno-covered-switch-default build --cxxopt=-Wno-unused-command-line-argument - -build:windows_san --config=windows -build:windows_san --copt=-fno-sanitize-ignorelist -build:windows_san --copt=-fsanitize=address -build:windows_san --copt=-fsanitize=undefined -build:windows_san --copt=-fno-sanitize-recover=all -build:windows_san --linkopt=clang_rt.asan_dynamic-x86_64.lib -build:windows_san --linkopt=clang_rt.asan_dynamic_runtime_thunk-x86_64.lib - -build:linux_san --config=linux -build:linux_san --copt=-fsanitize=address -build:linux_san --linkopt=-fsanitize=address -build:linux_san --copt=-fsanitize=undefined -build:linux_san --copt=-fno-sanitize-recover=all -build:linux_san --linkopt=-fsanitize=undefined -build:linux_san --linkopt=-fsanitize-link-c++-runtime +build --cxxopt=-Wno-padded +build --cxxopt=-Wno-weak-vtables test --test_output=errors diff --git a/BUILD.bazel b/BUILD.bazel index 9014daa..0d4601f 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -13,14 +13,3 @@ license( package_name = "ASL", ) -platform( - name = "x64_windows-clang-cl", - constraint_values = [ - "@platforms//cpu:x86_64", - "@platforms//os:windows", - # @Todo(bazel) Bit weird to use a private thing. - # We used to use @bazel_tools//tools/cpp:clang-cl but it's deprecated - # in favor of... this?... - "@rules_cc//cc/private/toolchain:clang-cl", - ], -) diff --git a/MODULE.bazel b/MODULE.bazel index 8d856b3..570884b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -8,11 +8,17 @@ bazel_dep(name = "platforms", version = "0.0.11") bazel_dep(name = "rules_license", version = "1.0.0") bazel_dep(name = "rules_cc", version = "0.1.1") -cc_configure = use_extension("@rules_cc//cc:extensions.bzl", "cc_configure_extension") -use_repo(cc_configure, "local_config_cc") bazel_dep(name = "hedron_compile_commands", version = "0.1.0", dev_dependency = True) bazel_dep(name = "rules_python", version = "1.3.0") python = use_extension("@rules_python//python/extensions:python.bzl", "python") python.toolchain(python_version = "3.13", is_default = True) + +clang_toolchain = use_extension("//bazel/clang_toolchain:config_detection.bzl", "clang_toolchain") +use_repo(clang_toolchain, "clang_toolchain") +register_toolchains( + "@clang_toolchain//:windows_x86_64_toolchain_def", + "@clang_toolchain//:linux_x86_64_toolchain_def", +) + diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock index 9fb4fd8..3ade483 100644 --- a/MODULE.bazel.lock +++ b/MODULE.bazel.lock @@ -146,6 +146,22 @@ }, "selectedYankedVersions": {}, "moduleExtensions": { + "//bazel/clang_toolchain:config_detection.bzl%clang_toolchain": { + "general": { + "bzlTransitiveDigest": "xXTcNvgp9bMnw/1ZKi1vOOoz139EHr8Hw3Ugd9+eos0=", + "usagesDigest": "CRr/eSLZQiKHqCq8MWfzhslrj4Mqar1310aEoa4BzJw=", + "recordedFileInputs": {}, + "recordedDirentsInputs": {}, + "envVariables": {}, + "generatedRepoSpecs": { + "clang_toolchain": { + "repoRuleId": "@@//bazel/clang_toolchain:config_detection.bzl%_config_detection", + "attributes": {} + } + }, + "recordedRepoMappingEntries": [] + } + }, "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { "general": { "bzlTransitiveDigest": "hUTp2w+RUVdL7ma5esCXZJAFnX7vLbVfLd7FwnQI6bU=", diff --git a/asl/base/annotations.hpp b/asl/base/annotations.hpp index ec17502..0a45d33 100644 --- a/asl/base/annotations.hpp +++ b/asl/base/annotations.hpp @@ -6,8 +6,8 @@ #include "asl/base/config.hpp" -#if ASL_COMPILER_CLANG_CL +#if defined(ASL_COMPILER_CLANG_CL) #define ASL_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] -#elif ASL_COMPILER_CLANG +#elif defined(ASL_COMPILER_CLANG) #define ASL_NO_UNIQUE_ADDRESS [[no_unique_address]] #endif diff --git a/asl/base/assert.hpp b/asl/base/assert.hpp index a899564..a764f0d 100644 --- a/asl/base/assert.hpp +++ b/asl/base/assert.hpp @@ -18,9 +18,9 @@ void report_assert_failure(const char* msg, const source_location& sl = source_l } // namespace asl -#if ASL_COMPILER_CLANG_CL +#if defined(ASL_COMPILER_CLANG_CL) #define ASL_DEBUG_BREAK() __debugbreak() -#elif ASL_COMPILER_CLANG +#elif defined(ASL_COMPILER_CLANG) #define ASL_DEBUG_BREAK() __builtin_debugtrap() #endif diff --git a/asl/base/bit_tests.cpp b/asl/base/bit_tests.cpp index 972bc72..5961b2e 100644 --- a/asl/base/bit_tests.cpp +++ b/asl/base/bit_tests.cpp @@ -15,6 +15,11 @@ ASL_TEST(has_single_bit) ASL_TEST_EXPECT(!asl::has_single_bit(0U)); ASL_TEST_EXPECT(!asl::has_single_bit(3U)); ASL_TEST_EXPECT(!asl::has_single_bit(341U)); + int k = 0x7fffffff; + k += 1; + int *array = new int[100]; + delete [] array; + ASL_TEST_EXPECT(array[1] == 0); // BOOM } ASL_TEST(popcount) // NOLINT(*-cognitive-complexity) diff --git a/asl/base/integers.hpp b/asl/base/integers.hpp index 4e481dc..b29a87b 100644 --- a/asl/base/integers.hpp +++ b/asl/base/integers.hpp @@ -9,18 +9,18 @@ using int8_t = signed char; using int16_t = signed short; using int32_t = signed int; -#if ASL_OS_WINDOWS +#if defined(ASL_OS_WINDOWS) using int64_t = signed long long; -#elif ASL_OS_LINUX +#elif defined(ASL_OS_LINUX) using int64_t = signed long; #endif using uint8_t = unsigned char; using uint16_t = unsigned short; using uint32_t = unsigned int; -#if ASL_OS_WINDOWS +#if defined(ASL_OS_WINDOWS) using uint64_t = unsigned long long; -#elif ASL_OS_LINUX +#elif defined(ASL_OS_LINUX) using uint64_t = unsigned long; #endif diff --git a/asl/memory/allocator.cpp b/asl/memory/allocator.cpp index f0cf758..a9f919c 100644 --- a/asl/memory/allocator.cpp +++ b/asl/memory/allocator.cpp @@ -15,11 +15,11 @@ void* asl::GlobalHeap::alloc(const layout& layout) { -#if ASL_OS_WINDOWS +#if defined(ASL_OS_WINDOWS) void* ptr = ::_aligned_malloc( static_cast(layout.size), static_cast(layout.align)); -#elif ASL_OS_LINUX +#elif defined(ASL_OS_LINUX) void* ptr = ::aligned_alloc( static_cast(layout.align), static_cast(layout.size)); @@ -30,11 +30,11 @@ void* asl::GlobalHeap::alloc(const layout& layout) void* asl::GlobalHeap::realloc(void* old_ptr, [[maybe_unused]] const layout& old_layout, const layout& new_layout) { -#if ASL_OS_WINDOWS +#if defined(ASL_OS_WINDOWS) return ::_aligned_realloc(old_ptr, static_cast(new_layout.size), static_cast(new_layout.align)); -#elif ASL_OS_LINUX +#elif defined(ASL_OS_LINUX) if (new_layout.align <= old_layout.align) { void* new_ptr = ::realloc(old_ptr, static_cast(new_layout.size)); @@ -51,9 +51,9 @@ void* asl::GlobalHeap::realloc(void* old_ptr, [[maybe_unused]] const layout& old void asl::GlobalHeap::dealloc(void* ptr, const layout&) { -#if ASL_OS_WINDOWS +#if defined(ASL_OS_WINDOWS) ::_aligned_free(ptr); -#elif ASL_OS_LINUX +#elif defined(ASL_OS_LINUX) ::free(ptr); #endif } diff --git a/bazel/clang_toolchain/BUILD.bazel b/bazel/clang_toolchain/BUILD.bazel new file mode 100644 index 0000000..8532c27 --- /dev/null +++ b/bazel/clang_toolchain/BUILD.bazel @@ -0,0 +1,4 @@ +# Copyright 2025 Steven Le Rouzic +# +# SPDX-License-Identifier: BSD-3-Clause + diff --git a/bazel/clang_toolchain/clang_config.bzl.tpl b/bazel/clang_toolchain/clang_config.bzl.tpl new file mode 100644 index 0000000..07fa9c2 --- /dev/null +++ b/bazel/clang_toolchain/clang_config.bzl.tpl @@ -0,0 +1,8 @@ +# Copyright 2025 Steven Le Rouzic +# +# SPDX-License-Identifier: BSD-3-Clause + +CLANG_BINDIR = "{CLANG_BINDIR}" +CLANG_LIBDIR = "{CLANG_LIBDIR}" +CLANG_INCLUDE_DIRS = {CLANG_INCLUDE_DIRS} + diff --git a/bazel/clang_toolchain/clang_toolchain.BUILD.bazel b/bazel/clang_toolchain/clang_toolchain.BUILD.bazel new file mode 100644 index 0000000..857af87 --- /dev/null +++ b/bazel/clang_toolchain/clang_toolchain.BUILD.bazel @@ -0,0 +1,18 @@ +# Copyright 2025 Steven Le Rouzic +# +# SPDX-License-Identifier: BSD-3-Clause + +load(":toolchain_config.bzl", "declare_toolchain") + +filegroup(name = "empty") + +PAIRS = [ + ("windows", "x86_64"), + ("linux", "x86_64"), +] + +[ + declare_toolchain(name = "%s_%s_toolchain" % (os, arch), os = os, arch = arch) + for (os, arch) in PAIRS +] + diff --git a/bazel/clang_toolchain/config_detection.bzl b/bazel/clang_toolchain/config_detection.bzl new file mode 100644 index 0000000..76d3890 --- /dev/null +++ b/bazel/clang_toolchain/config_detection.bzl @@ -0,0 +1,113 @@ +# Copyright 2025 Steven Le Rouzic +# +# SPDX-License-Identifier: BSD-3-Clause + +def _copy_file(ctx, from_path, to_path): + content = ctx.read(from_path) + ctx.file(to_path, content = content) + +def _get_clang_info(ctx, clang_path, line_prefix): + result = ctx.execute([clang_path, "--version"]) + if result.return_code != 0: + return None + + for l in result.stdout.splitlines(): + if l.startswith(line_prefix): + l = l[len(line_prefix):] + return l.split(" ")[0] + + return None + +def _get_clang_version(ctx, clang_path): + return _get_clang_info(ctx, clang_path, "clang version ") + +def _get_clang_lib_dir(ctx, clang_path): + result = ctx.execute([clang_path, "-no-canonical-prefixes", "--print-resource-dir"]) + if result.return_code != 0: + return None + + return result.stdout + +def _get_include_dirs(ctx, clang_path): + ctx.file("detect.cpp", content = "") + detect_path = ctx.path("detect.cpp") + res = ctx.execute([ + clang_path, + "-v", + "-no-canonical-prefixes", + "-fsyntax-only", + "-x", "c++", + detect_path, + ]) + + lines = res.stderr.splitlines() + listing_include_dirs = False + include_dirs = [] + + for l in lines: + if l.startswith("#include <...> search starts here:"): + listing_include_dirs = True + elif l.startswith("End of search list."): + listing_include_dirs = False + elif listing_include_dirs: + include_dirs.append(l.strip()) + + return include_dirs + +def _impl(ctx): + _copy_file(ctx, ctx.attr._build_bazel, "BUILD.bazel") + _copy_file(ctx, ctx.attr._toolchain_config_bzl, "toolchain_config.bzl") + + clang_path = ctx.which("clang") + if not clang_path: + fail("Could not find clang") + + clang_version = _get_clang_version(ctx, clang_path) + if not clang_version: + fail("Could not detect clang version") + + clang_lib_dir = _get_clang_lib_dir(ctx, clang_path) + if not clang_lib_dir: + fail("Could not detect clang lib dir") + + include_dirs = _get_include_dirs(ctx, clang_path) + if not include_dirs: + fail("Could not detect include dirs") + + ctx.template( + "clang_config.bzl", + ctx.attr._clang_config_bzl_tpl, + executable = False, + substitutions = { + "{CLANG_BINDIR}": str(clang_path.dirname), + "{CLANG_LIBDIR}": str(clang_lib_dir).strip().replace("\\", "/"), + "{CLANG_INCLUDE_DIRS}": str(include_dirs), + }, + ) + + +_config_detection = repository_rule( + implementation = _impl, + local = True, + configure = True, + attrs = { + "_build_bazel": attr.label( + default = Label("//bazel/clang_toolchain:clang_toolchain.BUILD.bazel"), + allow_single_file = True, + ), + "_toolchain_config_bzl": attr.label( + default = Label("//bazel/clang_toolchain:toolchain_config.bzl"), + allow_single_file = True, + ), + "_clang_config_bzl_tpl": attr.label( + default = Label("//bazel/clang_toolchain:clang_config.bzl.tpl"), + allow_single_file = True, + ), + }, +) + +clang_toolchain = module_extension( + implementation = lambda ctx: _config_detection( + name = "clang_toolchain", + ), +) diff --git a/bazel/clang_toolchain/toolchain_config.bzl b/bazel/clang_toolchain/toolchain_config.bzl new file mode 100644 index 0000000..504e885 --- /dev/null +++ b/bazel/clang_toolchain/toolchain_config.bzl @@ -0,0 +1,596 @@ +# Copyright 2025 Steven Le Rouzic +# +# SPDX-License-Identifier: BSD-3-Clause + +load( + "//:clang_config.bzl", + "CLANG_BINDIR", + "CLANG_LIBDIR", + "CLANG_INCLUDE_DIRS", +) + +load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES") + +load( + "@rules_cc//cc:cc_toolchain_config_lib.bzl", + "action_config", + "artifact_name_pattern", + "feature", + "feature_set", + "flag_group", + "flag_set", + "tool", + "tool_path", + "variable_with_value", +) + +CPP_COMPILE_ACTIONS = [ + ACTION_NAMES.cpp_compile, + ACTION_NAMES.cpp_header_parsing +] + +C_COMPILE_ACTIONS = [ + ACTION_NAMES.c_compile, +] + +COMPILE_ACTIONS = C_COMPILE_ACTIONS + CPP_COMPILE_ACTIONS + +LINK_ACTIONS = [ + ACTION_NAMES.cpp_link_dynamic_library, + ACTION_NAMES.cpp_link_nodeps_dynamic_library, + ACTION_NAMES.cpp_link_executable, +] + +ARCHIVE_ACTIONS = [ + ACTION_NAMES.cpp_link_static_library, +] + +def _impl(ctx): + os = ctx.attr.os + is_windows = os == "windows" + exe_suffix = ".exe" if is_windows else "" + + tool_paths = [ + tool_path(name = "ar", path = CLANG_BINDIR + "/llvm-ar" + exe_suffix), + tool_path(name = "ld", path = CLANG_BINDIR + "/ld.lld" + exe_suffix), + tool_path(name = "nm", path = CLANG_BINDIR + "/llvm-nm" + exe_suffix), + tool_path(name = "objdump", path = CLANG_BINDIR + "/llvm-objdump" + exe_suffix), + tool_path(name = "strip", path = CLANG_BINDIR + "/llvm-strip" + exe_suffix), + tool_path(name = "gcc", path = CLANG_BINDIR + "/clang" + exe_suffix), + tool_path(name = "cpp", path = CLANG_BINDIR + "/clang++" + exe_suffix), + ] + + action_configs = [ + action_config(action_name = name, enabled = True, tools = [tool(path = CLANG_BINDIR + "/clang" + exe_suffix)]) + for name in C_COMPILE_ACTIONS + ] + [ + action_config(action_name = name, enabled = True, tools = [tool(path = CLANG_BINDIR + "/clang++" + exe_suffix)]) + for name in CPP_COMPILE_ACTIONS + ] + [ + action_config(action_name = name, enabled = True, tools = [tool(path = CLANG_BINDIR + "/clang++" + exe_suffix)]) + for name in LINK_ACTIONS + ] + [ + action_config(action_name = name, enabled = True, tools = [tool(path = CLANG_BINDIR + "/llvm-ar" + exe_suffix)]) + for name in ARCHIVE_ACTIONS + ] + [ + action_config(ACTION_NAMES.strip, enabled = True, tools = [tool(path = CLANG_BINDIR + "/llvm-strip" + exe_suffix)]), + ] + + artifact_name_patterns = [ + artifact_name_pattern( + category_name = "object_file", + prefix = "", + extension = ".obj" if is_windows else ".o", + ), + artifact_name_pattern( + category_name = "static_library", + prefix = "" if is_windows else "lib", + extension = ".lib" if is_windows else ".a", + ), + artifact_name_pattern( + category_name = "dynamic_library", + prefix = "" if is_windows else "lib", + extension = ".dll" if is_windows else ".so", + ), + artifact_name_pattern( + category_name = "executable", + prefix = "", + extension = exe_suffix, + ), + ] + + asan_link_flag_sets = [] + ubsan_link_flag_sets = [] + + if is_windows: + asan_link_flag_sets.append(flag_set( + actions = LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-l\"" + CLANG_LIBDIR + "/lib/windows/clang_rt.asan_dynamic-x86_64.lib\"", + ], + ), + ], + )) + + ubsan_link_flag_sets.append(flag_set( + actions = LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-l\"" + CLANG_LIBDIR + "/lib/windows/clang_rt.ubsan_standalone-x86_64.lib\"", + ], + ), + ], + )) + + features = [ + feature(name = "no_legacy_features"), + feature(name = "opt"), + feature(name = "fastbuild"), + feature(name = "dbg"), + feature( + name = "default_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS + LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-no-canonical-prefixes", + "-fcolor-diagnostics", + ], + ), + ], + ), + flag_set( + actions = LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-fuse-ld=lld", + ], + ), + ], + ), + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-Wno-builtin-macro-redefined", + "-D__DATE__=\"redacted\"", + "-D__TIMESTAMP__=\"redacted\"", + "-D__TIME__=\"redacted\"", + "-c", + ], + ), + flag_group( + flags = ["-frandom-seed=%{output_file}"], + expand_if_available = "output_file", + ), + flag_group( + flags = ["-D%{preprocessor_defines}"], + iterate_over = "preprocessor_defines", + ), + flag_group( + flags = ["-I%{include_paths}"], + iterate_over = "include_paths", + ), + flag_group( + flags = ["-iquote", "%{quote_include_paths}"], + iterate_over = "quote_include_paths", + ), + flag_group( + flags = ["-isystem", "%{system_include_paths}"], + iterate_over = "system_include_paths", + ), + flag_group( + flags = ["-MD", "-MF", "%{dependency_file}"], + expand_if_available = "dependency_file", + ), + ], + ), + flag_set( + actions = ARCHIVE_ACTIONS, + flag_groups = [ + flag_group( + flags = ["rcsD"], + ), + flag_group( + flags = ["%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + flag_set( + actions = LINK_ACTIONS + ARCHIVE_ACTIONS, + flag_groups = [ + flag_group( + iterate_over = "libraries_to_link", + expand_if_available = "libraries_to_link", + flag_groups = [ + flag_group( + flags = ["-Wl,--start-lib"], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + flag_group( + iterate_over = "libraries_to_link.object_files", + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.object_files}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.object_files}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + ), + flag_group( + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file", + ), + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + ), + flag_group( + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "interface_library", + ), + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + ), + flag_group( + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "static_library", + ), + flag_groups = [ + flag_group( + flags = ["%{libraries_to_link.name}"], + expand_if_false = "libraries_to_link.is_whole_archive", + ), + flag_group( + flags = ["-Wl,-force_load,%{libraries_to_link.name}"], + expand_if_true = "libraries_to_link.is_whole_archive", + ), + ], + ), + flag_group( + flags = ["-l%{libraries_to_link.name}"], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "dynamic_library", + ), + ), + flag_group( + flags = ["-l:%{libraries_to_link.name}"], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "versioned_dynamic_library", + ), + ), + flag_group( + expand_if_true = "libraries_to_link.is_whole_archive", + flag_groups = [ + flag_group( + expand_if_false = "macos_flags", + flags = ["-Wl,-no-whole-archive"], + ), + ], + ), + flag_group( + flags = ["-Wl,--end-lib"], + expand_if_equal = variable_with_value( + name = "libraries_to_link.type", + value = "object_file_group", + ), + ), + ], + ), + ], + ), + ], + ), + feature( + name = "windows_linker_flags", + enabled = is_windows, + flag_sets = [ + flag_set( + actions = LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-Xlinker", + "/subsystem:console", + ], + ), + ], + ), + ], + ), + feature( + name = "dbg_flags", + enabled = True, + requires = [feature_set(["dbg"])], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-DDEBUG=1", + ], + ), + ], + ), + flag_set( + actions = COMPILE_ACTIONS + LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-g3", + ], + ), + ], + ), + ], + ), + feature( + name = "fastbuild_flags", + enabled = True, + requires = [feature_set(["fastbuild"])], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-O1", + "-DDEBUG=1", + ], + ), + ], + ), + flag_set( + actions = COMPILE_ACTIONS + LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-g1", + ], + ), + ], + ), + ], + ), + feature( + name = "opt_flags", + enabled = True, + requires = [feature_set(["opt"])], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-O3", + "-DNDEBUG=1", + ], + ), + ], + ), + ], + ), + feature( + name = "c++20", + provides = ["c++_version"], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = ["-std=c++20"], + ), + ], + ), + ], + ), + feature( + name = "c++23", + provides = ["c++_version"], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = ["-std=c++23"], + ), + ], + ), + ], + ), + feature( + name = "asan", + implies = ["sanitize"], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS + LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-fsanitize=address", + ], + ), + ], + ), + ] + asan_link_flag_sets, + ), + feature( + name = "ubsan", + implies = ["sanitize"], + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS + LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-fsanitize=undefined", + ], + ), + ], + ), + ] + ubsan_link_flag_sets, + ), + feature( + name = "sanitize", + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = [ + "-fno-omit-frame-pointer", + "-fno-sanitize-ignorelist", + "-fno-sanitize-recover=all", + ], + ), + ], + ), + ], + ), + feature( + name = "final_flags", + enabled = True, + flag_sets = [ + flag_set( + actions = COMPILE_ACTIONS, + flag_groups = [ + flag_group( + flags = ["%{user_compile_flags}"], + expand_if_available = "user_compile_flags", + iterate_over = "user_compile_flags", + ), + flag_group( + flags = ["-o", "%{output_file}"], + expand_if_available = "output_file", + ), + flag_group( + flags = ["%{source_file}"], + expand_if_available = "source_file", + ), + ], + ), + flag_set( + actions = LINK_ACTIONS, + flag_groups = [ + flag_group( + flags = ["%{user_link_flags}"], + expand_if_available = "user_link_flags", + iterate_over = "user_link_flags", + ), + flag_group( + flags = ["-o", "%{output_execpath}"], + expand_if_available = "output_execpath", + ), + ], + ), + flag_set( + actions = LINK_ACTIONS + ARCHIVE_ACTIONS, + flag_groups = [ + flag_group( + flags = ["@%{linker_param_file}"], + expand_if_available = "linker_param_file", + ), + ], + ), + ], + ), + ] + + return cc_common.create_cc_toolchain_config_info( + ctx = ctx, + toolchain_identifier = "%s-toolchain" % os, + compiler = "clang", + artifact_name_patterns = artifact_name_patterns, + cxx_builtin_include_directories = CLANG_INCLUDE_DIRS, + tool_paths = tool_paths, + action_configs = action_configs, + features = features, + ) + +toolchain_config = rule( + implementation = _impl, + attrs = { + "os": attr.string(mandatory = True), + }, + provides = [CcToolchainConfigInfo], +) + +def _declare_toolchain_impl(name, os, arch, visibility): + toolchain_config( + name = name + "_config", + os = os, + ) + + native.cc_toolchain( + name = name + "_cc", + toolchain_config = name + "_config", + all_files = ":empty", + compiler_files = ":empty", + linker_files = ":empty", + objcopy_files = ":empty", + strip_files = ":empty", + dwp_files = ":empty", + ) + + native.toolchain( + name = name + "_def", + toolchain = name + "_cc", + toolchain_type = "@rules_cc//cc:toolchain_type", + exec_compatible_with = [ + "@platforms//cpu:%s" % arch, + "@platforms//os:%s" % os, + ], + target_compatible_with = [ + "@platforms//cpu:%s" % arch, + "@platforms//os:%s" % os, + ], + visibility = ["//visibility:public"], + ) + +declare_toolchain = macro( + implementation = _declare_toolchain_impl, + attrs = { + "os": attr.string(mandatory = True, configurable = False), + "arch": attr.string(mandatory = True, configurable = False), + } +) diff --git a/refresh_clangd.sh b/refresh_clangd.sh index f1bae0d..0e50f4d 100755 --- a/refresh_clangd.sh +++ b/refresh_clangd.sh @@ -1 +1 @@ -bazel run //tools:refresh_clangd --config=linux -- --config=linux +bazel run //tools:refresh_clangd diff --git a/todo.txt b/todo.txt index c76a0b1..252cdb6 100644 --- a/todo.txt +++ b/todo.txt @@ -1 +1,6 @@ -C++26: constexpr cast from void* https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2738r1.pdf +constexpr cast from void* +cpp26 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2738r1.pdf + +add sanitizers features +bazel_clang_toolchain +linux x64 support +bazel_clang_toolchain +linux arm64 support +bazel_clang_toolchain + diff --git a/tools/fix_line_endings.py b/tools/fix_line_endings.py index ac38063..f072546 100644 --- a/tools/fix_line_endings.py +++ b/tools/fix_line_endings.py @@ -19,6 +19,7 @@ TO_FIX = [ "**/*.cpp", "**/*.py", "**/*.bzl", + "**/*.bzl.tpl", "**/*.bazel", "**/*.txt", "**/*.bat",