mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-10-27 19:25:29 +00:00
Merge pull request #474 from ben-polinsky/csp-no-dynamic-execution
Add opt-in WebGL builds that work under a strict CSP (no `unsafe-eval`)
This commit is contained in:
+2
-1
@@ -11,6 +11,7 @@
|
||||
# ./build.sh --clean # make clean + wipe CMake cache first (full rebuild)
|
||||
# ./build.sh --slow # serial build (plain make, one file at a time)
|
||||
# ./build.sh encoder -DKTX2_ZSTANDARD=OFF -DCMAKE_BUILD_TYPE=Debug
|
||||
# ./build.sh -DNO_DYNAMIC_EXECUTION=ON # no eval/new Function (strict CSP)
|
||||
#
|
||||
# Any -D... argument is forwarded to cmake. Runnable from any directory.
|
||||
#
|
||||
@@ -35,7 +36,7 @@ for a in "$@"; do
|
||||
--slow) SLOW=1 ;;
|
||||
transcoder|encoder) TARGETS+=("$a") ;;
|
||||
-D*) CMAKE_ARGS+=("$a") ;;
|
||||
-h|--help) sed -n '3,15p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
-h|--help) sed -n '3,16p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
||||
*) die "unknown argument: '$a' (try --help)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -5,8 +5,18 @@ project(basisu_encoder_js)
|
||||
option(KTX2_ZSTANDARD "Enable KTX2 Zstandard support" TRUE)
|
||||
option(SUPPORT_ASTCENC "Enable astcenc support" FALSE)
|
||||
|
||||
# Build JavaScript glue that never calls eval() or new Function(), so the module
|
||||
# loads under a Content-Security-Policy without 'unsafe-eval' (OFF by default).
|
||||
option(NO_DYNAMIC_EXECUTION "Disallow eval()/new Function() in the JS glue" FALSE)
|
||||
|
||||
# With NO_DYNAMIC_EXECUTION, generate the embind call wrappers at build time (fast)
|
||||
# instead of using the slower generic wrappers. No effect unless NO_DYNAMIC_EXECUTION is ON.
|
||||
option(EMBIND_AOT "Generate embind wrappers at build time" TRUE)
|
||||
|
||||
message("KTX2_ZSTANDARD=${KTX2_ZSTANDARD}")
|
||||
message("SUPPORT_ASTCENC=${SUPPORT_ASTCENC}")
|
||||
message("NO_DYNAMIC_EXECUTION=${NO_DYNAMIC_EXECUTION}")
|
||||
message("EMBIND_AOT=${EMBIND_AOT}")
|
||||
|
||||
# Only for Emscripten builds.
|
||||
if(EMSCRIPTEN)
|
||||
@@ -132,6 +142,13 @@ if(EMSCRIPTEN)
|
||||
|
||||
# Base link flags
|
||||
set(LINK_BASE "--bind -s ALLOW_MEMORY_GROWTH=1 -s INITIAL_MEMORY=134217728 -s STACK_SIZE=2097152 -s MODULARIZE=1 -s EXPORT_NAME=BASIS -s EXPORTED_RUNTIME_METHODS=['HEAP8']")
|
||||
if(NO_DYNAMIC_EXECUTION)
|
||||
set(LINK_BASE "${LINK_BASE} -s DYNAMIC_EXECUTION=0")
|
||||
if(EMBIND_AOT)
|
||||
set(LINK_BASE "${LINK_BASE} -s EMBIND_AOT=1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(LINK_THREADS "-s USE_PTHREADS=1 -s PTHREAD_POOL_SIZE=32 -s ENVIRONMENT=web,worker")
|
||||
set(LINK_WASM64 "-s MEMORY64=1 -sWASM_BIGINT=1 --profiling-funcs")
|
||||
|
||||
|
||||
@@ -5,3 +5,22 @@ cd webgl/encoder/build/
|
||||
emcmake cmake ../
|
||||
make
|
||||
```
|
||||
|
||||
### Strict Content-Security-Policy (no `unsafe-eval`)
|
||||
|
||||
By default, the generated JavaScript glue uses `new Function()` to build its
|
||||
embind bindings at runtime. A Content-Security-Policy without `'unsafe-eval'`
|
||||
blocks this, and module startup fails with an `EvalError`. To build glue that
|
||||
never calls `eval()` or `new Function()`, add `-DNO_DYNAMIC_EXECUTION=ON`:
|
||||
|
||||
```shell
|
||||
emcmake cmake ../ -DNO_DYNAMIC_EXECUTION=ON
|
||||
make
|
||||
```
|
||||
|
||||
This adds `-s DYNAMIC_EXECUTION=0 -s EMBIND_AOT=1` to the link flags. The
|
||||
`.wasm` file does not change. `EMBIND_AOT` generates the bindings at build
|
||||
time, so JavaScript-to-WASM calls stay as fast as in the default build. The
|
||||
page still needs `'wasm-unsafe-eval'` in `script-src` to compile the
|
||||
WebAssembly module. Use `-DEMBIND_AOT=OFF` to get the smaller, generic
|
||||
bindings, which are slower per call.
|
||||
|
||||
@@ -10,8 +10,18 @@ option(KTX2 "KTX2" TRUE)
|
||||
# If you know you'll never be transcoding KTX2 files using this feature you can set KTX2_ZSTANDARD to 0.
|
||||
option(KTX2_ZSTANDARD "KTX2_ZSTANDARD" TRUE)
|
||||
|
||||
# Use "cmake -DNO_DYNAMIC_EXECUTION=TRUE" to build JavaScript glue that never calls eval() or new Function().
|
||||
# This lets the module load under a Content-Security-Policy without 'unsafe-eval'.
|
||||
option(NO_DYNAMIC_EXECUTION "NO_DYNAMIC_EXECUTION" FALSE)
|
||||
|
||||
# With NO_DYNAMIC_EXECUTION, generate the embind call wrappers at build time (fast) instead of
|
||||
# using the slower generic wrappers. Only has an effect when NO_DYNAMIC_EXECUTION is TRUE.
|
||||
option(EMBIND_AOT "EMBIND_AOT" TRUE)
|
||||
|
||||
message("KTX2=${KTX2}")
|
||||
message("KTX2_ZSTANDARD=${KTX2_ZSTANDARD}")
|
||||
message("NO_DYNAMIC_EXECUTION=${NO_DYNAMIC_EXECUTION}")
|
||||
message("EMBIND_AOT=${EMBIND_AOT}")
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
@@ -61,8 +71,17 @@ if (EMSCRIPTEN)
|
||||
|
||||
target_include_directories(basis_transcoder.js PRIVATE ../../transcoder)
|
||||
|
||||
set(TRANSCODER_LINK_FLAGS "--bind -s ALLOW_MEMORY_GROWTH=1 -O3 -s MALLOC=emmalloc -s MODULARIZE=1 -s EXPORT_NAME=BASIS -s ASSERTIONS=0 -s EXPORTED_RUNTIME_METHODS=['HEAP8']")
|
||||
|
||||
if (NO_DYNAMIC_EXECUTION)
|
||||
set(TRANSCODER_LINK_FLAGS "${TRANSCODER_LINK_FLAGS} -s DYNAMIC_EXECUTION=0")
|
||||
if (EMBIND_AOT)
|
||||
set(TRANSCODER_LINK_FLAGS "${TRANSCODER_LINK_FLAGS} -s EMBIND_AOT=1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(basis_transcoder.js PROPERTIES
|
||||
OUTPUT_NAME "basis_transcoder"
|
||||
SUFFIX ".js"
|
||||
LINK_FLAGS "--bind -s ALLOW_MEMORY_GROWTH=1 -O3 -s MALLOC=emmalloc -s MODULARIZE=1 -s EXPORT_NAME=BASIS -s ASSERTIONS=0 -s EXPORTED_RUNTIME_METHODS=['HEAP8']")
|
||||
LINK_FLAGS "${TRANSCODER_LINK_FLAGS}")
|
||||
endif()
|
||||
|
||||
@@ -7,3 +7,22 @@ cd webgl/transcoder/build/
|
||||
emcmake cmake ../
|
||||
make
|
||||
```
|
||||
|
||||
### Strict Content-Security-Policy (no `unsafe-eval`)
|
||||
|
||||
By default, the generated JavaScript glue uses `new Function()` to build its
|
||||
embind bindings at runtime. A Content-Security-Policy without `'unsafe-eval'`
|
||||
blocks this, and module startup fails with an `EvalError`. To build glue that
|
||||
never calls `eval()` or `new Function()`, add `-DNO_DYNAMIC_EXECUTION=ON`:
|
||||
|
||||
```shell
|
||||
emcmake cmake ../ -DNO_DYNAMIC_EXECUTION=ON
|
||||
make
|
||||
```
|
||||
|
||||
This adds `-s DYNAMIC_EXECUTION=0 -s EMBIND_AOT=1` to the link flags. The
|
||||
`.wasm` file does not change. `EMBIND_AOT` generates the bindings at build
|
||||
time, so JavaScript-to-WASM calls stay as fast as in the default build. The
|
||||
page still needs `'wasm-unsafe-eval'` in `script-src` to compile the
|
||||
WebAssembly module. Use `-DEMBIND_AOT=OFF` to get the smaller, generic
|
||||
bindings, which are slower per call.
|
||||
|
||||
@@ -3347,17 +3347,17 @@ EMSCRIPTEN_BINDINGS(basis_codec) {
|
||||
constant("ASTC_HDR_MAX_VAL", basist::ASTC_HDR_MAX_VAL);
|
||||
|
||||
// UASTC LDR/HDR flags/options
|
||||
constant("cPackUASTCLevelFastest", cPackUASTCLevelFastest);
|
||||
constant("cPackUASTCLevelFaster", cPackUASTCLevelFaster);
|
||||
constant("cPackUASTCLevelDefault", cPackUASTCLevelDefault);
|
||||
constant("cPackUASTCLevelSlower", cPackUASTCLevelSlower);
|
||||
constant("cPackUASTCLevelVerySlow", cPackUASTCLevelVerySlow);
|
||||
constant("cPackUASTCLevelMask", cPackUASTCLevelMask);
|
||||
constant("cPackUASTCFavorUASTCError", cPackUASTCFavorUASTCError);
|
||||
constant("cPackUASTCFavorBC7Error", cPackUASTCFavorBC7Error);
|
||||
constant("cPackUASTCETC1FasterHints", cPackUASTCETC1FasterHints);
|
||||
constant("cPackUASTCETC1FastestHints", cPackUASTCETC1FastestHints);
|
||||
constant("cPackUASTCETC1DisableFlipAndIndividual", cPackUASTCETC1DisableFlipAndIndividual);
|
||||
constant("cPackUASTCLevelFastest", static_cast<uint32_t>(cPackUASTCLevelFastest));
|
||||
constant("cPackUASTCLevelFaster", static_cast<uint32_t>(cPackUASTCLevelFaster));
|
||||
constant("cPackUASTCLevelDefault", static_cast<uint32_t>(cPackUASTCLevelDefault));
|
||||
constant("cPackUASTCLevelSlower", static_cast<uint32_t>(cPackUASTCLevelSlower));
|
||||
constant("cPackUASTCLevelVerySlow", static_cast<uint32_t>(cPackUASTCLevelVerySlow));
|
||||
constant("cPackUASTCLevelMask", static_cast<uint32_t>(cPackUASTCLevelMask));
|
||||
constant("cPackUASTCFavorUASTCError", static_cast<uint32_t>(cPackUASTCFavorUASTCError));
|
||||
constant("cPackUASTCFavorBC7Error", static_cast<uint32_t>(cPackUASTCFavorBC7Error));
|
||||
constant("cPackUASTCETC1FasterHints", static_cast<uint32_t>(cPackUASTCETC1FasterHints));
|
||||
constant("cPackUASTCETC1FastestHints", static_cast<uint32_t>(cPackUASTCETC1FastestHints));
|
||||
constant("cPackUASTCETC1DisableFlipAndIndividual", static_cast<uint32_t>(cPackUASTCETC1DisableFlipAndIndividual));
|
||||
|
||||
constant("UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO", UASTC_RDO_DEFAULT_MAX_ALLOWED_RMS_INCREASE_RATIO);
|
||||
constant("UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH", UASTC_RDO_DEFAULT_SKIP_BLOCK_RMS_THRESH);
|
||||
|
||||
Reference in New Issue
Block a user