| """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], |
| ) |