Skip to content

Commit

Permalink
Merge pull request opencv#18965 from alalek:cmake_gen_js_code
Browse files Browse the repository at this point in the history
  • Loading branch information
alalek committed Dec 3, 2020
2 parents 84a3654 + 7e5c4fe commit e371592
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 60 deletions.
1 change: 1 addition & 0 deletions cmake/platforms/OpenCV-Emscripten.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
set(OPENCV_SKIP_LINK_AS_NEEDED 1)
78 changes: 25 additions & 53 deletions modules/js/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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})
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)
13 changes: 13 additions & 0 deletions modules/js/common.cmake
Original file line number Diff line number Diff line change
@@ -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()
74 changes: 74 additions & 0 deletions modules/js/generator/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -891,10 +889,10 @@ def gen(self, dst_file, src_files, core_bindings):


if __name__ == "__main__":
if len(sys.argv) < 4:
if len(sys.argv) < 5:
print("Usage:\n", \
os.path.basename(sys.argv[0]), \
"<full path to hdr_parser.py> <bindings.cpp> <headers.txt> <core_bindings.cpp>")
"<full path to hdr_parser.py> <bindings.cpp> <headers.txt> <core_bindings.cpp> <opencv_js.config.py>")
print("Current args are: ", ", ".join(["'"+a+"'" for a in sys.argv]))
exit(0)

Expand All @@ -908,5 +906,9 @@ def gen(self, dst_file, src_files, core_bindings):
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)
File renamed without changes.
2 changes: 1 addition & 1 deletion modules/js/src/core_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 0 additions & 2 deletions platforms/js/build_js.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,9 @@ def get_cmake_cmd(self):
"-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",
Expand Down

0 comments on commit e371592

Please sign in to comment.