From a98113e47fd859ee0919ceb91eb3179b927a1897 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 16 Jan 2025 22:45:22 -0800 Subject: [PATCH] Upgrade emsdk version to v4.0.1 --- .gitmodules | 2 +- cgmanifests/generated/cgmanifest.json | 2 +- cmake/external/emsdk | 2 +- .../external/onnxruntime_external_deps.cmake | 2 +- cmake/onnxruntime_webassembly.cmake | 55 ++++++++++++++++++ cmake/patches/emscripten/patch_3.1.74.tgz | Bin 4655 -> 0 bytes cmake/patches/emscripten/patch_4.0.1.tgz | Bin 0 -> 4631 bytes tools/ci_build/build.py | 2 +- .../templates/linux-wasm-ci.yml | 8 +-- 9 files changed, 64 insertions(+), 9 deletions(-) delete mode 100644 cmake/patches/emscripten/patch_3.1.74.tgz create mode 100644 cmake/patches/emscripten/patch_4.0.1.tgz diff --git a/.gitmodules b/.gitmodules index 29ca8821f8eb8..4d4a4b965420a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,4 +7,4 @@ [submodule "cmake/external/emsdk"] path = cmake/external/emsdk url = https://github.com/emscripten-core/emsdk.git - branch = 3.1.59 + branch = 4.0.1 diff --git a/cgmanifests/generated/cgmanifest.json b/cgmanifests/generated/cgmanifest.json index 044588c080072..3ec34488aa084 100644 --- a/cgmanifests/generated/cgmanifest.json +++ b/cgmanifests/generated/cgmanifest.json @@ -6,7 +6,7 @@ "component": { "type": "git", "git": { - "commitHash": "d52c46520124845b1e0e0525f2759299d840143f", + "commitHash": "9dbdc4b3437750b85d16931c7c801bb71a782122", "repositoryUrl": "https://github.com/emscripten-core/emsdk.git" }, "comments": "git submodule at cmake/external/emsdk" diff --git a/cmake/external/emsdk b/cmake/external/emsdk index d52c465201248..9dbdc4b343775 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit d52c46520124845b1e0e0525f2759299d840143f +Subproject commit 9dbdc4b3437750b85d16931c7c801bb71a782122 diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index 761ce47582ee5..47c456e43fda0 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -653,7 +653,7 @@ if (onnxruntime_USE_WEBGPU) # # We keep a copy of the missing file(s) in ${PROJECT_SOURCE_DIR}/patches/emscripten/, and now we extract them to the # emscripten toolchain folder. - execute_process(COMMAND ${CMAKE_COMMAND} -E tar x "${PROJECT_SOURCE_DIR}/patches/emscripten/patch_3.1.74.tgz" + execute_process(COMMAND ${CMAKE_COMMAND} -E tar x "${PROJECT_SOURCE_DIR}/patches/emscripten/patch_4.0.1.tgz" WORKING_DIRECTORY ${DAWN_EMSCRIPTEN_TOOLCHAIN}) else() if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) diff --git a/cmake/onnxruntime_webassembly.cmake b/cmake/onnxruntime_webassembly.cmake index 6cd05d1ad024b..2c4cdebcf450a 100644 --- a/cmake/onnxruntime_webassembly.cmake +++ b/cmake/onnxruntime_webassembly.cmake @@ -472,4 +472,59 @@ jsepDownload:_pp_") endif() set_target_properties(onnxruntime_webassembly PROPERTIES OUTPUT_NAME ${target_name} SUFFIX ".mjs") + + # + # The following POST_BUILD script is a workaround for enabling: + # - using onnxruntime-web with Multi-threading enabled when import from CDN + # - using onnxruntime-web when consumed in some frameworks like Vite + # + # In the use case mentioned above, the file name of the script may be changed. So we need to replace the line: + # `new Worker(new URL("ort-wasm-*.mjs", import.meta.url),` + # with + # `new Worker(new URL(import.meta.url),` + # + # This behavior is introduced in https://github.com/emscripten-core/emscripten/pull/22165. Since it's unlikely to be + # reverted, and there is no config to disable this behavior, we have to use a post-build script to workaround it. + # + + # Generate a script to do the post-build work + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/wasm_post_build.js " + const fs = require('fs'); + const path = require('path'); + + // node wasm_post_build.js + const mjsFilePath = process.argv[2]; + let contents = fs.readFileSync(mjsFilePath).toString(); + + const regex = 'new Worker\\\\(new URL\\\\(\".+?\", ?import\\\\.meta\\\\.url\\\\),'; + const matches = [...contents.matchAll(new RegExp(regex, 'g'))]; + if (matches.length !== 1) { + throw new Error( + `Unexpected number of matches for \"${regex}\" in \"${filepath}\": ${matches.length}.`, + ); + } + + // Replace the only occurrence. + contents = contents.replace( + new RegExp(regex), + `new Worker(new URL(import.meta.url),`, + ); + + fs.writeFileSync(mjsFilePath, contents); + " + ) + + find_program(NODE_EXECUTABLE node required) + if (NOT NODE_EXECUTABLE) + message(FATAL_ERROR "Node is required to run the post-build script") + endif() + + add_custom_command( + TARGET onnxruntime_webassembly + POST_BUILD + # Backup file at $.bak + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$.bak" + COMMAND ${CMAKE_COMMAND} -E echo "Performing post-process for $" + COMMAND ${NODE_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/wasm_post_build.js" "$" + ) endif() diff --git a/cmake/patches/emscripten/patch_3.1.74.tgz b/cmake/patches/emscripten/patch_3.1.74.tgz deleted file mode 100644 index cfb52de6386538aede41508e829843fecc858433..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4655 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 diff --git a/cmake/patches/emscripten/patch_4.0.1.tgz b/cmake/patches/emscripten/patch_4.0.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..6a4306472458d7cb5377d1b8e2a32d6238eeac65 GIT binary patch literal 4631 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 N^Dlu3I=TQr0034Q__+W8 literal 0 HcmV?d00001 diff --git a/tools/ci_build/build.py b/tools/ci_build/build.py index bce7552854a4c..c8b115c7054f8 100644 --- a/tools/ci_build/build.py +++ b/tools/ci_build/build.py @@ -488,7 +488,7 @@ def convert_arg_line_to_args(self, arg_line): # WebAssembly build parser.add_argument("--build_wasm", action="store_true", help="Build for WebAssembly") parser.add_argument("--build_wasm_static_lib", action="store_true", help="Build for WebAssembly static library") - parser.add_argument("--emsdk_version", default="3.1.59", help="Specify version of emsdk") + parser.add_argument("--emsdk_version", default="4.0.1", help="Specify version of emsdk") parser.add_argument("--enable_wasm_simd", action="store_true", help="Enable WebAssembly SIMD") parser.add_argument("--enable_wasm_threads", action="store_true", help="Enable WebAssembly multi-threads support") diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index 1df740798750d..08d5ab0c05ed2 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -90,15 +90,15 @@ jobs: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 3.1.59 ccache-git-emscripten-64bit - ./emsdk activate 3.1.59 ccache-git-emscripten-64bit + ./emsdk install 4.0.1 ccache-git-emscripten-64bit + ./emsdk activate 4.0.1 ccache-git-emscripten-64bit displayName: 'emsdk install and activate ccache for emscripten' - ${{if eq(parameters.WithCache, false)}}: - script: | set -ex cd '$(Build.SourcesDirectory)/cmake/external/emsdk' - ./emsdk install 3.1.59 - ./emsdk activate 3.1.59 + ./emsdk install 4.0.1 + ./emsdk activate 4.0.1 displayName: 'emsdk install and activate ccache for emscripten' - template: build-linux-wasm-step.yml