From 181dcab6be1c66a23544a7cdcdd440e63e36abed Mon Sep 17 00:00:00 2001 From: Matija Kecman Date: Tue, 25 Nov 2025 10:39:37 -0800 Subject: [PATCH] Combine markers and content and reorganize parts of the WASM template file PiperOrigin-RevId: 836729951 Change-Id: Ib3bb25a23325cfbd84fd0439243db37ca8236bf3 --- wasm/codegen/generated/bindings.cc | 131 ++++++++++++++--------------- wasm/codegen/generators/structs.py | 65 ++++++-------- wasm/codegen/templates/bindings.cc | 78 ++++++++--------- 3 files changed, 123 insertions(+), 151 deletions(-) diff --git a/wasm/codegen/generated/bindings.cc b/wasm/codegen/generated/bindings.cc index 9ae27fea..eca58689 100644 --- a/wasm/codegen/generated/bindings.cc +++ b/wasm/codegen/generated/bindings.cc @@ -39,13 +39,8 @@ namespace mujoco::wasm { using emscripten::enum_; -using emscripten::class_; using emscripten::function; using emscripten::val; -using emscripten::constant; -using emscripten::register_optional; -using emscripten::register_type; -using emscripten::register_vector; using emscripten::return_value_policy::reference; using emscripten::return_value_policy::take_ownership; @@ -115,33 +110,33 @@ val get_mjRNDSTRING() { return MakeValArray3(mjRNDSTRING); } EMSCRIPTEN_BINDINGS(mujoco_constants) { // from mjmodel.h - constant("mjPI", mjPI); - constant("mjMAXVAL", mjMAXVAL); - constant("mjMINMU", mjMINMU); - constant("mjMINIMP", mjMINIMP); - constant("mjMAXIMP", mjMAXIMP); - constant("mjMAXCONPAIR", mjMAXCONPAIR); - constant("mjNEQDATA", mjNEQDATA); - constant("mjNDYN", mjNDYN); - constant("mjNGAIN", mjNGAIN); - constant("mjNBIAS", mjNBIAS); - constant("mjNREF", mjNREF); - constant("mjNIMP", mjNIMP); - constant("mjNSOLVER", mjNSOLVER); + emscripten::constant("mjPI", mjPI); + emscripten::constant("mjMAXVAL", mjMAXVAL); + emscripten::constant("mjMINMU", mjMINMU); + emscripten::constant("mjMINIMP", mjMINIMP); + emscripten::constant("mjMAXIMP", mjMAXIMP); + emscripten::constant("mjMAXCONPAIR", mjMAXCONPAIR); + emscripten::constant("mjNEQDATA", mjNEQDATA); + emscripten::constant("mjNDYN", mjNDYN); + emscripten::constant("mjNGAIN", mjNGAIN); + emscripten::constant("mjNBIAS", mjNBIAS); + emscripten::constant("mjNREF", mjNREF); + emscripten::constant("mjNIMP", mjNIMP); + emscripten::constant("mjNSOLVER", mjNSOLVER); // from mjvisualize.h - constant("mjNGROUP", mjNGROUP); - constant("mjMAXLIGHT", mjMAXLIGHT); - constant("mjMAXOVERLAY", mjMAXOVERLAY); - constant("mjMAXLINE", mjMAXLINE); - constant("mjMAXLINEPNT", mjMAXLINEPNT); - constant("mjMAXPLANEGRID", mjMAXPLANEGRID); + emscripten::constant("mjNGROUP", mjNGROUP); + emscripten::constant("mjMAXLIGHT", mjMAXLIGHT); + emscripten::constant("mjMAXOVERLAY", mjMAXOVERLAY); + emscripten::constant("mjMAXLINE", mjMAXLINE); + emscripten::constant("mjMAXLINEPNT", mjMAXLINEPNT); + emscripten::constant("mjMAXPLANEGRID", mjMAXPLANEGRID); // from mujoco.h - constant("mjVERSION_HEADER", mjVERSION_HEADER); + emscripten::constant("mjVERSION_HEADER", mjVERSION_HEADER); // from mjtnum.h - constant("mjMINVAL", mjMINVAL); + emscripten::constant("mjMINVAL", mjMINVAL); // emscripten::constant() is designed for simple, compile-time literal values // (like numbers or a single string literal), complex values need to be @@ -10058,6 +10053,36 @@ EMSCRIPTEN_BINDINGS(mujoco_structs) { .property("status", &MjvScene::status, &MjvScene::set_status, reference()) .property("stereo", &MjvScene::stereo, &MjvScene::set_stereo, reference()) .property("translate", &MjvScene::translate); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); + emscripten::register_optional(); // TODO: should be generated in future CLs -- // emscripten::register_vector("MjSolverStatVec"); @@ -12753,64 +12778,34 @@ EMSCRIPTEN_BINDINGS(mujoco_functions) { function("mjv_updateCamera", &mjv_updateCamera_wrapper); function("mjv_updateScene", &mjv_updateScene_wrapper); function("mjv_updateSkin", &mjv_updateSkin_wrapper); - class_>("FloatBuffer") + emscripten::class_>("FloatBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); - class_>("DoubleBuffer") + emscripten::class_>("DoubleBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); - class_>("IntBuffer") + emscripten::class_>("IntBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); - register_vector("mjStringVec"); - register_vector("mjIntVec"); - register_vector("mjIntVecVec"); - register_vector("mjFloatVec"); - register_vector("mjFloatVecVec"); - register_vector("mjDoubleVec"); // register_type gives better type information (val is mapped to any by default) - register_type("number[]"); - register_type("string"); - register_vector("mjByteVec"); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); - register_optional(); + emscripten::register_vector("mjStringVec"); + emscripten::register_vector("mjIntVec"); + emscripten::register_vector("mjIntVecVec"); + emscripten::register_vector("mjFloatVec"); + emscripten::register_vector("mjFloatVecVec"); + emscripten::register_vector("mjDoubleVec"); + emscripten::register_type("number[]"); + emscripten::register_type("string"); + emscripten::register_vector("mjByteVec"); } } // namespace mujoco::wasm diff --git a/wasm/codegen/generators/structs.py b/wasm/codegen/generators/structs.py index 55feda2c..8b45e242 100644 --- a/wasm/codegen/generators/structs.py +++ b/wasm/codegen/generators/structs.py @@ -734,23 +734,19 @@ def generate(struct_to_bind: List[str]) -> list[tuple[str, list[str]]]: typedefs.append( f"using {type_name} = decltype(::{s['parent']}::{s['field_name']});" ) - markers_and_content.append(( - "// {{ ANONYMOUS_STRUCT_TYPEDEFS }}", - typedefs, - )) # Sort by struct name by dependency to ensure deterministic output order dependency_sorted_struct_names = sort_structs_by_dependency( structs_to_bind_data ) - autogenned_struct_definitions = [] - for struct_name in dependency_sorted_struct_names: - struct_data = structs_to_bind_data[struct_name] + structs_header = [] + for s in dependency_sorted_struct_names: + struct_data = structs_to_bind_data[s] if struct_data.wrapped_header: - autogenned_struct_definitions.append(struct_data.wrapped_header + "\n") + structs_header.append(struct_data.wrapped_header + "\n") else: - definitions = [] + definitions: list[str] = [] for f in sorted(struct_data.wrapped_fields, key=lambda f: f.definition): if f.definition: definitions.append(f.definition) @@ -758,42 +754,29 @@ def generate(struct_to_bind: List[str]) -> list[tuple[str, list[str]]]: f"// INSERT-GENERATED-{struct_data.wrap_name}-DEFINITIONS", definitions, )) - markers_and_content.append(( - "// {{ AUTOGENNED_STRUCTS_HEADER }}", - autogenned_struct_definitions, - )) - autogenned_struct_source = [] - for struct_name in dependency_sorted_struct_names: - struct_data = structs_to_bind_data[struct_name] + structs_source = [] + for s in dependency_sorted_struct_names: + struct_data = structs_to_bind_data[s] if struct_data.wrapped_source: - autogenned_struct_source.append(struct_data.wrapped_source + "\n") + structs_source.append(struct_data.wrapped_source + "\n") - autogenned_struct_bindings = [] + struct_bindings = [] alphabetically_sorted_struct_names = sorted(structs_to_bind_data.keys()) - for struct_name in alphabetically_sorted_struct_names: - struct_data = structs_to_bind_data[struct_name] - autogenned_struct_bindings.append(struct_data.bindings) + for s in alphabetically_sorted_struct_names: + struct_data = structs_to_bind_data[s] + struct_bindings.append(struct_data.bindings) + for s in sorted(struct_to_bind): + w = common.capitalize(s) + if w.startswith("Mjs") or w == "MjSpec": + struct_bindings.append(f"emscripten::register_optional<{w}>();") - markers_and_content.append(( - "// {{ AUTOGENNED_STRUCTS_SOURCE }}", - autogenned_struct_source, - )) - markers_and_content.append(( - "// {{ AUTOGENNED_STRUCTS_BINDINGS }}", - autogenned_struct_bindings, - )) - - # Generate optional bindings - optional_bindings = [] - for s_name in sorted(struct_to_bind): - w_name = common.capitalize(s_name) - if w_name.startswith("Mjs") or w_name == "MjSpec": - optional_bindings.append(f"register_optional<{w_name}>();") - - markers_and_content.append(( - "// {{ OPTIONAL_STRUCT_BINDINGS }}", - optional_bindings, - )) + # Combine all the markers and content into a single list + markers_and_content += [ + ("// {{ ANONYMOUS_STRUCT_TYPEDEFS }}", typedefs), + ("// {{ STRUCTS_HEADER }}", structs_header), + ("// {{ STRUCTS_SOURCE }}", structs_source), + ("// {{ STRUCTS_BINDINGS }}", struct_bindings), + ] return markers_and_content diff --git a/wasm/codegen/templates/bindings.cc b/wasm/codegen/templates/bindings.cc index c67f8768..1db0553b 100644 --- a/wasm/codegen/templates/bindings.cc +++ b/wasm/codegen/templates/bindings.cc @@ -39,13 +39,8 @@ namespace mujoco::wasm { using emscripten::enum_; -using emscripten::class_; using emscripten::function; using emscripten::val; -using emscripten::constant; -using emscripten::register_optional; -using emscripten::register_type; -using emscripten::register_vector; using emscripten::return_value_policy::reference; using emscripten::return_value_policy::take_ownership; @@ -115,33 +110,33 @@ val get_mjRNDSTRING() { return MakeValArray3(mjRNDSTRING); } EMSCRIPTEN_BINDINGS(mujoco_constants) { // from mjmodel.h - constant("mjPI", mjPI); - constant("mjMAXVAL", mjMAXVAL); - constant("mjMINMU", mjMINMU); - constant("mjMINIMP", mjMINIMP); - constant("mjMAXIMP", mjMAXIMP); - constant("mjMAXCONPAIR", mjMAXCONPAIR); - constant("mjNEQDATA", mjNEQDATA); - constant("mjNDYN", mjNDYN); - constant("mjNGAIN", mjNGAIN); - constant("mjNBIAS", mjNBIAS); - constant("mjNREF", mjNREF); - constant("mjNIMP", mjNIMP); - constant("mjNSOLVER", mjNSOLVER); + emscripten::constant("mjPI", mjPI); + emscripten::constant("mjMAXVAL", mjMAXVAL); + emscripten::constant("mjMINMU", mjMINMU); + emscripten::constant("mjMINIMP", mjMINIMP); + emscripten::constant("mjMAXIMP", mjMAXIMP); + emscripten::constant("mjMAXCONPAIR", mjMAXCONPAIR); + emscripten::constant("mjNEQDATA", mjNEQDATA); + emscripten::constant("mjNDYN", mjNDYN); + emscripten::constant("mjNGAIN", mjNGAIN); + emscripten::constant("mjNBIAS", mjNBIAS); + emscripten::constant("mjNREF", mjNREF); + emscripten::constant("mjNIMP", mjNIMP); + emscripten::constant("mjNSOLVER", mjNSOLVER); // from mjvisualize.h - constant("mjNGROUP", mjNGROUP); - constant("mjMAXLIGHT", mjMAXLIGHT); - constant("mjMAXOVERLAY", mjMAXOVERLAY); - constant("mjMAXLINE", mjMAXLINE); - constant("mjMAXLINEPNT", mjMAXLINEPNT); - constant("mjMAXPLANEGRID", mjMAXPLANEGRID); + emscripten::constant("mjNGROUP", mjNGROUP); + emscripten::constant("mjMAXLIGHT", mjMAXLIGHT); + emscripten::constant("mjMAXOVERLAY", mjMAXOVERLAY); + emscripten::constant("mjMAXLINE", mjMAXLINE); + emscripten::constant("mjMAXLINEPNT", mjMAXLINEPNT); + emscripten::constant("mjMAXPLANEGRID", mjMAXPLANEGRID); // from mujoco.h - constant("mjVERSION_HEADER", mjVERSION_HEADER); + emscripten::constant("mjVERSION_HEADER", mjVERSION_HEADER); // from mjtnum.h - constant("mjMINVAL", mjMINVAL); + emscripten::constant("mjMINVAL", mjMINVAL); // emscripten::constant() is designed for simple, compile-time literal values // (like numbers or a single string literal), complex values need to be @@ -159,9 +154,9 @@ EMSCRIPTEN_BINDINGS(mujoco_constants) { // {{ ANONYMOUS_STRUCT_TYPEDEFS }} -// {{ AUTOGENNED_STRUCTS_HEADER }} +// {{ STRUCTS_HEADER }} -// {{ AUTOGENNED_STRUCTS_SOURCE }} +// {{ STRUCTS_SOURCE }} struct MjvScene { MjvScene(); @@ -470,7 +465,7 @@ int mj_setLengthRange_wrapper(const MjModel& m, const MjData& d, int index, cons } EMSCRIPTEN_BINDINGS(mujoco_structs) { - // {{ AUTOGENNED_STRUCTS_BINDINGS }} + // {{ STRUCTS_BINDINGS }} // TODO: should be generated in future CLs -- // emscripten::register_vector("MjSolverStatVec"); @@ -488,35 +483,34 @@ EMSCRIPTEN_BINDINGS(mujoco_functions) { function("parseXMLString", &parseXMLString_wrapper, take_ownership()); function("error", &error_wrapper); // {{ FUNCTION_BINDINGS }} - class_>("FloatBuffer") + emscripten::class_>("FloatBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); - class_>("DoubleBuffer") + emscripten::class_>("DoubleBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); - class_>("IntBuffer") + emscripten::class_>("IntBuffer") .constructor() .class_function("FromArray", &WasmBuffer::FromArray) .function("GetPointer", &WasmBuffer::GetPointer) .function("GetElementCount", &WasmBuffer::GetElementCount) .function("GetView", &WasmBuffer::GetView); - register_vector("mjStringVec"); - register_vector("mjIntVec"); - register_vector("mjIntVecVec"); - register_vector("mjFloatVec"); - register_vector("mjFloatVecVec"); - register_vector("mjDoubleVec"); // register_type gives better type information (val is mapped to any by default) - register_type("number[]"); - register_type("string"); - register_vector("mjByteVec"); - // {{ OPTIONAL_STRUCT_BINDINGS }} + emscripten::register_vector("mjStringVec"); + emscripten::register_vector("mjIntVec"); + emscripten::register_vector("mjIntVecVec"); + emscripten::register_vector("mjFloatVec"); + emscripten::register_vector("mjFloatVecVec"); + emscripten::register_vector("mjDoubleVec"); + emscripten::register_type("number[]"); + emscripten::register_type("string"); + emscripten::register_vector("mjByteVec"); } } // namespace mujoco::wasm