load("@skia_user_config//:copts.bzl", "DEFAULT_COPTS") load("//bazel:macros.bzl", "bool_flag", "exports_files_legacy", "skia_filegroup", "wasm_cc_binary") load("//bazel/karma:karma_test.bzl", "karma_test") package( default_applicable_licenses = ["//:license"], ) licenses(["notice"]) exports_files_legacy( label_list = ["npm_build/types/index.d.ts"], visibility = ["//infra:__subpackages__"], ) BASE_LINKOPTS = [ #"-flto", # https://github.com/emscripten-core/emsdk/issues/807 "--bind", # Compiles the source code using the Embind bindings to connect C/C++ and JavaScript "-fno-rtti", "--no-entry", "-sALLOW_MEMORY_GROWTH", "-sUSE_PTHREADS=0", # Disable pthreads "-sMODULARIZE", "-sDISABLE_EXCEPTION_CATCHING", # Disable all exception catching "-sNODEJS_CATCH_EXIT=0", # We don't have a 'main' so disable exit() catching "-sWASM", "-sMAX_WEBGL_VERSION=2", "-sUSE_WEBGL2=1", "-sFORCE_FILESYSTEM=0", "-sDYNAMIC_EXECUTION=0", "-sFILESYSTEM=0", "-sEXPORTED_FUNCTIONS=['_malloc','_free']", ] RELEASE_OPTS = [ "-sASSERTIONS=0", # Turn off assertions "-Oz", ] DEBUG_OPTS = [ "--closure 0", # Do not use closure "-sASSERTIONS", # Turn on assertions "-sGL_ASSERTIONS", "-O0", "-g3", ] skia_filegroup( name = "hdrs", srcs = [ "WasmCommon.h", ], ) # See https://stackoverflow.com/a/57499321 for reference. genrule( name = "create_notomono_cpp", srcs = ["fonts/NotoMono-Regular.ttf"], outs = ["fonts/NotoMono-Regular.ttf.bazel.cpp"], # Distinct name from compile.sh's version cmd = "$(location //tools:embed_resources) --name=SK_EMBEDDED_FONTS " + "--input=modules/canvaskit/fonts/NotoMono-Regular.ttf " + # The $@ means substitute in the one and only output location, which will be located # in //bazel-out, not in the fonts subdirectory (although it will be available to clients # in the fonts/ subdirectory as if it had been there all along. "--output=$@ " + "--align=4", tools = ["//tools:embed_resources"], ) # Note: These are defines that only impact the _bindings.cpp files in this folder. # Any defines that need to effect the entire Skia build should go in //bazel/BUILD.bazel CK_DEFINES = [ "CK_INCLUDE_PATHOPS", "EMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0", # Allows us to compile with -fno-rtti "SK_DISABLE_LEGACY_PARAGRAPH_UNICODE=1", ] + select({ ":enable_fonts_true": ["CK_INCLUDE_PARAGRAPH"], ":enable_fonts_false": ["CK_NO_FONTS"], }) + select({ ":include_embedded_font_true": ["CK_EMBED_FONT"], ":include_embedded_font_false": [], }) + select({ ":enable_skp_serialization_true": ["CK_SERIALIZE_SKP=1"], ":enable_skp_serialization_false": [], }) + select({ ":enable_runtime_effect_true": ["CK_INCLUDE_RUNTIME_EFFECT=1"], ":enable_runtime_effect_false": [], }) + select({ ":enable_webgl_true": ["CK_ENABLE_WEBGL"], "//conditions:default": [], }) CK_RELEASE_OPTS = [ "--closure 1", # Run the closure compiler # pass the externs file in "--closure-args=--externs=$(location externs.js)", ] CK_LINKOPTS = BASE_LINKOPTS + [ "-sEXPORT_NAME=CanvasKitInit", "-sINITIAL_MEMORY=128MB", # The order of these --pre-js flags matters! The preamble is a partially open scope and the # postamble closes it. TODO(kjlubick) do we need to do it this way anymore? "--pre-js", "modules/canvaskit/preamble.js", "--pre-js", "modules/canvaskit/color.js", "--pre-js", "modules/canvaskit/memory.js", "--pre-js", "modules/canvaskit/util.js", "--pre-js", "modules/canvaskit/interface.js", "--pre-js", "modules/canvaskit/pathops.js", ] + select({ ":enable_webgl_true": [ "--pre-js", "modules/canvaskit/cpu.js", "--pre-js", "modules/canvaskit/webgl.js", ], "//conditions:default": [ "--pre-js", "modules/canvaskit/cpu.js", ], }) + select({ ":enable_fonts_true": [ "--pre-js", "modules/canvaskit/font.js", "--pre-js", "modules/canvaskit/paragraph.js", ], ":enable_fonts_false": [], }) + select({ ":enable_canvas_polyfill_true": [ "--pre-js", "modules/canvaskit/htmlcanvas/preamble.js", "--pre-js", "modules/canvaskit/htmlcanvas/util.js", "--pre-js", "modules/canvaskit/htmlcanvas/color.js", "--pre-js", "modules/canvaskit/htmlcanvas/font.js", "--pre-js", "modules/canvaskit/htmlcanvas/canvas2dcontext.js", "--pre-js", "modules/canvaskit/htmlcanvas/htmlcanvas.js", "--pre-js", "modules/canvaskit/htmlcanvas/htmlimage.js", "--pre-js", "modules/canvaskit/htmlcanvas/imagedata.js", "--pre-js", "modules/canvaskit/htmlcanvas/lineargradient.js", "--pre-js", "modules/canvaskit/htmlcanvas/path2d.js", "--pre-js", "modules/canvaskit/htmlcanvas/pattern.js", "--pre-js", "modules/canvaskit/htmlcanvas/radialgradient.js", "--pre-js", "modules/canvaskit/htmlcanvas/postamble.js", ], ":enable_canvas_polyfill_false": [], }) + select({ ":enable_skottie_true": [ "--pre-js", "modules/canvaskit/skottie.js", ], ":enable_skottie_false": [], }) + select({ ":enable_skp_serialization_true": [ "--pre-js", "modules/canvaskit/skp.js", ], ":enable_skp_serialization_false": [], }) + select({ ":enable_runtime_effect_true": [ "--pre-js", "modules/canvaskit/rt_shader.js", ], ":enable_runtime_effect_false": [], }) + select({ "//bazel/common_config_settings:build_for_debugger_true": [ "--pre-js", "modules/canvaskit/debugger.js", ], "//bazel/common_config_settings:build_for_debugger_false": [], }) + select({ ":include_matrix_js_true": [ "--pre-js", "modules/canvaskit/matrix.js", ], ":include_matrix_js_false": [], }) + [ # This must come last "--pre-js", "modules/canvaskit/postamble.js", ] + select({ "//bazel/common_config_settings:debug_build": DEBUG_OPTS + [ "--pre-js", "modules/canvaskit/debug.js", ], "//conditions:default": RELEASE_OPTS + CK_RELEASE_OPTS + [ "--pre-js", "modules/canvaskit/release.js", ], }) # All JS files that could possibly be included via --pre-js or --post-js. # Whether they actually will be or not will be controlled above in the construction of CK_LINKOPTS. JS_INTERFACE_FILES = [ "color.js", "cpu.js", "debug.js", "font.js", "interface.js", "matrix.js", "memory.js", "paragraph.js", "pathops.js", "postamble.js", "preamble.js", "release.js", "rt_shader.js", "skottie.js", "skp.js", "util.js", "webgl.js", "webgpu.js", ] + [ "htmlcanvas/canvas2dcontext.js", "htmlcanvas/color.js", "htmlcanvas/font.js", "htmlcanvas/htmlcanvas.js", "htmlcanvas/htmlimage.js", "htmlcanvas/imagedata.js", "htmlcanvas/lineargradient.js", "htmlcanvas/path2d.js", "htmlcanvas/pattern.js", "htmlcanvas/postamble.js", "htmlcanvas/preamble.js", "htmlcanvas/radialgradient.js", "htmlcanvas/util.js", ] + select({ "//bazel/common_config_settings:build_for_debugger_true": ["debugger.js"], "//bazel/common_config_settings:build_for_debugger_false": [], }) CK_SRCS = [ "canvaskit_bindings.cpp", ":hdrs", ] + select({ ":include_embedded_font_true": ["fonts/NotoMono-Regular.ttf.bazel.cpp"], ":include_embedded_font_false": [], }) + select({ ":enable_fonts_true": [ "paragraph_bindings.cpp", "paragraph_bindings_gen.cpp", ], ":enable_fonts_false": [], }) + select({ ":enable_skottie_true": ["skottie_bindings.cpp"], ":enable_skottie_false": [], }) + select({ "//bazel/common_config_settings:build_for_debugger_true": ["debugger_bindings.cpp"], "//bazel/common_config_settings:build_for_debugger_false": [], }) CK_COPTS = [ "-Wno-header-hygiene", ] cc_binary( name = "canvaskit.build", srcs = CK_SRCS, additional_linker_inputs = JS_INTERFACE_FILES + ["externs.js"], copts = DEFAULT_COPTS + CK_COPTS, linkopts = CK_LINKOPTS, local_defines = CK_DEFINES, # This target won't build successfully on its own because of missing emscripten # headers etc. Therefore, we hide it from wildcards. tags = ["manual"], deps = [ "//:bmp_decode_codec", "//:core", "//:gif_decode_codec", "//:ico_decode_codec", "//:jpeg_decode_codec", "//:jpeg_encode_codec", "//:png_decode_codec", "//:png_encode_codec", "//:wbmp_decode_codec", "//:webp_decode_codec", "//:webp_encode_codec", "//src/android:animated_image", ] + select({ ":enable_fonts_true": [ "//:fontmgr_data_freetype", "//:fontmgr_empty_freetype", "//modules/skparagraph:skparagraph_harfbuzz_icu", ], ":enable_fonts_false": [], }) + select({ ":enable_skottie_true": [ "//:skshaper_harfbuzz", "//:skshaper_unicode", "//:skunicode_icu", "//modules/skottie", "//modules/skottie/utils:skottie_utils", "//modules/skottie/utils:text_editor", ], ":enable_skottie_false": [], }) + select({ "//bazel/common_config_settings:build_for_debugger_true": [ "//tools/debugger", ], "//bazel/common_config_settings:build_for_debugger_false": [], }) + select({ ":enable_webgl_true": [ "//:ganesh_gl", "//:ganesh_webgl_factory", ], "//conditions:default": [], }), ) wasm_cc_binary( name = "canvaskit", # Whatever is before the dot will be the name of the output js and wasm, aka "the stem". # https://github.com/emscripten-core/emsdk/blob/82ad00499a42abde16b363239d2bc83bf5d863ab/bazel/emscripten_toolchain/wasm_cc_binary.bzl#L91 cc_target = ":canvaskit.build", visibility = [ "//infra/debugger-app:__pkg__", "//infra/jsfiddle:__pkg__", "//infra/shaders:__pkg__", "//infra/skottie:__pkg__", ], ) bool_flag( name = "enable_canvas_polyfill", default = False, ) bool_flag( name = "enable_fonts", default = False, ) bool_flag( name = "include_embedded_font", default = False, ) bool_flag( name = "include_matrix_js", default = False, ) bool_flag( name = "enable_skottie", default = False, ) bool_flag( name = "enable_skp_serialization", default = False, ) bool_flag( name = "enable_runtime_effect", default = False, ) bool_flag( name = "enable_webgl", default = False, ) karma_test( name = "canvaskit_js_tests", srcs = [ ":canvaskit/canvaskit.js", # We want to make sure the CanvasKit JS is loaded before the loader script, so # CanvasKitInit is defined. This loader script makes a promise... "tests/init_with_gold_server.js", "tests/util.js", "tests/bazel_test_reporter.js", # ...which is used by all of the tests "tests/canvas_test.js", "tests/canvas2d_test.js", "tests/core_test.js", "tests/font_test.js", "tests/matrix_test.js", "tests/paragraph_test.js", "tests/path_test.js", "tests/rtshader_test.js", "tests/skottie_test.js", ], config_file = "karma.bazel.js", # The tests need the Gold server to be up and running so they can make POST requests to # exfiltrate the PNGs they create. env = "//modules/canvaskit/go/gold_test_env:gold_test_env", static_files = [ ":canvaskit/canvaskit.wasm", "//modules/canvaskit/tests/assets:test_assets", ], ) genrule( name = "make version file", srcs = ["make_version.sh"], outs = ["version.js"], cmd = "$< $@", # This script uses the Git executable, which is not on the remote builders. # Forcing the execution to be local ensures it will be in the path. local = True, visibility = ["//infra:__subpackages__"], )