@@ -113,6 +113,11 @@ def _cpp_component_impl(ctx):
113113 headers = ctx .files .hdrs
114114 wit_file = ctx .file .wit
115115
116+ # Detect if we need C++ compilation support (for source files, not bindings)
117+ # This allows C++ source files to work with both C and C++ bindings
118+ has_cpp_sources = any ([src .extension in ["cpp" , "cc" , "cxx" , "C" , "CPP" ] for src in sources ])
119+ needs_cpp_compilation = ctx .attr .language == "cpp" or has_cpp_sources
120+
116121 # Collect dependency headers and libraries using CcInfo provider
117122 dep_headers = []
118123 dep_libraries = []
@@ -154,7 +159,7 @@ def _cpp_component_impl(ctx):
154159
155160 # Generate C/C++ bindings from WIT
156161 wit_args = ctx .actions .args ()
157- wit_args .add ("c" )
162+ wit_args .add (ctx . attr . language )
158163 wit_args .add ("--out-dir" , bindings_dir .path )
159164
160165 if ctx .attr .world :
@@ -167,8 +172,8 @@ def _cpp_component_impl(ctx):
167172 arguments = [wit_args ],
168173 inputs = [wit_file ],
169174 outputs = [bindings_dir ],
170- mnemonic = "WitBindgenCpp" ,
171- progress_message = "Generating C/C++ bindings for %s" % ctx .label ,
175+ mnemonic = "WitBindgen" + ( "C" if ctx . attr . language == "c" else "Cpp" ) ,
176+ progress_message = "Generating %s bindings for %s" % ( ctx .attr . language . upper (), ctx . label ) ,
172177 )
173178
174179 # Create working directory for compilation using File Operations Component
@@ -226,8 +231,8 @@ def _cpp_component_impl(ctx):
226231 compile_args .add ("-O0" )
227232 compile_args .add ("-g" )
228233
229- # C++ specific flags
230- if ctx . attr . language == "cpp" :
234+ # C++ specific flags (for source compilation)
235+ if needs_cpp_compilation :
231236 if ctx .attr .enable_exceptions :
232237 # Enable exceptions if specifically requested
233238 compile_args .add ("-fexceptions" )
@@ -248,7 +253,7 @@ def _cpp_component_impl(ctx):
248253 compile_args .add ("-I" + work_dir .path )
249254
250255 # Add C++ standard library paths for wasm32-wasip2 target
251- if ctx . attr . language == "cpp" :
256+ if needs_cpp_compilation :
252257 # WASI SDK stores C++ headers in share/wasi-sysroot, not just sysroot
253258 if "/external/" in sysroot_path :
254259 toolchain_repo = sysroot_path .split ("/sysroot" )[0 ]
@@ -298,11 +303,12 @@ def _cpp_component_impl(ctx):
298303 for src in sources :
299304 compile_args .add (work_dir .path + "/" + src .basename )
300305
301- # Compile generated WIT binding C file separately (without C++ flags)
306+ # Compile generated WIT binding file separately
302307 # wit-bindgen generates filenames by converting hyphens to underscores: http-service-world -> http_service_world.c
303308 world_name = ctx .attr .world or "component" # Default to "component" if no world specified
304309 file_safe_world_name = world_name .replace ("-" , "_" ) # Convert hyphens to underscores for filesystem
305- binding_c_file = bindings_dir .path + "/" + file_safe_world_name + ".c"
310+ binding_ext = ".cpp" if ctx .attr .language == "cpp" else ".c"
311+ binding_c_file = bindings_dir .path + "/" + file_safe_world_name + binding_ext
306312 binding_h_file = bindings_dir .path + "/" + file_safe_world_name + ".h"
307313 binding_o_file = bindings_dir .path + "/" + file_safe_world_name + "_component_type.o"
308314
@@ -336,6 +342,27 @@ def _cpp_component_impl(ctx):
336342 binding_compile_args .add ("-fexceptions" )
337343 binding_compile_args .add ("-fcxx-exceptions" )
338344
345+ # C++ compilation flags for binding compilation
346+ if ctx .attr .language == "cpp" :
347+ # C++ standard (bindings require C++20 for std::span)
348+ if ctx .attr .cxx_std :
349+ binding_compile_args .add ("-std=" + ctx .attr .cxx_std )
350+ else :
351+ binding_compile_args .add ("-std=c++20" ) # Default to C++20 for bindings
352+
353+ # WASI SDK stores C++ headers in share/wasi-sysroot, not just sysroot
354+ if "/external/" in sysroot_path :
355+ toolchain_repo = sysroot_path .split ("/sysroot" )[0 ]
356+ wasi_sysroot = toolchain_repo + "/share/wasi-sysroot"
357+ else :
358+ wasi_sysroot = sysroot_path
359+ binding_compile_args .add ("-I" + wasi_sysroot + "/include/wasm32-wasip2/c++/v1" )
360+ binding_compile_args .add ("-I" + wasi_sysroot + "/include/c++/v1" )
361+
362+ # Also add clang's builtin headers
363+ if "/external/" in sysroot_path :
364+ binding_compile_args .add ("-I" + toolchain_repo + "/lib/clang/20/include" )
365+
339366 # Include directories
340367 binding_compile_args .add ("-I" + work_dir .path )
341368 binding_compile_args .add ("-I" + bindings_dir .path )
@@ -353,8 +380,8 @@ def _cpp_component_impl(ctx):
353380 arguments = [binding_compile_args ],
354381 inputs = [work_dir , bindings_dir ] + sysroot_files .files .to_list () + dep_headers + external_headers ,
355382 outputs = [binding_obj_file ],
356- mnemonic = "CompileCppBindings " ,
357- progress_message = "Compiling WIT bindings for %s" % ctx .label ,
383+ mnemonic = "Compile" + ( "C" if ctx . attr . language == "c" else "Cpp" ) + "Bindings " ,
384+ progress_message = "Compiling %s WIT bindings for %s" % ( ctx .attr . language . upper (), ctx . label ) ,
358385 )
359386
360387 # Add compiled binding object file and pre-compiled component type object to linking
@@ -370,8 +397,8 @@ def _cpp_component_impl(ctx):
370397 else :
371398 compile_args .add ("-l" + lib ) # Library name (e.g., "m" -> "-lm")
372399 else :
373- # Standard library linking for C++ language
374- if ctx . attr . language == "cpp" :
400+ # Standard library linking for C++ source files
401+ if needs_cpp_compilation :
375402 compile_args .add ("-lc++" )
376403 compile_args .add ("-lc++abi" )
377404
@@ -394,8 +421,8 @@ def _cpp_component_impl(ctx):
394421 arguments = [compile_args ],
395422 inputs = [work_dir , bindings_dir , binding_obj_file ] + sysroot_files .files .to_list () + dep_libraries + dep_headers + external_headers ,
396423 outputs = [wasm_binary ],
397- mnemonic = "CompileCppWasm " ,
398- progress_message = "Compiling C/C++ to WASM for %s" % ctx .label ,
424+ mnemonic = "Compile" + ( "C" if ctx . attr . language == "c" else "Cpp" ) + "Wasm " ,
425+ progress_message = "Compiling %s to WASM for %s" % ( ctx .attr . language . upper (), ctx . label ) ,
399426 )
400427
401428 # Embed WIT metadata and create component in one step
@@ -414,8 +441,8 @@ def _cpp_component_impl(ctx):
414441 arguments = [embed_args ],
415442 inputs = [wasm_binary , wit_file ],
416443 outputs = [component_wasm ],
417- mnemonic = "CreateCppComponent " ,
418- progress_message = "Creating WebAssembly component for %s" % ctx .label ,
444+ mnemonic = "Create" + ( "C" if ctx . attr . language == "c" else "Cpp" ) + "Component " ,
445+ progress_message = "Creating %s WebAssembly component for %s" % ( ctx .attr . language . upper (), ctx . label ) ,
419446 )
420447
421448 # Optional WIT validation
@@ -469,10 +496,12 @@ def _cpp_component_impl(ctx):
469496 exports = [ctx .attr .world ] if ctx .attr .world else [],
470497 metadata = {
471498 "name" : ctx .label .name ,
472- "language" : "cpp" ,
499+ "language" : ctx . attr . language ,
473500 "target" : "wasm32-wasip2" ,
474501 "wasi_sdk" : True ,
475502 "toolchain" : "wasi-sdk" ,
503+ "cxx_std" : ctx .attr .cxx_std if ctx .attr .cxx_std else None ,
504+ "optimization" : ctx .attr .optimize ,
476505 },
477506 profile = ctx .attr .optimization if hasattr (ctx .attr , "optimization" ) else "release" ,
478507 profile_variants = {},
@@ -625,7 +654,7 @@ def _cpp_wit_bindgen_impl(ctx):
625654
626655 # Generate C/C++ bindings
627656 args = ctx .actions .args ()
628- args .add ("c" )
657+ args .add (ctx . attr . language )
629658 args .add ("--out-dir" , bindings_dir .path )
630659
631660 if ctx .attr .world :
@@ -634,7 +663,8 @@ def _cpp_wit_bindgen_impl(ctx):
634663 if ctx .attr .stubs_only :
635664 args .add ("--stubs-only" )
636665
637- if ctx .attr .string_encoding :
666+ # string-encoding is only supported for C bindings
667+ if ctx .attr .string_encoding and ctx .attr .language == "c" :
638668 args .add ("--string-encoding" , ctx .attr .string_encoding )
639669
640670 args .add (wit_file .path )
@@ -644,8 +674,8 @@ def _cpp_wit_bindgen_impl(ctx):
644674 arguments = [args ],
645675 inputs = [wit_file ],
646676 outputs = [bindings_dir ],
647- mnemonic = "CppWitBindgen " ,
648- progress_message = "Generating C/C++ WIT bindings for %s" % ctx .label ,
677+ mnemonic = ( "C" if ctx . attr . language == "c" else "Cpp" ) + "WitBindgen " ,
678+ progress_message = "Generating %s WIT bindings for %s" % ( ctx .attr . language . upper (), ctx . label ) ,
649679 )
650680
651681 return [
@@ -675,6 +705,11 @@ cpp_wit_bindgen = rule(
675705 values = ["utf8" , "utf16" , "compact-utf16" ],
676706 doc = "String encoding to use in generated bindings" ,
677707 ),
708+ "language" : attr .string (
709+ default = "cpp" ,
710+ values = ["c" , "cpp" ],
711+ doc = "Language variant (c or cpp)" ,
712+ ),
678713 },
679714 toolchains = [
680715 "@rules_wasm_component//toolchains:cpp_component_toolchain_type" ,
@@ -750,6 +785,10 @@ def _cc_component_library_impl(ctx):
750785 sysroot = cpp_toolchain .sysroot
751786 sysroot_files = cpp_toolchain .sysroot_files
752787
788+ # Detect if we need C++ compilation support (for source files)
789+ has_cpp_sources = any ([src .extension in ["cpp" , "cc" , "cxx" , "C" , "CPP" ] for src in ctx .files .srcs ])
790+ needs_cpp_compilation = ctx .attr .language == "cpp" or has_cpp_sources
791+
753792 # Output library
754793 library = ctx .actions .declare_file ("lib{}.a" .format (ctx .attr .name ))
755794
@@ -821,8 +860,8 @@ def _cc_component_library_impl(ctx):
821860 compile_args .add ("-O0" )
822861 compile_args .add ("-g" )
823862
824- # C++ specific flags
825- if ctx . attr . language == "cpp" :
863+ # C++ specific flags (for source compilation)
864+ if needs_cpp_compilation :
826865 if ctx .attr .enable_exceptions :
827866 # Enable exceptions if specifically requested
828867 pass
@@ -837,7 +876,7 @@ def _cc_component_library_impl(ctx):
837876 compile_args .add ("-I" + work_dir .path ) # Workspace with staged headers
838877
839878 # Add C++ standard library paths for wasm32-wasip2 target
840- if ctx . attr . language == "cpp" :
879+ if needs_cpp_compilation :
841880 # WASI SDK stores C++ headers in share/wasi-sysroot, not just sysroot
842881 if "/external/" in sysroot_dir :
843882 toolchain_repo = sysroot_dir .split ("/sysroot" )[0 ]
@@ -897,8 +936,8 @@ def _cc_component_library_impl(ctx):
897936 arguments = [compile_args ],
898937 inputs = all_inputs ,
899938 outputs = [obj_file ],
900- mnemonic = "CompileCppObject " ,
901- progress_message = "Compiling {} for component library" .format (src .basename ),
939+ mnemonic = "Compile" + ( "C" if ctx . attr . language == "c" else "Cpp" ) + "Object " ,
940+ progress_message = "Compiling {} {} for component library" .format (ctx . attr . language . upper (), src .basename ),
902941 )
903942
904943 # Create static library
@@ -912,8 +951,8 @@ def _cc_component_library_impl(ctx):
912951 arguments = [ar_args ],
913952 inputs = object_files ,
914953 outputs = [library ],
915- mnemonic = "CreateCppLibrary " ,
916- progress_message = "Creating component library %s" % ctx .label ,
954+ mnemonic = "Create" + ( "C" if ctx . attr . language == "c" else "Cpp" ) + "Library " ,
955+ progress_message = "Creating %s component library %s" % ( ctx .attr . language . upper (), ctx . label ) ,
917956 )
918957
919958 # Collect transitive headers and libraries from dependencies
0 commit comments