diff --git a/cmake/platforms/OpenCV-Emscripten.cmake b/cmake/platforms/OpenCV-Emscripten.cmake new file mode 100644 index 0000000000000000000000000000000000000000..ec15fba799f464fbe6a20a86b048d1353769b8ca --- /dev/null +++ b/cmake/platforms/OpenCV-Emscripten.cmake @@ -0,0 +1 @@ +set(OPENCV_SKIP_LINK_AS_NEEDED 1) diff --git a/modules/js/CMakeLists.txt b/modules/js/CMakeLists.txt index f3a625b37e65c4fe309e0c6d01f1ce3c8605c32f..d82e4a26f6b14058ef5b4eed1b87fbf5619f3a06 100644 --- a/modules/js/CMakeLists.txt +++ b/modules/js/CMakeLists.txt @@ -1,13 +1,19 @@ # ---------------------------------------------------------------------------- # CMake file for js support # ---------------------------------------------------------------------------- -set(the_description "The js bindings") +if(OPENCV_INITIAL_PASS) + # generator for Objective-C source code and documentation signatures + add_subdirectory(generator) +endif() if(NOT BUILD_opencv_js) # should be enabled explicitly (by build_js.py script) - ocv_module_disable(js) + return() endif() +set(the_description "The JavaScript(JS) bindings") + set(OPENCV_JS "opencv.js") +set(JS_HELPER "${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.js") find_path(EMSCRIPTEN_INCLUDE_DIR emscripten/bind.h @@ -28,59 +34,18 @@ if(NOT EMSCRIPTEN_INCLUDE_DIR OR NOT PYTHON_DEFAULT_AVAILABLE) ocv_module_disable(js) endif() -ocv_add_module(js BINDINGS) +ocv_add_module(js BINDINGS PRIVATE_REQUIRED opencv_js_bindings_generator) ocv_module_include_directories(${EMSCRIPTEN_INCLUDE_DIR}) -# get list of modules to wrap -# message(STATUS "Wrapped in js:") -set(OPENCV_JS_MODULES) -foreach(m ${OPENCV_MODULES_BUILD}) - if(";${OPENCV_MODULE_${m}_WRAPPERS};" MATCHES ";js;" AND HAVE_${m}) - list(APPEND OPENCV_JS_MODULES ${m}) - # message(STATUS "\t${m}") - endif() -endforeach() - -set(opencv_hdrs "") -foreach(m ${OPENCV_JS_MODULES}) - list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS}) -endforeach(m) - -# header blacklist -ocv_list_filterout(opencv_hdrs "modules/.*.h$") -ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda") -ocv_list_filterout(opencv_hdrs "modules/core/.*/opencl") -ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/opengl.hpp") -ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/ocl.hpp") -ocv_list_filterout(opencv_hdrs "modules/cuda.*") -ocv_list_filterout(opencv_hdrs "modules/cudev") -ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/") -ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker.hpp") # Conditional compilation -ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/.*") - -file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}") - -set(bindings_cpp "${CMAKE_CURRENT_BINARY_DIR}/bindings.cpp") - -set(scripts_hdr_parser "${CMAKE_CURRENT_SOURCE_DIR}/../python/src2/hdr_parser.py") - -set(JS_HELPER "${CMAKE_CURRENT_SOURCE_DIR}/src/helpers.js") - -add_custom_command( - OUTPUT ${bindings_cpp} - COMMAND ${PYTHON_DEFAULT_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/src/embindgen.py" ${scripts_hdr_parser} ${bindings_cpp} "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${CMAKE_CURRENT_SOURCE_DIR}/src/core_bindings.cpp" - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/core_bindings.cpp - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/embindgen.py - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/templates.py - DEPENDS ${scripts_hdr_parser} - #(not needed - generated by CMake) DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/headers.txt - DEPENDS ${opencv_hdrs} - DEPENDS ${JS_HELPER}) - add_definitions("-std=c++11") -link_libraries(${OPENCV_MODULE_${the_module}_DEPS}) +set(deps ${OPENCV_MODULE_${the_module}_DEPS}) +list(REMOVE_ITEM deps opencv_js_bindings_generator) # don't add dummy module +link_libraries(${deps}) + +set(bindings_cpp "${OPENCV_JS_BINDINGS_DIR}/gen/bindings.cpp") +set_source_files_properties(${bindings_cpp} PROPERTIES GENERATED TRUE) OCV_OPTION(BUILD_WASM_INTRIN_TESTS "Build WASM intrin tests" OFF ) if(BUILD_WASM_INTRIN_TESTS) @@ -94,12 +59,17 @@ else() ocv_add_executable(${the_module} ${bindings_cpp}) endif() +add_dependencies(${the_module} gen_opencv_js_source) + set_target_properties(${the_module} PROPERTIES COMPILE_FLAGS "-Wno-missing-prototypes") +#set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s NODERAWFS=0") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} --memory-init-file 0 -s TOTAL_MEMORY=128MB -s WASM_MEM_MAX=1GB -s ALLOW_MEMORY_GROWTH=1") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s MODULARIZE=1 -s SINGLE_FILE=1") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s EXPORT_NAME=\"'cv'\" -s DEMANGLE_SUPPORT=1") set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s FORCE_FILESYSTEM=1 --use-preload-plugins --bind --post-js ${JS_HELPER} -Wno-missing-prototypes") +#set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} --use-preload-plugins --bind --post-js ${JS_HELPER} -Wno-missing-prototypes") +#set(EMSCRIPTEN_LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS} -s FORCE_FILESYSTEM=1 --bind --post-js ${JS_HELPER} -Wno-missing-prototypes") set_target_properties(${the_module} PROPERTIES LINK_FLAGS "${EMSCRIPTEN_LINK_FLAGS}") # add UMD wrapper @@ -150,7 +120,7 @@ add_custom_command(OUTPUT "${opencv_test_js_bin_dir}/${test_data}" ) list(APPEND opencv_test_js_file_deps "${test_data_path}" "${opencv_test_js_bin_dir}/${test_data}") -add_custom_target(${PROJECT_NAME}_test ALL +add_custom_target(${PROJECT_NAME}_test DEPENDS ${OCV_JS_PATH} ${opencv_test_js_file_deps}) # perf @@ -173,7 +143,7 @@ foreach(f ${perf_files}) list(APPEND opencv_perf_js_file_deps "${perf_dir}/${f}" "${opencv_perf_js_bin_dir}/${f}") endforeach() -add_custom_target(${PROJECT_NAME}_perf ALL +add_custom_target(${PROJECT_NAME}_perf DEPENDS ${OCV_JS_PATH} ${opencv_perf_js_file_deps}) #loader @@ -193,4 +163,6 @@ add_custom_command( list(APPEND opencv_loader_js_file_deps "${loader_dir}/loader.js" "${opencv_loader_js_bin_dir}/loader.js") add_custom_target(${PROJECT_NAME}_loader ALL - DEPENDS ${OCV_JS_PATH} ${opencv_loader_js_file_deps}) \ No newline at end of file + DEPENDS ${OCV_JS_PATH} ${opencv_loader_js_file_deps}) + +add_custom_target(opencv_test_js ALL DEPENDS opencv_js_test opencv_js_perf opencv_js_loader) diff --git a/modules/js/common.cmake b/modules/js/common.cmake new file mode 100644 index 0000000000000000000000000000000000000000..192bcca4ea7063a27bba913d51885ce5affbf507 --- /dev/null +++ b/modules/js/common.cmake @@ -0,0 +1,13 @@ +# get list of modules to wrap +if(HAVE_opencv_js) + message(STATUS "Wrapped in JavaScript(js):") +endif() +set(OPENCV_JS_MODULES "") +foreach(m ${OPENCV_MODULES_BUILD}) + if(";${OPENCV_MODULE_${m}_WRAPPERS};" MATCHES ";js;" AND HAVE_${m}) + list(APPEND OPENCV_JS_MODULES ${m}) + if(HAVE_opencv_js) + message(STATUS " ${m}") + endif() + endif() +endforeach() diff --git a/modules/js/generator/CMakeLists.txt b/modules/js/generator/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..75c8a03545210428392a35d775d09eb3d32092f7 --- /dev/null +++ b/modules/js/generator/CMakeLists.txt @@ -0,0 +1,74 @@ +set(MODULE_NAME "js_bindings_generator") +set(OPENCV_MODULE_IS_PART_OF_WORLD FALSE) +ocv_add_module(${MODULE_NAME} INTERNAL) + +set(OPENCV_JS_BINDINGS_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE INTERNAL "") +file(REMOVE_RECURSE "${OPENCV_JS_BINDINGS_DIR}/gen") +file(MAKE_DIRECTORY "${OPENCV_JS_BINDINGS_DIR}/gen") +file(REMOVE "${OPENCV_DEPHELPER}/gen_opencv_js_source") # force re-run after CMake + +# This file is included from a subdirectory +set(JS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") +include(${JS_SOURCE_DIR}/common.cmake) # fill OPENCV_JS_MODULES + +set(opencv_hdrs "") +foreach(m ${OPENCV_JS_MODULES}) + list(APPEND opencv_hdrs ${OPENCV_MODULE_${m}_HEADERS}) +endforeach(m) + +# header blacklist +ocv_list_filterout(opencv_hdrs "modules/.*.h$") +ocv_list_filterout(opencv_hdrs "modules/core/.*/cuda") +ocv_list_filterout(opencv_hdrs "modules/core/.*/opencl") +ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/opengl.hpp") +ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/ocl.hpp") +ocv_list_filterout(opencv_hdrs "modules/cuda.*") +ocv_list_filterout(opencv_hdrs "modules/cudev") +ocv_list_filterout(opencv_hdrs "modules/core/.*/hal/") +ocv_list_filterout(opencv_hdrs "modules/.*/detection_based_tracker.hpp") # Conditional compilation +ocv_list_filterout(opencv_hdrs "modules/core/include/opencv2/core/utils/.*") + +ocv_update_file("${CMAKE_CURRENT_BINARY_DIR}/headers.txt" "${opencv_hdrs}") + +set(bindings_cpp "${OPENCV_JS_BINDINGS_DIR}/gen/bindings.cpp") + +set(scripts_hdr_parser "${JS_SOURCE_DIR}/../python/src2/hdr_parser.py") + +if(DEFINED ENV{OPENCV_JS_WHITELIST}) + set(OPENCV_JS_WHITELIST_FILE "$ENV{OPENCV_JS_WHITELIST}") +else() + set(OPENCV_JS_WHITELIST_FILE "${OpenCV_SOURCE_DIR}/platforms/js/opencv_js.config.py") +endif() + +add_custom_command( + OUTPUT ${bindings_cpp} "${OPENCV_DEPHELPER}/gen_opencv_js_source" + COMMAND + ${PYTHON_DEFAULT_EXECUTABLE} + "${CMAKE_CURRENT_SOURCE_DIR}/embindgen.py" + "${scripts_hdr_parser}" + "${bindings_cpp}" + "${CMAKE_CURRENT_BINARY_DIR}/headers.txt" + "${JS_SOURCE_DIR}/src/core_bindings.cpp" + "${OPENCV_JS_WHITELIST_FILE}" + COMMAND + ${CMAKE_COMMAND} -E touch "${OPENCV_DEPHELPER}/gen_opencv_js_source" + WORKING_DIRECTORY + "${CMAKE_CURRENT_BINARY_DIR}/gen" + DEPENDS + ${JS_SOURCE_DIR}/src/core_bindings.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/embindgen.py + ${CMAKE_CURRENT_SOURCE_DIR}/templates.py + ${scripts_hdr_parser} + #(not needed - generated by CMake) ${CMAKE_CURRENT_BINARY_DIR}/headers.txt + ${opencv_hdrs} + COMMENT "Generate source files for JavaScript bindings" +) + +add_custom_target(gen_opencv_js_source + # excluded from all: ALL + DEPENDS ${bindings_cpp} "${OPENCV_DEPHELPER}/gen_opencv_js_source" + SOURCES + ${JS_SOURCE_DIR}/src/core_bindings.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/embindgen.py + ${CMAKE_CURRENT_SOURCE_DIR}/templates.py +) diff --git a/modules/js/src/embindgen.py b/modules/js/generator/embindgen.py similarity index 99% rename from modules/js/src/embindgen.py rename to modules/js/generator/embindgen.py index 0ec44889463aba4c8fe1dd2717bf1e8d874d4122..6e2bac71a1c25d26dff9b1ef91342bafd4a2f19e 100644 --- a/modules/js/src/embindgen.py +++ b/modules/js/generator/embindgen.py @@ -104,8 +104,6 @@ def makeWhiteList(module_list): return wl white_list = None -exec(open(os.environ["OPENCV_JS_WHITELIST"]).read()) -assert(white_list) # Features to be exported export_enums = False @@ -891,10 +889,10 @@ class JSWrapperGenerator(object): if __name__ == "__main__": - if len(sys.argv) < 4: + if len(sys.argv) < 5: print("Usage:\n", \ os.path.basename(sys.argv[0]), \ - " ") + " ") print("Current args are: ", ", ".join(["'"+a+"'" for a in sys.argv])) exit(0) @@ -908,5 +906,9 @@ if __name__ == "__main__": bindingsCpp = sys.argv[2] headers = open(sys.argv[3], 'r').read().split(';') coreBindings = sys.argv[4] + whiteListFile = sys.argv[5] + exec(open(whiteListFile).read()) + assert(white_list) + generator = JSWrapperGenerator() generator.gen(bindingsCpp, headers, coreBindings) diff --git a/modules/js/src/templates.py b/modules/js/generator/templates.py similarity index 100% rename from modules/js/src/templates.py rename to modules/js/generator/templates.py diff --git a/modules/js/src/core_bindings.cpp b/modules/js/src/core_bindings.cpp index ceeb641c7c06f24a0d833f3099f126b6bd1bec74..a43fb726de575ebf6412441be782aed61804e1b4 100644 --- a/modules/js/src/core_bindings.cpp +++ b/modules/js/src/core_bindings.cpp @@ -87,7 +87,7 @@ namespace hal { using namespace emscripten; using namespace cv; #ifdef HAVE_OPENCV_DNN -using namespace dnn; +using namespace cv::dnn; #endif namespace binding_utils diff --git a/platforms/js/build_js.py b/platforms/js/build_js.py index 38e988a3bd31a619c8dd61fb4b7c4754d0a1b4c1..cd22db0f02e76e145fd58b67baa429ae75de8324 100644 --- a/platforms/js/build_js.py +++ b/platforms/js/build_js.py @@ -129,11 +129,9 @@ class Builder: "-DBUILD_opencv_superres=OFF", "-DBUILD_opencv_stitching=OFF", "-DBUILD_opencv_java=OFF", - "-DBUILD_opencv_java_bindings_generator=OFF", "-DBUILD_opencv_js=ON", "-DBUILD_opencv_python2=OFF", "-DBUILD_opencv_python3=OFF", - "-DBUILD_opencv_python_bindings_generator=OFF", "-DBUILD_EXAMPLES=OFF", "-DBUILD_PACKAGE=OFF", "-DBUILD_TESTS=OFF",