Fix WASM build issues, improve test coverage and improve cmake files
* Ensure compiler.usethread=0 is set before compilation in single-threaded WASM builds * Explicitly enable exceptions for the single-threaded WASM module * Test the single-threaded module in addition to the multi-threaded module in internal and external CI * Consolidate wasm/tests/CMakeLists.txt into wasm/CMakeLists.txt, fixing the single-threaded benchmark test build which was missing shared linker flags PiperOrigin-RevId: 901149728 Change-Id: If4946e29e5116610782d218906cf3f5940c1cdd0
This commit is contained in:
committed by
Copybara-Service
parent
f91ce9a627
commit
c23b5e8420
@@ -212,25 +212,28 @@ build_test_wasm() {
|
||||
echo "Building and testing WASM bindings..."
|
||||
source emsdk/emsdk_env.sh
|
||||
export PATH="$(pwd)/node_modules/.bin:$PATH"
|
||||
|
||||
echo "Building Multi-Threaded version..."
|
||||
echo "Build MuJoCo with Emscripten (Multi-Threaded)..."
|
||||
emcmake cmake -B build_wasm_mt \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF \
|
||||
-DMUJOCO_WASM_THREADS=ON \
|
||||
$WASM_CMAKE_ARGS
|
||||
cmake --build build_wasm_mt --parallel $(nproc)
|
||||
|
||||
echo "Run bindings tests for Multi-Threaded version..."
|
||||
npm run test --prefix ./wasm
|
||||
|
||||
echo "Moving Multi-Thread version under mt subfolder..."
|
||||
mkdir -p wasm/dist/mt
|
||||
mv wasm/dist/mujoco.* wasm/dist/mt/
|
||||
|
||||
echo "Building Single-Threaded version..."
|
||||
echo "Build MuJoCo with Emscripten (Single-Threaded)..."
|
||||
emcmake cmake -B build_wasm_st \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION:BOOL=OFF \
|
||||
-DMUJOCO_WASM_THREADS=OFF \
|
||||
$WASM_CMAKE_ARGS
|
||||
cmake --build build_wasm_st --parallel $(nproc)
|
||||
|
||||
echo "Run bindings tests for Single-Threaded version..."
|
||||
npm run test --prefix ./wasm
|
||||
}
|
||||
|
||||
|
||||
@@ -132,9 +132,6 @@ endif()
|
||||
|
||||
if(EMSCRIPTEN)
|
||||
add_subdirectory(wasm)
|
||||
if(MUJOCO_BUILD_TESTS_WASM)
|
||||
add_subdirectory(wasm/tests)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -4967,6 +4967,20 @@ void mjCModel::ResolveKeyframes(const mjModel* m) {
|
||||
}
|
||||
|
||||
void mjCModel::TryCompile(mjModel*& m, mjData*& d, const mjVFS* vfs) {
|
||||
#if defined(__EMSCRIPTEN__) && !defined(MUJOCO_WASM_THREADS)
|
||||
// The MuJoCo compiler defaults to usethread=1, which causes it to try to
|
||||
// create pthreads for compilation. In the single-threaded WASM build, this
|
||||
// crashes because there is no threading support, so we disable threading on
|
||||
// the internal compiler struct (not the spec) to avoid permanently mutating
|
||||
// the spec (which would cause usethread="false" to appear in a saved XML).
|
||||
struct ScopedDisableThreading {
|
||||
mjtByte& ref;
|
||||
mjtByte saved;
|
||||
explicit ScopedDisableThreading(mjtByte& r) : ref(r), saved(r) { ref = 0; }
|
||||
~ScopedDisableThreading() { ref = saved; }
|
||||
} disable_usethread(compiler.usethread);
|
||||
#endif
|
||||
|
||||
// check if nan test works
|
||||
double test = mjNAN;
|
||||
if (mjuu_defined(test)) {
|
||||
|
||||
+58
-18
@@ -22,16 +22,14 @@ include_directories(${PROJECT_SOURCE_DIR})
|
||||
|
||||
link_directories(${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
file(GLOB MUJOCO_WASM_FILES
|
||||
"codegen/generated/*.cc"
|
||||
"unpack.cc"
|
||||
)
|
||||
# Set Emscripten compile flags.
|
||||
# -fexceptions is required for val::throw_() (used by ThrowMujocoErrorToJS) to
|
||||
# actually throw a JS exception. Without it, Emscripten compiles throw as a
|
||||
# no-op. In the MT build, -pthread implicitly enables exception support, but
|
||||
# the ST build needs it set explicitly here.
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions")
|
||||
|
||||
if(NOT MUJOCO_WASM_FILES)
|
||||
message(FATAL_ERROR "No source files found in codegen/generated/")
|
||||
endif()
|
||||
|
||||
# Set Emscripten linker flags
|
||||
# Set Emscripten linker flags shared by all WASM targets.
|
||||
set(EMCC_LINKER_FLAGS
|
||||
"--bind"
|
||||
"-s ASSERTIONS=1"
|
||||
@@ -42,9 +40,9 @@ set(EMCC_LINKER_FLAGS
|
||||
"-s EXPORTED_RUNTIME_METHODS=['ccall','cwrap','FS','MEMFS']"
|
||||
"-s EXPORT_NAME=loadMujoco"
|
||||
"-s DISABLE_EXCEPTION_CATCHING=0"
|
||||
"-fexceptions"
|
||||
"-gsource-map"
|
||||
"-g"
|
||||
"--emit-tsd mujoco.d.ts"
|
||||
)
|
||||
if(MUJOCO_WASM_THREADS)
|
||||
list(APPEND EMCC_LINKER_FLAGS
|
||||
@@ -53,7 +51,28 @@ if(MUJOCO_WASM_THREADS)
|
||||
)
|
||||
add_definitions(-DMUJOCO_WASM_THREADS)
|
||||
endif()
|
||||
string (REPLACE ";" " " EMCC_LINKER_FLAGS_STR "${EMCC_LINKER_FLAGS}")
|
||||
|
||||
# Common link libraries for all WASM targets. The mujoco library is linked as a
|
||||
# whole archive to avoid losing plugin registration such as obj_decoder and
|
||||
# stl_decoder.
|
||||
set(MUJOCO_WASM_LINK_LIBRARIES
|
||||
-Wl,--whole-archive mujoco -Wl,--no-whole-archive
|
||||
ccd lodepng tinyxml2 qhullstatic_r
|
||||
)
|
||||
|
||||
# --- Main WASM bindings target ---
|
||||
|
||||
file(GLOB MUJOCO_WASM_FILES
|
||||
"codegen/generated/*.cc"
|
||||
"unpack.cc"
|
||||
)
|
||||
|
||||
if(NOT MUJOCO_WASM_FILES)
|
||||
message(FATAL_ERROR "No source files found in codegen/generated/")
|
||||
endif()
|
||||
|
||||
set(MUJOCO_WASM_LINKER_FLAGS ${EMCC_LINKER_FLAGS} "--emit-tsd mujoco.d.ts")
|
||||
string(REPLACE ";" " " MUJOCO_WASM_LINKER_FLAGS_STR "${MUJOCO_WASM_LINKER_FLAGS}")
|
||||
|
||||
add_executable(mujoco_wasm ${MUJOCO_WASM_FILES})
|
||||
|
||||
@@ -61,15 +80,36 @@ add_executable(mujoco_wasm ${MUJOCO_WASM_FILES})
|
||||
# `mujoco` library target, but emit artifacts named `mujoco.*` by setting the
|
||||
# output name. Also apply the emscripten linker flags to the wasm target.
|
||||
set_target_properties(mujoco_wasm PROPERTIES
|
||||
LINK_FLAGS "${EMCC_LINKER_FLAGS_STR}"
|
||||
LINK_FLAGS "${MUJOCO_WASM_LINKER_FLAGS_STR}"
|
||||
OUTPUT_NAME "mujoco"
|
||||
)
|
||||
|
||||
# Link the mujoco library as a whole archive to avoid losing plugin
|
||||
# registration such as obj_decoder and stl_decoder.
|
||||
target_link_libraries(mujoco_wasm PRIVATE
|
||||
-Wl,--whole-archive mujoco -Wl,--no-whole-archive
|
||||
ccd lodepng tinyxml2 qhullstatic_r
|
||||
)
|
||||
target_link_libraries(mujoco_wasm PRIVATE ${MUJOCO_WASM_LINK_LIBRARIES})
|
||||
|
||||
install(TARGETS mujoco_wasm DESTINATION ${DIVISIBLE_INSTALL_BIN_DIR})
|
||||
|
||||
# --- Benchmark target ---
|
||||
|
||||
if(MUJOCO_BUILD_TESTS_WASM)
|
||||
file(GLOB MUJOCO_WASM_BENCHMARK_FILES
|
||||
"tests/benchmark_test.cc"
|
||||
"unpack.cc"
|
||||
)
|
||||
|
||||
if(NOT MUJOCO_WASM_BENCHMARK_FILES)
|
||||
message(FATAL_ERROR "No benchmark source files found")
|
||||
endif()
|
||||
|
||||
set(BENCHMARK_LINKER_FLAGS ${EMCC_LINKER_FLAGS} "--emit-tsd mujoco_wasm_benchmark.d.ts")
|
||||
string(REPLACE ";" " " BENCHMARK_LINKER_FLAGS_STR "${BENCHMARK_LINKER_FLAGS}")
|
||||
|
||||
add_executable(mujoco_wasm_benchmark ${MUJOCO_WASM_BENCHMARK_FILES})
|
||||
|
||||
set_target_properties(mujoco_wasm_benchmark PROPERTIES
|
||||
LINK_FLAGS "${BENCHMARK_LINKER_FLAGS_STR}"
|
||||
)
|
||||
|
||||
target_link_libraries(mujoco_wasm_benchmark PRIVATE ${MUJOCO_WASM_LINK_LIBRARIES})
|
||||
|
||||
install(TARGETS mujoco_wasm_benchmark DESTINATION ${DIVISIBLE_INSTALL_BIN_DIR})
|
||||
endif()
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
# Copyright 2025 DeepMind Technologies Limited
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/wasm/dist")
|
||||
|
||||
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/wasm)
|
||||
|
||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src)
|
||||
include_directories(${PROJECT_SOURCE_DIR})
|
||||
|
||||
link_directories(${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
file(GLOB MUJOCO_WASM_FILES
|
||||
"benchmark_test.cc"
|
||||
"../unpack.cc"
|
||||
)
|
||||
|
||||
if(NOT MUJOCO_WASM_FILES)
|
||||
message(FATAL_ERROR "No source files found")
|
||||
endif()
|
||||
|
||||
# Set Emscripten linker flags
|
||||
set(EMCC_LINKER_FLAGS
|
||||
"--bind"
|
||||
"-pthread"
|
||||
"-s PTHREAD_POOL_SIZE=navigator.hardwareConcurrency"
|
||||
"-s ASSERTIONS=1"
|
||||
"-s ALLOW_MEMORY_GROWTH=1"
|
||||
"-s EXPORT_ES6=1"
|
||||
"-s MODULARIZE=1"
|
||||
"-s FORCE_FILESYSTEM=1"
|
||||
"-s EXPORTED_RUNTIME_METHODS=['ccall','cwrap','FS','MEMFS']"
|
||||
"-s EXPORT_NAME=loadMujoco"
|
||||
"-gsource-map"
|
||||
"-g"
|
||||
"--emit-tsd mujoco_wasm_benchmark.d.ts"
|
||||
)
|
||||
string (REPLACE ";" " " EMCC_LINKER_FLAGS_STR "${EMCC_LINKER_FLAGS}")
|
||||
|
||||
add_executable(mujoco_wasm_benchmark ${MUJOCO_WASM_FILES})
|
||||
|
||||
set_target_properties(mujoco_wasm_benchmark PROPERTIES LINK_FLAGS "${EMCC_LINKER_FLAGS_STR}")
|
||||
|
||||
# Link the mujoco library as a whole archive to avoid losing plugin
|
||||
# registration such as obj_decoder and stl_decoder.
|
||||
target_link_libraries(mujoco_wasm_benchmark PRIVATE
|
||||
-Wl,--whole-archive mujoco -Wl,--no-whole-archive
|
||||
ccd lodepng tinyxml2 qhullstatic_r
|
||||
)
|
||||
|
||||
install(TARGETS mujoco_wasm_benchmark DESTINATION ${DIVISIBLE_INSTALL_BIN_DIR})
|
||||
Reference in New Issue
Block a user