diff --git a/CMakeLists.txt b/CMakeLists.txt index da8d5d76..bacd6e7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,7 @@ function(configure_native_kernel kernel) endfunction() function(configure_wasm_kernel kernel) + set(XEUS_CPP_RESOURCE_DIR "/lib/clang/${CPPINTEROP_LLVM_VERSION_MAJOR}" PARENT_SCOPE) configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}${kernel}wasm_kernel.json.in" @@ -169,17 +170,9 @@ endfunction() message("Configure kernels: ...") if(EMSCRIPTEN) - # TODO: Currently jupyterlite-xeus and xeus-lite do not provide - # methods to fetch information from the arguments present in the - # generated emscripten kernel. - # The following needs to be done here : - # 1) We need to configure the kernel properly - # Check issue https://github.com/compiler-research/xeus-cpp/issues/185. - # 2) Once the above is done we need to add support in jupyterlite-xeus & xeus-lite - # to be able to deal with arguments present in kernel.json - # 3) Finally we should fetch the C++ version from the kernel.json file and - # be able to pass it to our wasm interpreter rather than forcing a version. + configure_wasm_kernel("/share/jupyter/kernels/xcpp17/") configure_wasm_kernel("/share/jupyter/kernels/xcpp20/") + configure_wasm_kernel("/share/jupyter/kernels/xcpp23/") else() configure_native_kernel("/share/jupyter/kernels/xcpp17/") configure_native_kernel("/share/jupyter/kernels/xcpp20/") @@ -444,20 +437,13 @@ if(EMSCRIPTEN) xeus_wasm_link_options(xcpp "web,worker") target_link_options(xcpp PUBLIC "SHELL: --preload-file ${SYSROOT_PATH}/include@/include" + #PUBLIC "SHELL: --preload-file ${CMAKE_INSTALL_PREFIX}${XEUS_CPP_RESOURCE_DIR}@${XEUS_CPP_RESOURCE_DIR}" PUBLIC "SHELL: --preload-file ${XEUS_CPP_DATA_DIR}@/share/xeus-cpp" PUBLIC "SHELL: --preload-file ${XEUS_CPP_CONF_DIR}@/etc/xeus-cpp" PUBLIC "SHELL: --post-js ${CMAKE_CURRENT_SOURCE_DIR}/wasm_patches/post.js" ) - # TODO: Emscripten supports preloading files just once before it generates - # the xcpp.data file (containing the binary representation of the file(s) we - # want to include in our application). - # Hence although we are adding support for Standard Headers, Libraries etc - # through emscripten's sysroot for now, we need to do the following: - # 1) Enable CppInterOp to provide us with a resource dir. - # 2) If the above cannot be done, we can use the resource dir provided - # by llvm on emscripten-forge but would involve adding a dependency. - # 3) Shift the resource dir and the sysroot to a common location. - # 4) Preload everything required together. + # TODO: Uncomment the above line regarding preloading clang's resource dir + # once has been supported through cppinterop. endif() # Tests # ===== diff --git a/include/xeus-cpp/xinterpreter_wasm.hpp b/include/xeus-cpp/xinterpreter_wasm.hpp index abb7614e..8b1d54c5 100644 --- a/include/xeus-cpp/xinterpreter_wasm.hpp +++ b/include/xeus-cpp/xinterpreter_wasm.hpp @@ -19,7 +19,7 @@ namespace xcpp { public: - wasm_interpreter(); + wasm_interpreter(int argc = 0, char** argv = nullptr); virtual ~wasm_interpreter() = default; }; diff --git a/share/jupyter/kernels/xcpp17/wasm_kernel.json.in b/share/jupyter/kernels/xcpp17/wasm_kernel.json.in new file mode 100644 index 00000000..a6be99dd --- /dev/null +++ b/share/jupyter/kernels/xcpp17/wasm_kernel.json.in @@ -0,0 +1,15 @@ +{ + "display_name": "C++17", + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@", + "-std=c++17" + ], + "language": "cpp", + "metadata": { + "debugger": false, + "shared": { + "libclangCppInterOp.so": "lib/libclangCppInterOp.so" + } + } +} diff --git a/share/jupyter/kernels/xcpp20/wasm_kernel.json.in b/share/jupyter/kernels/xcpp20/wasm_kernel.json.in index 697e46a9..ea792b9f 100644 --- a/share/jupyter/kernels/xcpp20/wasm_kernel.json.in +++ b/share/jupyter/kernels/xcpp20/wasm_kernel.json.in @@ -2,8 +2,7 @@ "display_name": "C++20", "argv": [ "@XEUS_CPP_KERNELSPEC_PATH@xcpp", - "-f", - "{connection_file}", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@", "-std=c++20" ], "language": "cpp", diff --git a/share/jupyter/kernels/xcpp23/wasm_kernel.json.in b/share/jupyter/kernels/xcpp23/wasm_kernel.json.in new file mode 100644 index 00000000..93ffa621 --- /dev/null +++ b/share/jupyter/kernels/xcpp23/wasm_kernel.json.in @@ -0,0 +1,15 @@ +{ + "display_name": "C++23", + "argv": [ + "@XEUS_CPP_KERNELSPEC_PATH@xcpp", + "-resource-dir", "@XEUS_CPP_RESOURCE_DIR@", + "-std=c++23" + ], + "language": "cpp", + "metadata": { + "debugger": false, + "shared": { + "libclangCppInterOp.so": "lib/libclangCppInterOp.so" + } + } +} diff --git a/src/main_emscripten_kernel.cpp b/src/main_emscripten_kernel.cpp index e25f8960..555b596a 100644 --- a/src/main_emscripten_kernel.cpp +++ b/src/main_emscripten_kernel.cpp @@ -15,9 +15,30 @@ #include "xeus-cpp/xinterpreter_wasm.hpp" +template +static interpreter_type* builder_with_args(emscripten::val js_args) +{ + // TODO: Refactor interpreter constructor to avoid static args-to-argv conversion. + static std::vector args = emscripten::vecFromJSArray(js_args); + static std::vector argv_vec; + + for (const auto& s : args) + { + argv_vec.push_back(s.c_str()); + } + + int argc = static_cast(argv_vec.size()); + char** argv = const_cast(argv_vec.data()); + + auto* res = new interpreter_type(argc, argv); + argv_vec.clear(); + args.clear(); + return res; +} + EMSCRIPTEN_BINDINGS(my_module) { xeus::export_core(); using interpreter_type = xcpp::wasm_interpreter; - xeus::export_kernel("xkernel"); + xeus::export_kernel>("xkernel"); } diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 85aa07b1..14972324 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -18,6 +18,7 @@ #include "xinput.hpp" #include "xinspect.hpp" #include "xmagics/os.hpp" +#include #ifndef EMSCRIPTEN #include "xmagics/xassist.hpp" #endif @@ -27,17 +28,16 @@ using Args = std::vector; void* createInterpreter(const Args &ExtraArgs = {}) { - Args ClangArgs = {/*"-xc++"*/"-v"}; // ? {"-Xclang", "-emit-llvm-only", "-Xclang", "-diagnostic-log-file", "-Xclang", "-", "-xc++"}; -#ifdef EMSCRIPTEN - ClangArgs.push_back("-std=c++20"); -#else + Args ClangArgs = {/*"-xc++"*/"-v"}; if (std::find_if(ExtraArgs.begin(), ExtraArgs.end(), [](const std::string& s) { return s == "-resource-dir";}) == ExtraArgs.end()) { std::string resource_dir = Cpp::DetectResourceDir(); - if (resource_dir.empty()) - std::cerr << "Failed to detect the resource-dir\n"; - ClangArgs.push_back("-resource-dir"); - ClangArgs.push_back(resource_dir.c_str()); + if (!resource_dir.empty()) { + ClangArgs.push_back("-resource-dir"); + ClangArgs.push_back(resource_dir.c_str()); + } else { + std::cerr << "Failed to detect the resource-dir\n"; + } } std::vector CxxSystemIncludes; Cpp::DetectSystemCompilerIncludePaths(CxxSystemIncludes); @@ -45,7 +45,6 @@ void* createInterpreter(const Args &ExtraArgs = {}) { ClangArgs.push_back("-isystem"); ClangArgs.push_back(CxxInclude.c_str()); } -#endif ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end()); // FIXME: We should process the kernel input options and conditionally pass // the gpu args here. diff --git a/src/xinterpreter_wasm.cpp b/src/xinterpreter_wasm.cpp index 7746c7b6..9e65bdb9 100644 --- a/src/xinterpreter_wasm.cpp +++ b/src/xinterpreter_wasm.cpp @@ -15,9 +15,8 @@ namespace xcpp { - - wasm_interpreter::wasm_interpreter() - : interpreter(0, nullptr) + wasm_interpreter::wasm_interpreter(int argc, char** argv) + : interpreter(argc, argv) { } }