changeset 2510:04873915beaf

configuration of DCMTK for WebAssembly
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 28 Mar 2018 14:14:37 +0200
parents 9d9f2d088dce
children 8a0d3044ef53
files Resources/CMake/Compiler.cmake Resources/CMake/DcmtkConfiguration.cmake Resources/CMake/OrthancFrameworkConfiguration.cmake Resources/WebAssembly/ArithmeticTests/CMakeLists.txt Resources/WebAssembly/ArithmeticTests/Run2.cpp Resources/WebAssembly/ArithmeticTests/app.js Resources/WebAssembly/ArithmeticTests/arith.patch Resources/WebAssembly/ArithmeticTests/index.html Resources/WebAssembly/arith.h
diffstat 9 files changed, 310 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/Resources/CMake/Compiler.cmake	Wed Mar 28 11:31:19 2018 +0200
+++ b/Resources/CMake/Compiler.cmake	Wed Mar 28 14:14:37 2018 +0200
@@ -174,6 +174,12 @@
 elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
   message("Building using Emscripten (for WebAssembly or asm.js targets)")
 
+  # The BINARYEN_TRAP_MODE specifies what to do when divisions per
+  # zero (and similar conditions like integer overflows) are
+  # encountered: The "clamp" mode avoids throwing errors, as they
+  # cannot be properly catched by "try {} catch (...)" constructions.
+  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"ccall\", \"cwrap\"]' -s BINARYEN_TRAP_MODE='\"clamp\"'")
+
 else()
   message(FATAL_ERROR "Support your platform here")
 endif()
--- a/Resources/CMake/DcmtkConfiguration.cmake	Wed Mar 28 11:31:19 2018 +0200
+++ b/Resources/CMake/DcmtkConfiguration.cmake	Wed Mar 28 14:14:37 2018 +0200
@@ -106,8 +106,20 @@
       SET(C_CHAR_UNSIGNED 1 CACHE INTERNAL "Whether char is unsigned.")
 
     elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")  # WebAssembly or asm.js
-      SET(C_CHAR_UNSIGNED 0 CACHE INTERNAL "Whether char is unsigned.")
-      SET(SIZEOF_VOID_P 4 CACHE INTERNAL "")
+      # Check out "../WebAssembly/arith.h"
+      SET(SIZEOF_VOID_P 4   CACHE INTERNAL "")
+      SET(SIZEOF_CHAR 1     CACHE INTERNAL "")
+      SET(SIZEOF_DOUBLE 8   CACHE INTERNAL "")
+      SET(SIZEOF_FLOAT 4    CACHE INTERNAL "")
+      SET(SIZEOF_INT 4      CACHE INTERNAL "")
+      SET(SIZEOF_LONG 4     CACHE INTERNAL "")
+      SET(SIZEOF_SHORT 2    CACHE INTERNAL "")
+      SET(SIZEOF_VOID_P 4   CACHE INTERNAL "")
+      SET(C_CHAR_UNSIGNED 0 CACHE INTERNAL "")
+      configure_file(
+        ${ORTHANC_ROOT}/Resources/WebAssembly/arith.h
+        ${DCMTK_SOURCES_DIR}/config/include/dcmtk/config/arith.h
+        COPYONLY)
 
     else()
       message(FATAL_ERROR "Support your platform here")
@@ -156,7 +168,9 @@
     endif()
 
     # This step must be after the generation of "osconfig.h"
-    INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES()
+    if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
+      INSPECT_FUNDAMENTAL_ARITHMETIC_TYPES()
+    endif()
   endif()
 
   AUX_SOURCE_DIRECTORY(${DCMTK_SOURCES_DIR}/dcmdata/libsrc DCMTK_SOURCES)
--- a/Resources/CMake/OrthancFrameworkConfiguration.cmake	Wed Mar 28 11:31:19 2018 +0200
+++ b/Resources/CMake/OrthancFrameworkConfiguration.cmake	Wed Mar 28 14:14:37 2018 +0200
@@ -376,7 +376,7 @@
 
 if (ENABLE_DCMTK)
   if (NOT ENABLE_LOCALE)
-    message(FATAL_ERROR "Support for locales must be enabled if enabling DICOM support")
+#    message(FATAL_ERROR "Support for locales must be enabled if enabling DICOM support")
   endif()
 
   include(${CMAKE_CURRENT_LIST_DIR}/DcmtkConfiguration.cmake)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/WebAssembly/ArithmeticTests/CMakeLists.txt	Wed Mar 28 14:14:37 2018 +0200
@@ -0,0 +1,101 @@
+# source ~/Downloads/emsdk-portable/emsdk_env.sh
+# cmake .. -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Modules/Platform/Emscripten.cmake \
+#       -DCMAKE_BUILD_TYPE=Debug \
+#       -DCMAKE_INSTALL_PREFIX=/tmp/wasm-install/
+# make install
+# -> Open the "/tmp/wasm-install/" with Firefox by serving it through Apache
+# -> Copy the result as "../arith.h"
+
+
+cmake_minimum_required(VERSION 2.8.3)
+
+
+#####################################################################
+## Configuration of the Emscripten compiler for WebAssembly target
+#####################################################################
+
+set(WASM_FLAGS "-s WASM=1 -s DISABLE_EXCEPTION_CATCHING=0")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WASM_FLAGS}")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WASM_FLAGS}")
+
+# Turn on support for debug exceptions
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s DISABLE_EXCEPTION_CATCHING=0")
+
+
+#####################################################################
+## Prepare DCMTK 3.6.2
+#####################################################################
+
+set(ORTHANC_ROOT ${CMAKE_SOURCE_DIR}/../../..)
+include(${ORTHANC_ROOT}/Resources/CMake/Compiler.cmake)
+include(${ORTHANC_ROOT}/Resources/CMake/DownloadPackage.cmake)
+
+set(DCMTK_SOURCES_DIR ${CMAKE_BINARY_DIR}/dcmtk-3.6.2)
+set(DCMTK_URL "http://www.orthanc-server.com/downloads/third-party/dcmtk-3.6.2.tar.gz")
+set(DCMTK_MD5 "d219a4152772985191c9b89d75302d12")
+
+if (IS_DIRECTORY "${DCMTK_SOURCES_DIR}")
+  set(FirstRun OFF)
+else()
+  set(FirstRun ON)
+endif()
+
+DownloadPackage(${DCMTK_MD5} ${DCMTK_URL} "${DCMTK_SOURCES_DIR}")
+
+if (FirstRun)
+  message("Patching file")
+  execute_process(
+    COMMAND ${PATCH_EXECUTABLE} -p0 -N -i
+    ${CMAKE_SOURCE_DIR}/arith.patch
+    WORKING_DIRECTORY ${DCMTK_SOURCES_DIR}/config/tests
+    RESULT_VARIABLE Failure
+    )
+
+  if (Failure)
+    message(FATAL_ERROR "Error while patching a file")
+  endif()
+endif()
+
+
+#####################################################################
+## Build the DCMTK tests for arithmetics
+#####################################################################
+
+# https://github.com/kripken/emscripten/wiki/WebAssembly#web-server-setup
+file(WRITE ${CMAKE_BINARY_DIR}/.htaccess "
+AddType application/wasm .wasm
+AddOutputFilterByType DEFLATE application/wasm
+")
+
+file(WRITE ${CMAKE_BINARY_DIR}/dcmtk/config/osconfig.h "
+#pragma once
+#define HAVE_CMATH 1
+#define HAVE_MATH_H 1
+#define HAVE_PROTOTYPE_FINITE 1
+#define HAVE_PROTOTYPE_STD__ISINF 1
+#define HAVE_PROTOTYPE_STD__ISNAN 1
+#define HAVE_STD_NAMESPACE 1
+#define HAVE_STRSTREAM 1
+#define SIZEOF_VOID_P 4
+#define USE_STD_CXX_INCLUDES
+")
+
+include_directories(
+  ${DCMTK_SOURCES_DIR}/ofstd/include
+  ${CMAKE_BINARY_DIR}
+  )
+
+add_executable(dcmtk
+  ${DCMTK_SOURCES_DIR}/config/tests/arith.cc
+  ${CMAKE_SOURCE_DIR}/Run2.cpp
+  )
+
+install(TARGETS dcmtk DESTINATION .)
+
+install(FILES
+  ${CMAKE_BINARY_DIR}/.htaccess
+  ${CMAKE_BINARY_DIR}/dcmtk.wasm
+  ${CMAKE_SOURCE_DIR}/app.js
+  ${CMAKE_SOURCE_DIR}/index.html
+  DESTINATION .
+  )
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/WebAssembly/ArithmeticTests/Run2.cpp	Wed Mar 28 14:14:37 2018 +0200
@@ -0,0 +1,22 @@
+#include <iostream>
+#include <emscripten/emscripten.h>
+
+extern "C"
+{
+  void EMSCRIPTEN_KEEPALIVE Run2()
+  {
+    // This stuff is not properly discovered by DCMTK 3.6.2 configuration scripts
+    std::cerr << std::endl << std::endl;
+    std::cerr << "/**" << std::endl;
+    std::cerr << "#define SIZEOF_CHAR " << sizeof(char) << std::endl;
+    std::cerr << "#define SIZEOF_DOUBLE " << sizeof(double) << std::endl;    
+    std::cerr << "#define SIZEOF_FLOAT " << sizeof(float) << std::endl;
+    std::cerr << "#define SIZEOF_INT " << sizeof(int) << std::endl;
+    std::cerr << "#define SIZEOF_LONG " << sizeof(long) << std::endl;
+    std::cerr << "#define SIZEOF_SHORT " << sizeof(short) << std::endl;
+    std::cerr << "#define SIZEOF_VOID_P " << sizeof(void*) << std::endl;
+    std::cerr << "#define C_CHAR_UNSIGNED " << (!std::is_signed<char>()) << std::endl;
+    std::cerr << "**/" << std::endl;
+    std::cerr << std::endl << std::endl;
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/WebAssembly/ArithmeticTests/app.js	Wed Mar 28 14:14:37 2018 +0200
@@ -0,0 +1,34 @@
+function Initialize()
+{
+  Module.ccall('Run2', // name of C function
+               null, // return type
+               [], // argument types
+               []);
+
+  Module.ccall('Run', // name of C function
+               'number', // return type
+               [], // argument types
+               []);
+}
+
+
+var Module = {
+  preRun: [],
+  postRun: [ Initialize ],
+  print: function(text) {
+    console.log(text);
+  },
+  printErr: function(text) {
+    if (text != 'Calling stub instead of signal()')
+    {
+      document.getElementById("stderr").textContent += text + '\n';
+    }
+  },
+  totalDependencies: 0
+};
+
+
+if (!('WebAssembly' in window)) {
+  alert('Sorry, your browser does not support WebAssembly :(');
+} else {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/WebAssembly/ArithmeticTests/arith.patch	Wed Mar 28 14:14:37 2018 +0200
@@ -0,0 +1,46 @@
+--- /home/jodogne/Subversion/orthanc/Resources/WebAssembly/ArithmeticTests/i/dcmtk-3.6.2/config/tests/arith.cc	2017-07-14 17:41:11.000000000 +0200
++++ arith.cc	2018-03-28 13:53:34.242234303 +0200
+@@ -19,6 +19,8 @@
+  *           for being used within oflimits.h.
+  */
+ 
++#include <emscripten/emscripten.h>
++
+ // Note: This depends on some files of ofstd and osconfig.h,
+ //       although it is part of configure testing itself.
+ //       Therefore, ensure osconfig.h has already been generated
+@@ -514,7 +516,9 @@
+ }
+ #endif
+ 
+-int main( int argc, char** argv )
++extern "C"
++{
++int EMSCRIPTEN_KEEPALIVE Run()
+ {
+ #ifdef HAVE_WINDOWS_H
+     // Activate the fallback workaround, it will only be used
+@@ -524,6 +528,8 @@
+ #endif
+ 
+     COUT << "Inspecting fundamental arithmetic types... " << OFendl;
++
++#if 0
+     if( argc != 2 )
+     {
+         STD_NAMESPACE cerr << "--   " << "Error: missing destination file "
+@@ -532,6 +538,9 @@
+     }
+ 
+     STD_NAMESPACE ofstream out( argv[1] );
++#else
++    std::ostream& out = std::cerr;
++#endif
+ 
+     out << "#ifndef CONFIG_ARITH_H" << '\n';
+     out << "#define CONFIG_ARITH_H" << '\n';
+@@ -619,3 +628,4 @@
+ 
+     return 0;
+ }
++}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/WebAssembly/ArithmeticTests/index.html	Wed Mar 28 14:14:37 2018 +0200
@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en-us">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+    <title>DCMTK - Inspect arithmetic types</title>
+  </head>
+  <body>
+    <pre id="stderr"></pre>
+    <script type="text/javascript" src="app.js"></script>
+    <script type="text/javascript" async src="dcmtk.js"></script>
+  </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/WebAssembly/arith.h	Wed Mar 28 14:14:37 2018 +0200
@@ -0,0 +1,70 @@
+/**
+#define SIZEOF_CHAR 1
+#define SIZEOF_DOUBLE 8
+#define SIZEOF_FLOAT 4
+#define SIZEOF_INT 4
+#define SIZEOF_LONG 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_VOID_P 4
+#define C_CHAR_UNSIGNED 0
+**/
+
+
+#ifndef CONFIG_ARITH_H
+#define CONFIG_ARITH_H
+
+#define DCMTK_SIGNED_CHAR_DIGITS10 2
+#define DCMTK_UNSIGNED_CHAR_DIGITS10 2
+#define DCMTK_SIGNED_SHORT_DIGITS10 4
+#define DCMTK_UNSIGNED_SHORT_DIGITS10 4
+#define DCMTK_SIGNED_INT_DIGITS10 9
+#define DCMTK_UNSIGNED_INT_DIGITS10 9
+#define DCMTK_SIGNED_LONG_DIGITS10 9
+#define DCMTK_UNSIGNED_LONG_DIGITS10 9
+#define DCMTK_FLOAT_MAX_DIGITS10 9
+#define DCMTK_DOUBLE_MAX_DIGITS10 17
+#define DCMTK_CHAR_TRAPS OFFalse
+#define DCMTK_CHAR_MODULO OFTrue
+#define DCMTK_SIGNED_CHAR_TRAPS OFFalse
+#define DCMTK_SIGNED_CHAR_MODULO OFTrue
+#define DCMTK_UNSIGNED_CHAR_TRAPS OFFalse
+#define DCMTK_UNSIGNED_CHAR_MODULO OFTrue
+#define DCMTK_SIGNED_SHORT_TRAPS OFFalse
+#define DCMTK_SIGNED_SHORT_MODULO OFTrue
+#define DCMTK_UNSIGNED_SHORT_TRAPS OFFalse
+#define DCMTK_UNSIGNED_SHORT_MODULO OFTrue
+#define DCMTK_SIGNED_INT_TRAPS OFFalse
+#define DCMTK_SIGNED_INT_MODULO OFTrue
+#define DCMTK_UNSIGNED_INT_TRAPS OFFalse
+#define DCMTK_UNSIGNED_INT_MODULO OFTrue
+#define DCMTK_SIGNED_LONG_TRAPS OFFalse
+#define DCMTK_SIGNED_LONG_MODULO OFTrue
+#define DCMTK_UNSIGNED_LONG_TRAPS OFFalse
+#define DCMTK_UNSIGNED_LONG_MODULO OFTrue
+#define DCMTK_FLOAT_TRAPS OFFalse
+#define DCMTK_DOUBLE_TRAPS OFFalse
+#define DCMTK_FLOAT_HAS_INFINITY OFTrue
+#define DCMTK_FLOAT_INFINITY *OFreinterpret_cast( const float*, "\000\000\200\177" )
+#define DCMTK_DOUBLE_HAS_INFINITY OFTrue
+#define DCMTK_DOUBLE_INFINITY *OFreinterpret_cast( const double*, "\000\000\000\000\000\000\360\177" )
+#define DCMTK_FLOAT_HAS_QUIET_NAN OFTrue
+#define DCMTK_FLOAT_QUIET_NAN *OFreinterpret_cast( const float*, "\000\000\300\177" )
+#define DCMTK_DOUBLE_HAS_QUIET_NAN OFTrue
+#define DCMTK_DOUBLE_QUIET_NAN *OFreinterpret_cast( const double*, "\000\000\000\000\000\000\370\177" )
+#define DCMTK_FLOAT_HAS_SIGNALING_NAN OFFalse
+#define DCMTK_FLOAT_SIGNALING_NAN *OFreinterpret_cast( const float*, "\001\000\200\177" )
+#define DCMTK_DOUBLE_HAS_SIGNALING_NAN OFFalse
+#define DCMTK_DOUBLE_SIGNALING_NAN *OFreinterpret_cast( const double*, "\001\000\000\000\000\000\360\177" )
+#define DCMTK_FLOAT_IS_IEC559 OFFalse
+#define DCMTK_DOUBLE_IS_IEC559 OFFalse
+#define DCMTK_FLOAT_HAS_DENORM OFdenorm_present
+#define DCMTK_FLOAT_DENORM_MIN *OFreinterpret_cast( const float*, "\001\000\000\000" )
+#define DCMTK_DOUBLE_HAS_DENORM OFdenorm_present
+#define DCMTK_DOUBLE_DENORM_MIN *OFreinterpret_cast( const double*, "\001\000\000\000\000\000\000\000" )
+#define DCMTK_FLOAT_TINYNESS_BEFORE OFFalse
+#define DCMTK_DOUBLE_TINYNESS_BEFORE OFFalse
+#define DCMTK_FLOAT_HAS_DENORM_LOSS OFFalse
+#define DCMTK_DOUBLE_HAS_DENORM_LOSS OFFalse
+#define DCMTK_ROUND_STYLE 1
+
+#endif // CONFIG_ARITH_H