blob: e7c1f45b85eac60c4a5121e3353a89f67b256de7 [file] [log] [blame]
"""This module encapsulates logic to create emscripten_cc_toolchain_config rule."""
load(
"@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
"action_config",
"env_entry",
"env_set",
"feature",
"feature_set",
"flag_group",
"tool",
"tool_path",
"variable_with_value",
"with_feature_set",
_flag_set = "flag_set",
)
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
def flag_set(flags = None, features = None, not_features = None, **kwargs):
"""Extension to flag_set which allows for a "simple" form.
The simple form allows specifying flags as a simple list instead of a flag_group
if enable_if or expand_if semantics are not required.
Similarly, the simple form allows passing features/not_features if they are a simple
list of semantically "and" features.
(i.e. "asan" and "dbg", rather than "asan" or "dbg")
Args:
flags: list, set of flags
features: list, set of features required to be enabled.
not_features: list, set of features required to not be enabled.
**kwargs: The rest of the args for flag_set.
Returns:
flag_set
"""
if flags:
if kwargs.get("flag_groups"):
fail("Cannot set flags and flag_groups")
else:
kwargs["flag_groups"] = [flag_group(flags = flags)]
if features or not_features:
if kwargs.get("with_features"):
fail("Cannot set features/not_feature and with_features")
kwargs["with_features"] = [with_feature_set(
features = features or [],
not_features = not_features or [],
)]
return _flag_set(**kwargs)
CROSSTOOL_DEFAULT_WARNINGS = [
"-Wall",
]
def _impl(ctx):
target_cpu = ctx.attr.cpu
toolchain_identifier = "emscripten-" + target_cpu
target_system_name = target_cpu + "-unknown-emscripten"
host_system_name = "i686-unknown-linux-gnu"
target_libc = "musl/js"
abi_version = "emscripten_syscalls"
compiler = "emscripten"
abi_libc_version = "default"
cc_target_os = "emscripten"
emscripten_dir = ctx.attr.emscripten_binaries.label.workspace_root
builtin_sysroot = emscripten_dir + "/emscripten/cache/sysroot"
emcc_script = "emcc.%s" % ctx.attr.script_extension
emcc_link_script = "emcc_link.%s" % ctx.attr.script_extension
emar_script = "emar.%s" % ctx.attr.script_extension
################################################################
# Tools
################################################################
clang_tool = tool(path = emcc_script)
clif_match_tool = tool(path = "dummy_clif_matcher")
link_tool = tool(path = emcc_link_script)
archive_tool = tool(path = emar_script)
strip_tool = tool(path = "NOT_USED_STRIP_TOOL")
#### Legacy tool paths (much of this is redundant with action_configs, but
#### these are still used for some things)
tool_paths = [
tool_path(name = "ar", path = emar_script),
tool_path(name = "cpp", path = "/bin/false"),
tool_path(name = "gcc", path = emcc_script),
tool_path(name = "gcov", path = "/bin/false"),
tool_path(name = "ld", path = emcc_link_script),
tool_path(name = "nm", path = "NOT_USED"),
tool_path(name = "objdump", path = "/bin/false"),
tool_path(name = "strip", path = "NOT_USED"),
]
################################################################
# Action Configs
################################################################
cpp_compile_action = action_config(
action_name = ACTION_NAMES.cpp_compile,
tools = [clang_tool],
)
cpp_module_compile_action = action_config(
action_name = ACTION_NAMES.cpp_module_compile,
tools = [clang_tool],
)
cpp_module_codegen_action = action_config(
action_name = ACTION_NAMES.cpp_module_codegen,
tools = [clang_tool],
)
clif_match_action = action_config(
action_name = ACTION_NAMES.clif_match,
tools = [clif_match_tool],
)
cpp_link_dynamic_library_action = action_config(
action_name = ACTION_NAMES.cpp_link_dynamic_library,
tools = [link_tool],
)
strip_action = action_config(
action_name = ACTION_NAMES.strip,
tools = [strip_tool],
)
preprocess_assemble_action = action_config(
action_name = ACTION_NAMES.preprocess_assemble,
tools = [clang_tool],
)
cpp_header_parsing_action = action_config(
action_name = ACTION_NAMES.cpp_header_parsing,
tools = [clang_tool],
)
cpp_link_static_library_action = action_config(
action_name = ACTION_NAMES.cpp_link_static_library,
enabled = True,
flag_sets = [
flag_set(
flag_groups = [
flag_group(
flags = ["rcsD", "%{output_execpath}"],
expand_if_available = "output_execpath",
),
],
),
flag_set(
flag_groups = [
flag_group(
iterate_over = "libraries_to_link",
flag_groups = [
flag_group(
flags = ["%{libraries_to_link.name}"],
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file",
),
),
flag_group(
flags = ["%{libraries_to_link.object_files}"],
iterate_over = "libraries_to_link.object_files",
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
),
],
expand_if_available = "libraries_to_link",
),
],
),
flag_set(
flag_groups = [
flag_group(
flags = ["@%{linker_param_file}"],
expand_if_available = "linker_param_file",
),
],
),
],
tools = [archive_tool],
)
c_compile_action = action_config(
action_name = ACTION_NAMES.c_compile,
tools = [clang_tool],
)
linkstamp_compile_action = action_config(
action_name = ACTION_NAMES.linkstamp_compile,
tools = [clang_tool],
)
assemble_action = action_config(
action_name = ACTION_NAMES.assemble,
tools = [clang_tool],
)
cpp_link_executable_action = action_config(
action_name = ACTION_NAMES.cpp_link_executable,
tools = [link_tool],
)
cpp_link_nodeps_dynamic_library_action = action_config(
action_name = ACTION_NAMES.cpp_link_nodeps_dynamic_library,
tools = [link_tool],
)
action_configs = [
strip_action,
c_compile_action,
cpp_compile_action,
linkstamp_compile_action,
assemble_action,
preprocess_assemble_action,
cpp_header_parsing_action,
cpp_module_compile_action,
cpp_module_codegen_action,
cpp_link_executable_action,
cpp_link_dynamic_library_action,
cpp_link_nodeps_dynamic_library_action,
cpp_link_static_library_action,
clif_match_action,
]
all_compile_actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
ACTION_NAMES.lto_backend,
]
all_cpp_compile_actions = [
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
]
preprocessor_compile_actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.clif_match,
]
all_link_actions = [
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
]
################################################################
# Features
################################################################
features = [
# This set of magic "feature"s are important configuration information for blaze.
feature(name = "no_legacy_features", enabled = True),
feature(
name = "has_configured_linker_path",
enabled = True,
),
# Blaze requests this feature by default, but we don't care.
feature(name = "dependency_file"),
# Blaze requests this feature by default, but we don't care.
feature(name = "random_seed"),
# Formerly "needsPic" attribute
feature(name = "supports_pic", enabled = False),
# Blaze requests this feature by default.
# Blaze also tests if this feature is supported, before setting the "pic" build-variable.
feature(name = "pic"),
# Blaze requests this feature by default.
# Blaze also tests if this feature is supported before setting preprocessor_defines
# (...but why?)
feature(name = "preprocessor_defines"),
# Blaze requests this feature by default.
# Blaze also tests if this feature is supported before setting includes. (...but why?)
feature(name = "include_paths"),
# Blaze tests if this feature is enabled in order to create implicit
# "nodeps" .so outputs from cc_library rules.
feature(name = "supports_dynamic_linker", enabled = False),
# Blaze requests this feature when linking a cc_binary which is
# "dynamic" aka linked against nodeps-dynamic-library cc_library
# outputs.
feature(name = "dynamic_linking_mode"),
#### Configuration features
feature(
name = "crosstool_cpu",
enabled = True,
implies = ["crosstool_cpu_" + target_cpu],
),
feature(
name = "crosstool_cpu_asmjs",
provides = ["variant:crosstool_cpu"],
),
feature(
name = "crosstool_cpu_wasm",
provides = ["variant:crosstool_cpu"],
),
# These 3 features will be automatically enabled by blaze in the
# corresponding build mode.
feature(
name = "opt",
provides = ["variant:crosstool_build_mode"],
),
feature(
name = "dbg",
provides = ["variant:crosstool_build_mode"],
),
feature(
name = "fastbuild",
provides = ["variant:crosstool_build_mode"],
),
# Feature to prevent 'command line too long' issues
feature(
name = "archive_param_file",
enabled = True,
),
feature(
name = "compiler_param_file",
enabled = True,
),
#### User-settable features
# Set if enabling exceptions.
feature(name = "exceptions"),
# This feature overrides the default optimization to prefer execution speed
# over binary size (like clang -O3).
feature(
name = "optimized_for_speed",
provides = ["variant:crosstool_optimization_mode"],
),
# This feature overrides the default optimization to prefer binary size over
# execution speed (like clang -Oz).
feature(
name = "optimized_for_size",
provides = ["variant:crosstool_optimization_mode"],
),
# Convenience aliases / alt-spellings.
feature(
name = "optimize_for_speed",
implies = ["optimized_for_speed"],
),
feature(
name = "optimize_for_size",
implies = ["optimized_for_size"],
),
# This feature allows easier use of profiling tools by preserving mangled
# C++ names. This does everything profiling_funcs does and more.
feature(name = "profiling"),
# This feature emits only enough debug info for function names to appear
# in profiles.
feature(name = "profiling_funcs"),
# This feature allows source maps to be generated.
feature(
name = "source_maps",
implies = ["full_debug_info"],
),
feature(
name = "dwarf_debug_info",
implies = ["profiling"],
),
# Turns on full debug info (-g4).
feature(name = "full_debug_info"),
# Enables the use of "Emscripten" Pthread implementation.
# https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
# https://github.com/kripken/emscripten/wiki/Pthreads-with-WebAssembly
feature(name = "use_pthreads"),
# If enabled, the runtime will exit when main() completes.
feature(name = "exit_runtime"),
# Primarily for toolchain maintainers:
feature(name = "emcc_debug"),
feature(name = "emcc_debug_link"),
feature(
name = "llvm_backend",
requires = [feature_set(features = ["crosstool_cpu_wasm"])],
enabled = True,
),
# Remove once flag is flipped.
# See https://github.com/bazelbuild/bazel/issues/7687
feature(
name = "do_not_split_linking_cmdline",
),
# Adds simd support, only available with the llvm backend.
feature(
name = "wasm_simd",
requires = [feature_set(features = ["llvm_backend"])],
),
# Adds relaxed-simd support, only available with the llvm backend.
feature(
name = "wasm_relaxed_simd",
requires = [feature_set(features = ["llvm_backend"])],
),
feature(
name = "precise_long_double_printf",
enabled = True,
),
feature(
name = "wasm_warnings_as_errors",
enabled = False,
),
# ASan and UBSan. See also:
# https://emscripten.org/docs/debugging/Sanitizers.html
feature(name = "wasm_asan"),
feature(name = "wasm_ubsan"),
feature(
name = "output_format_js",
enabled = True,
),
feature(
name = "wasm_standalone",
),
]
crosstool_default_flag_sets = [
# Compile, Link, and CC_FLAGS make variable
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
],
flag_groups = [
flag_group(
flags = ["--sysroot=%{sysroot}"],
expand_if_available = "sysroot",
),
],
),
# Compile + Link
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
ACTION_NAMES.cpp_link_executable,
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
],
# This forces color diagnostics even on Forge (where we don't have an
# attached terminal).
flags = [
"-fdiagnostics-color",
],
),
# C++ compiles (and implicitly link)
flag_set(
actions = all_cpp_compile_actions,
flags = [
"-fno-exceptions",
],
not_features = ["exceptions"],
),
flag_set(
actions = all_cpp_compile_actions,
flags = [
"-fexceptions",
],
features = ["exceptions"],
),
# All compiles (and implicitly link)
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = [
"-fno-strict-aliasing",
"-funsigned-char",
"-no-canonical-prefixes",
],
),
# Language Features
flag_set(
actions = all_cpp_compile_actions,
flags = ["-std=gnu++17", "-nostdinc", "-nostdinc++"],
),
# Emscripten-specific settings:
flag_set(
actions = all_compile_actions + all_link_actions,
flags = ["-s", "WASM=0"],
features = ["crosstool_cpu_asmjs"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-s", "USE_PTHREADS=1"],
features = ["use_pthreads"],
),
flag_set(
actions = all_link_actions,
flags = ["-s", "EXIT_RUNTIME=1"],
features = ["exit_runtime"],
),
flag_set(
actions = all_compile_actions + all_link_actions,
flags = ["-pthread"],
features = ["llvm_backend", "use_pthreads"],
),
flag_set(
actions = all_compile_actions + all_link_actions,
flags = ["-msimd128"],
features = ["wasm_simd"],
),
flag_set(
actions = all_compile_actions + all_link_actions,
flags = ["-msimd128", "-mrelaxed-simd"],
features = ["wasm_relaxed_simd"],
),
flag_set(
actions = all_link_actions,
flags = ["-s", "PRINTF_LONG_DOUBLE=1"],
features = ["precise_long_double_printf"],
),
flag_set(
actions = all_link_actions,
flags = ["--oformat=js"],
features = ["output_format_js"],
),
# Opt
flag_set(
actions = preprocessor_compile_actions,
flags = ["-DNDEBUG"],
features = ["opt"],
),
flag_set(
actions = all_compile_actions,
flags = ["-fomit-frame-pointer"],
features = ["opt"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-O2"],
features = ["opt"],
),
# Users can override opt-level with semantic names...
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-Oz"],
features = ["optimized_for_size", "opt"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-O3"],
features = ["optimized_for_speed", "opt"],
),
# Fastbuild
flag_set(
actions = all_compile_actions,
flags = ["-fomit-frame-pointer"],
features = ["fastbuild"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-O0"],
features = ["fastbuild"],
),
# Dbg
flag_set(
actions = all_compile_actions,
flags = ["-fno-omit-frame-pointer"],
features = ["dbg"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-g", "-O0"],
features = ["dbg"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = [
"-g",
"-fsanitize=address",
"-O1",
"-DADDRESS_SANITIZER=1",
"-fno-omit-frame-pointer",
],
features = ["wasm_asan"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = [
"-g4",
"-fsanitize=undefined",
"-O1",
"-DUNDEFINED_BEHAVIOR_SANITIZER=1",
"-fno-omit-frame-pointer",
"-fno-sanitize=vptr",
],
features = ["wasm_ubsan"],
),
# Profiling provides full debug info and a special --profiling flag
# to control name mangling
flag_set(
actions = all_link_actions,
flags = ["--profiling"],
features = ["profiling"],
),
flag_set(
actions = all_link_actions,
flags = ["--profiling_funcs"],
features = ["profiling_funcs"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-g4"],
features = ["full_debug_info"],
),
flag_set(
actions = all_link_actions,
flags = ["-gseparate-dwarf"],
features = ["dwarf_debug_info"],
),
flag_set(
actions = all_compile_actions +
all_link_actions,
flags = ["-fdebug-compilation-dir=."],
features = ["dwarf_debug_info"],
),
# Generic warning flag list
flag_set(
actions = all_compile_actions,
flags = CROSSTOOL_DEFAULT_WARNINGS,
),
# Defines and Includes and Paths and such
flag_set(
actions = all_compile_actions,
flag_groups = [
flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
],
),
flag_set(
actions = preprocessor_compile_actions,
flag_groups = [
flag_group(
flags = ["-D%{preprocessor_defines}"],
iterate_over = "preprocessor_defines",
),
],
),
flag_set(
actions = preprocessor_compile_actions,
flag_groups = [
flag_group(
flags = ["-include", "%{includes}"],
iterate_over = "includes",
expand_if_available = "includes",
),
],
),
flag_set(
actions = preprocessor_compile_actions,
flag_groups = [
flag_group(
flags = ["-iquote", "%{quote_include_paths}"],
iterate_over = "quote_include_paths",
),
flag_group(
flags = ["-I%{include_paths}"],
iterate_over = "include_paths",
),
flag_group(
flags = ["-isystem", "%{system_include_paths}"],
iterate_over = "system_include_paths",
),
],
),
## Linking options (not libs -- those go last)
# Generic link options
flag_set(
actions = [
ACTION_NAMES.cpp_link_dynamic_library,
ACTION_NAMES.cpp_link_nodeps_dynamic_library,
],
flags = ["-shared"],
),
# Linker search paths and objects:
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
iterate_over = "runtime_library_search_directories",
flag_groups = [
flag_group(
flags = [
"-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}",
],
expand_if_true = "is_cc_test",
),
flag_group(
flags = [
"-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
],
expand_if_false = "is_cc_test",
),
],
expand_if_available = "runtime_library_search_directories",
),
],
),
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
flags = ["-L%{library_search_directories}"],
iterate_over = "library_search_directories",
expand_if_available = "library_search_directories",
),
],
),
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
# This is actually a list of object files from the linkstamp steps
flags = ["%{linkstamp_paths}"],
iterate_over = "linkstamp_paths",
expand_if_available = "linkstamp_paths",
),
],
),
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
flags = ["@%{thinlto_param_file}"],
expand_if_available = "libraries_to_link",
expand_if_true = "thinlto_param_file",
),
flag_group(
iterate_over = "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(
flags = ["-Wl,-whole-archive"],
expand_if_true = "libraries_to_link.is_whole_archive",
),
flag_group(
flags = ["%{libraries_to_link.object_files}"],
iterate_over = "libraries_to_link.object_files",
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
),
flag_group(
flags = ["%{libraries_to_link.name}"],
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file",
),
),
flag_group(
flags = ["%{libraries_to_link.name}"],
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "interface_library",
),
),
flag_group(
flags = ["%{libraries_to_link.name}"],
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "static_library",
),
),
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(
flags = ["-Wl,-no-whole-archive"],
expand_if_true = "libraries_to_link.is_whole_archive",
),
flag_group(
flags = ["-Wl,--end-lib"],
expand_if_equal = variable_with_value(
name = "libraries_to_link.type",
value = "object_file_group",
),
),
],
expand_if_available = "libraries_to_link",
),
],
),
# Configure the header parsing and preprocessing.
flag_set(
actions = [ACTION_NAMES.cpp_header_parsing],
flags = ["-xc++-header", "-fsyntax-only"],
features = ["parse_headers"],
),
# Note: user compile flags should be nearly last -- you probably
# don't want to put any more features after this!
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
],
flag_groups = [
flag_group(
flags = ["%{user_compile_flags}"],
iterate_over = "user_compile_flags",
expand_if_available = "user_compile_flags",
),
],
),
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
flags = ["%{user_link_flags}"],
iterate_over = "user_link_flags",
expand_if_available = "user_link_flags",
),
],
),
## Options which need to go late -- after all the user options -- go here.
flag_set(
# One might hope that these options would only be needed for C++
# compiles. But, sadly, users compile ".c" files with custom
# copts=["-x", "c++"], and expect that to be able to find C++ stdlib
# headers. It might be worth pondering how blaze could support this sort
# of use-case better.
actions = preprocessor_compile_actions +
[ACTION_NAMES.cc_flags_make_variable],
flags = [
"-iwithsysroot" + "/include/c++/v1",
"-iwithsysroot" + "/include/compat",
"-iwithsysroot" + "/include",
"-isystem",
emscripten_dir + "/lib/clang/20/include",
],
),
# Inputs and outputs
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
],
flag_groups = [
flag_group(
flags = ["-MD", "-MF", "%{dependency_file}"],
expand_if_available = "dependency_file",
),
],
),
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
],
flag_groups = [
flag_group(
flags = ["-c", "%{source_file}"],
expand_if_available = "source_file",
),
],
),
flag_set(
actions = [
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.clif_match,
],
flag_groups = [
flag_group(
flags = ["-S"],
expand_if_available = "output_assembly_file",
),
flag_group(
flags = ["-E"],
expand_if_available = "output_preprocess_file",
),
flag_group(
flags = ["-o", "%{output_file}"],
expand_if_available = "output_file",
),
],
),
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
flags = ["-o", "%{output_execpath}"],
expand_if_available = "output_execpath",
),
],
),
# And finally, the params file!
flag_set(
actions = all_link_actions,
flag_groups = [
flag_group(
flags = ["@%{linker_param_file}"],
expand_if_available = "linker_param_file",
),
],
),
flag_set(
actions = all_compile_actions,
flags = [
"-Wno-builtin-macro-redefined",
# Genrules may not escape quotes enough for these, so
# don't put them into $(CC_FLAGS):
'-D__DATE__="redacted"',
'-D__TIMESTAMP__="redacted"',
'-D__TIME__="redacted"',
],
),
flag_set(
actions = all_compile_actions,
flags = ["-Werror"],
features = ["wasm_warnings_as_errors"],
),
flag_set(
actions = all_link_actions,
flags = ["-sSTANDALONE_WASM"],
features = ["wasm_standalone"],
),
]
crosstool_default_env_sets = [
# Globals
env_set(
actions = all_compile_actions +
all_link_actions +
[ACTION_NAMES.cpp_link_static_library],
env_entries = [
env_entry(
key = "EM_BIN_PATH",
value = emscripten_dir,
),
env_entry(
key = "EM_CONFIG_PATH",
value = ctx.file.em_config.path,
),
],
),
# Use llvm backend. Off by default, enabled via --features=llvm_backend
env_set(
actions = all_compile_actions +
all_link_actions +
[ACTION_NAMES.cpp_link_static_library],
env_entries = [env_entry(key = "EMCC_WASM_BACKEND", value = "1")],
with_features = [with_feature_set(features = ["llvm_backend"])],
),
# Debug compile and link. Off by default, enabled via --features=emcc_debug
env_set(
actions = all_compile_actions,
env_entries = [env_entry(key = "EMCC_DEBUG", value = "1")],
with_features = [with_feature_set(features = ["emcc_debug"])],
),
# Debug only link step. Off by default, enabled via --features=emcc_debug_link
env_set(
actions = all_link_actions,
env_entries = [env_entry(key = "EMCC_DEBUG", value = "1")],
with_features = [
with_feature_set(features = ["emcc_debug"]),
with_feature_set(features = ["emcc_debug_link"]),
],
),
]
crosstool_default_flags_feature = feature(
name = "crosstool_default_flags",
enabled = True,
flag_sets = crosstool_default_flag_sets,
env_sets = crosstool_default_env_sets,
)
features.append(crosstool_default_flags_feature)
cxx_builtin_include_directories = [
emscripten_dir + "/emscripten/cache/sysroot/include/c++/v1",
emscripten_dir + "/emscripten/cache/sysroot/include/compat",
emscripten_dir + "/emscripten/cache/sysroot/include",
emscripten_dir + "/lib/clang/20/include",
]
artifact_name_patterns = []
make_variables = []
return cc_common.create_cc_toolchain_config_info(
ctx = ctx,
features = features,
action_configs = action_configs,
artifact_name_patterns = artifact_name_patterns,
cxx_builtin_include_directories = cxx_builtin_include_directories,
toolchain_identifier = toolchain_identifier,
host_system_name = host_system_name,
target_system_name = target_system_name,
target_cpu = target_cpu,
target_libc = target_libc,
compiler = compiler,
abi_version = abi_version,
abi_libc_version = abi_libc_version,
tool_paths = tool_paths,
make_variables = make_variables,
builtin_sysroot = builtin_sysroot,
cc_target_os = cc_target_os,
)
emscripten_cc_toolchain_config_rule = rule(
implementation = _impl,
attrs = {
"cpu": attr.string(mandatory = True, values = ["asmjs", "wasm"]),
"em_config": attr.label(mandatory = True, allow_single_file = True),
"emscripten_binaries": attr.label(mandatory = True, cfg = "exec"),
"script_extension": attr.string(mandatory = True, values = ["sh", "bat"]),
},
provides = [CcToolchainConfigInfo],
)