changeset 155:23cf7def8e44

use of OrthancPluginsExports.cmake, avoid race conditions with EmbedResources.py
author Sebastien Jodogne <s.jodogne@gmail.com>
date Mon, 06 Jul 2020 12:04:00 +0200
parents 99d13f5b576a
children 710537acb488
files MySQL/CMakeLists.txt PostgreSQL/CMakeLists.txt Resources/CMake/DatabasesFrameworkParameters.cmake Resources/CMake/DatabasesPluginConfiguration.cmake Resources/Orthanc/CMake/AutoGeneratedCode.cmake Resources/Orthanc/CMake/Compiler.cmake Resources/Orthanc/CMake/DownloadOrthancFramework.cmake Resources/Orthanc/CMake/DownloadPackage.cmake Resources/Orthanc/CMake/GoogleTestConfiguration.cmake Resources/Orthanc/DownloadOrthancFramework.cmake Resources/Orthanc/EmbedResources.py Resources/Orthanc/Plugins/ExportedSymbolsPlugins.list Resources/Orthanc/Plugins/OrthancPluginsExports.cmake Resources/Orthanc/Plugins/VersionScriptPlugins.map Resources/SyncOrthancFolder.py SQLite/CMakeLists.txt
diffstat 16 files changed, 1692 insertions(+), 535 deletions(-) [+]
line wrap: on
line diff
--- a/MySQL/CMakeLists.txt	Wed Jul 01 17:13:38 2020 +0200
+++ b/MySQL/CMakeLists.txt	Mon Jul 06 12:04:00 2020 +0200
@@ -61,6 +61,12 @@
   MYSQL_CREATE_INSTANCE        ${CMAKE_SOURCE_DIR}/Plugins/CreateInstance.sql
   )
 
+add_custom_target(
+  AutogeneratedTarget
+  DEPENDS 
+  ${AUTOGENERATED_SOURCES}
+  )
+
 add_library(OrthancMySQLIndex SHARED
   ${INDEX_RESOURCES}
   ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/PluginInitialization.cpp
@@ -71,6 +77,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(OrthancMySQLIndex AutogeneratedTarget)
+
 add_library(OrthancMySQLStorage SHARED
   ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/PluginInitialization.cpp
   ${STORAGE_RESOURCES}
@@ -81,6 +89,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(OrthancMySQLStorage AutogeneratedTarget)
+
 message("Setting the version of the libraries to ${ORTHANC_PLUGIN_VERSION}")
 
 add_definitions(
@@ -116,6 +126,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(UnitTests AutogeneratedTarget)
+
 target_link_libraries(UnitTests ${GOOGLE_TEST_LIBRARIES})
 set_target_properties(UnitTests PROPERTIES
   COMPILE_FLAGS -DORTHANC_ENABLE_LOGGING_PLUGIN=0
--- a/PostgreSQL/CMakeLists.txt	Wed Jul 01 17:13:38 2020 +0200
+++ b/PostgreSQL/CMakeLists.txt	Mon Jul 06 12:04:00 2020 +0200
@@ -63,6 +63,12 @@
   POSTGRESQL_GET_LAST_CHANGE_INDEX  ${CMAKE_SOURCE_DIR}/Plugins/GetLastChangeIndex.sql
   )
 
+add_custom_target(
+  AutogeneratedTarget
+  DEPENDS 
+  ${AUTOGENERATED_SOURCES}
+  )
+
 add_library(OrthancPostgreSQLIndex SHARED
   ${INDEX_RESOURCES}
   ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/PluginInitialization.cpp
@@ -73,6 +79,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(OrthancPostgreSQLIndex AutogeneratedTarget)
+
 add_library(OrthancPostgreSQLStorage SHARED
   ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/PluginInitialization.cpp
   ${STORAGE_RESOURCES}
@@ -83,6 +91,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(OrthancPostgreSQLStorage AutogeneratedTarget)
+
 message("Setting the version of the libraries to ${ORTHANC_PLUGIN_VERSION}")
 
 add_definitions(
@@ -118,6 +128,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(UnitTests AutogeneratedTarget)
+
 target_link_libraries(UnitTests ${GOOGLE_TEST_LIBRARIES})
 set_target_properties(UnitTests PROPERTIES
   COMPILE_FLAGS -DORTHANC_ENABLE_LOGGING_PLUGIN=0
--- a/Resources/CMake/DatabasesFrameworkParameters.cmake	Wed Jul 01 17:13:38 2020 +0200
+++ b/Resources/CMake/DatabasesFrameworkParameters.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -22,7 +22,7 @@
 ## Import the parameters of the Orthanc Framework
 #####################################################################
 
-include(${CMAKE_CURRENT_LIST_DIR}/../../Resources/Orthanc/DownloadOrthancFramework.cmake)
+include(${CMAKE_CURRENT_LIST_DIR}/../Orthanc/CMake/DownloadOrthancFramework.cmake)
 include(${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
 
 
--- a/Resources/CMake/DatabasesPluginConfiguration.cmake	Wed Jul 01 17:13:38 2020 +0200
+++ b/Resources/CMake/DatabasesPluginConfiguration.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -19,7 +19,8 @@
 
 
 include(${CMAKE_SOURCE_DIR}/../Resources/CMake/DatabasesFrameworkConfiguration.cmake)
-include(${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/AutoGeneratedCode.cmake)
+include(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/CMake/AutoGeneratedCode.cmake)
+include(${CMAKE_SOURCE_DIR}/../Resources/Orthanc/Plugins/OrthancPluginsExports.cmake)
 
 
 include_directories(${ORTHANC_FRAMEWORK_ROOT}/Sources)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/CMake/AutoGeneratedCode.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,58 @@
+set(EMBED_RESOURCES_PYTHON "${CMAKE_CURRENT_LIST_DIR}/../EmbedResources.py"
+  CACHE INTERNAL "Path to the EmbedResources.py script from Orthanc")
+set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED")
+set(AUTOGENERATED_SOURCES)
+
+file(MAKE_DIRECTORY ${AUTOGENERATED_DIR})
+include_directories(${AUTOGENERATED_DIR})
+
+macro(EmbedResources)
+  # Convert a semicolon separated list to a whitespace separated string
+  set(SCRIPT_OPTIONS)
+  set(SCRIPT_ARGUMENTS)
+  set(DEPENDENCIES)
+  set(IS_PATH_NAME false)
+
+  set(TARGET_BASE "${AUTOGENERATED_DIR}/EmbeddedResources")
+
+  # Loop over the arguments of the function
+  foreach(arg ${ARGN})
+    # Extract the first character of the argument
+    string(SUBSTRING "${arg}" 0 1 FIRST_CHAR)
+    if (${FIRST_CHAR} STREQUAL "-")
+      # If the argument starts with a dash "-", this is an option to
+      # EmbedResources.py
+      if (${arg} MATCHES "--target=.*")
+        # Does the argument starts with "--target="?
+        string(SUBSTRING "${arg}" 9 -1 TARGET)  # 9 is the length of "--target="
+        set(TARGET_BASE "${AUTOGENERATED_DIR}/${TARGET}")
+      else()
+        list(APPEND SCRIPT_OPTIONS ${arg})
+      endif()
+    else()
+      if (${IS_PATH_NAME})
+        list(APPEND SCRIPT_ARGUMENTS "${arg}")
+        list(APPEND DEPENDENCIES "${arg}")
+        set(IS_PATH_NAME false)
+      else()
+        list(APPEND SCRIPT_ARGUMENTS "${arg}")
+        set(IS_PATH_NAME true)
+      endif()
+    endif()
+  endforeach()
+
+  add_custom_command(
+    OUTPUT
+    "${TARGET_BASE}.h"
+    "${TARGET_BASE}.cpp"
+    COMMAND ${PYTHON_EXECUTABLE} ${EMBED_RESOURCES_PYTHON}
+            ${SCRIPT_OPTIONS} "${TARGET_BASE}" ${SCRIPT_ARGUMENTS}
+    DEPENDS
+    ${EMBED_RESOURCES_PYTHON}
+    ${DEPENDENCIES}
+    )
+
+  list(APPEND AUTOGENERATED_SOURCES
+    "${TARGET_BASE}.cpp"
+    ) 
+endmacro()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/CMake/Compiler.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,243 @@
+# This file sets all the compiler-related flags
+
+
+# Save the current compiler flags to the cache every time cmake configures the project
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "compiler flags" FORCE)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "compiler flags" FORCE)
+
+
+include(CheckLibraryExists)
+
+if ((CMAKE_CROSSCOMPILING AND NOT
+      "${CMAKE_SYSTEM_VERSION}" STREQUAL "CrossToolNg") OR    
+    "${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
+  # Cross-compilation necessarily implies standalone and static build
+  SET(STATIC_BUILD ON)
+  SET(STANDALONE_BUILD ON)
+endif()
+
+
+if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
+  # Cache the environment variables "LSB_CC" and "LSB_CXX" for further
+  # use by "ExternalProject" in CMake
+  SET(CMAKE_LSB_CC $ENV{LSB_CC} CACHE STRING "")
+  SET(CMAKE_LSB_CXX $ENV{LSB_CXX} CACHE STRING "")
+endif()
+
+
+if (CMAKE_COMPILER_IS_GNUCXX)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-long-long")
+
+  # --std=c99 makes libcurl not to compile
+  # -pedantic gives a lot of warnings on OpenSSL 
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -Wno-variadic-macros")
+
+  if (CMAKE_CROSSCOMPILING)
+    # http://stackoverflow.com/a/3543845/881731
+    set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff -I<CMAKE_CURRENT_SOURCE_DIR> <SOURCE> <OBJECT>")
+  endif()
+
+elseif (MSVC)
+  # Use static runtime under Visual Studio
+  # http://www.cmake.org/Wiki/CMake_FAQ#Dynamic_Replace
+  # http://stackoverflow.com/a/6510446
+  foreach(flag_var
+    CMAKE_C_FLAGS_DEBUG
+    CMAKE_CXX_FLAGS_DEBUG
+    CMAKE_C_FLAGS_RELEASE 
+    CMAKE_CXX_FLAGS_RELEASE
+    CMAKE_C_FLAGS_MINSIZEREL 
+    CMAKE_CXX_FLAGS_MINSIZEREL 
+    CMAKE_C_FLAGS_RELWITHDEBINFO 
+    CMAKE_CXX_FLAGS_RELWITHDEBINFO) 
+    string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
+    string(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
+  endforeach(flag_var)
+
+  # Add /Zm256 compiler option to Visual Studio to fix PCH errors
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zm256")
+
+  # New in Orthanc 1.5.5
+  if (MSVC_MULTIPLE_PROCESSES)
+    # "If you omit the processMax argument in the /MP option, the
+    # compiler obtains the number of effective processors from the
+    # operating system, and then creates one process per effective
+    # processor"
+    # https://blog.kitware.com/cmake-building-with-all-your-cores/
+    # https://docs.microsoft.com/en-us/cpp/build/reference/mp-build-with-multiple-processes
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+  endif()
+    
+  add_definitions(
+    -D_CRT_SECURE_NO_WARNINGS=1
+    -D_CRT_SECURE_NO_DEPRECATE=1
+    )
+
+  if (MSVC_VERSION LESS 1600)
+    # Starting with Visual Studio >= 2010 (i.e. macro _MSC_VER >=
+    # 1600), Microsoft ships a standard-compliant <stdint.h>
+    # header. For earlier versions of Visual Studio, give access to a
+    # compatibility header.
+    # http://stackoverflow.com/a/70630/881731
+    # https://en.wikibooks.org/wiki/C_Programming/C_Reference/stdint.h#External_links
+    include_directories(${CMAKE_CURRENT_LIST_DIR}/../../Resources/ThirdParty/VisualStudio)
+  endif()
+
+  link_libraries(netapi32)
+endif()
+
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+  # In FreeBSD/OpenBSD, the "/usr/local/" folder contains the ports and need to be imported
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/local/include")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/local/include")
+  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L/usr/local/lib")
+  SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -L/usr/local/lib")
+endif()
+
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+
+  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD" AND
+      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
+    # The "--no-undefined" linker flag makes the shared libraries
+    # (plugins ModalityWorklists and ServeFolders) fail to compile on
+    # OpenBSD, and make the PostgreSQL plugin complain about missing
+    # "environ" global variable in FreeBSD
+    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
+  endif()
+
+  # Remove the "-rdynamic" option
+  # http://www.mail-archive.com/cmake@cmake.org/msg08837.html
+  set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+  link_libraries(pthread)
+
+  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+    link_libraries(rt)
+  endif()
+
+  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND
+      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+    link_libraries(dl)
+  endif()
+
+  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND
+      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+    # The "--as-needed" linker flag is not available on FreeBSD and OpenBSD
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed")
+    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--as-needed")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed")
+  endif()
+
+  if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" AND
+      NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+    # FreeBSD/OpenBSD have just one single interface for file
+    # handling, which is 64bit clean, so there is no need to define macro
+    # for LFS (Large File Support).
+    # https://ohse.de/uwe/articles/lfs.html
+    add_definitions(
+      -D_LARGEFILE64_SOURCE=1 
+      -D_FILE_OFFSET_BITS=64
+      )
+  endif()
+
+elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
+  if (MSVC)
+    message("MSVC compiler version = " ${MSVC_VERSION} "\n")
+    # Starting Visual Studio 2013 (version 1800), it is not possible
+    # to target Windows XP anymore
+    if (MSVC_VERSION LESS 1800)
+      add_definitions(
+        -DWINVER=0x0501
+        -D_WIN32_WINNT=0x0501
+        )
+    endif()
+  else()
+    add_definitions(
+      -DWINVER=0x0501
+      -D_WIN32_WINNT=0x0501
+      )
+  endif()
+
+  add_definitions(
+    -D_CRT_SECURE_NO_WARNINGS=1
+    )
+  link_libraries(rpcrt4 ws2_32)
+
+  if (CMAKE_COMPILER_IS_GNUCXX)
+    # Some additional C/C++ compiler flags for MinGW
+    SET(MINGW_NO_WARNINGS "-Wno-unused-function -Wno-unused-variable")
+    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MINGW_NO_WARNINGS} -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MINGW_NO_WARNINGS}")
+
+    if (DYNAMIC_MINGW_STDLIB)
+    else()
+      # This is a patch for MinGW64
+      SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++")
+      SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--allow-multiple-definition -static-libgcc -static-libstdc++")
+    endif()
+
+    CHECK_LIBRARY_EXISTS(winpthread pthread_create "" HAVE_WIN_PTHREAD)
+    if (HAVE_WIN_PTHREAD)
+      if (DYNAMIC_MINGW_STDLIB)
+      else()
+        # This line is necessary to compile with recent versions of MinGW,
+        # otherwise "libwinpthread-1.dll" is not statically linked.
+        SET(CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} -Wl,-Bstatic -lstdc++ -lpthread -Wl,-Bdynamic")
+      endif()
+      add_definitions(-DHAVE_WIN_PTHREAD=1)
+    else()
+      add_definitions(-DHAVE_WIN_PTHREAD=0)
+    endif()
+  endif()
+
+elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
+  add_definitions(
+    -D_XOPEN_SOURCE=1
+    )
+  link_libraries(iconv)
+
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
+  message("Building using Emscripten (for WebAssembly or asm.js targets)")
+  include(${CMAKE_CURRENT_LIST_DIR}/EmscriptenParameters.cmake)
+  
+elseif (CMAKE_SYSTEM_NAME STREQUAL "Android")
+
+else()
+  message("Unknown target platform: ${CMAKE_SYSTEM_NAME}")
+  message(FATAL_ERROR "Support your platform here")
+endif()
+
+
+if (DEFINED ENABLE_PROFILING AND ENABLE_PROFILING)
+  if (CMAKE_COMPILER_IS_GNUCXX)
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg")
+    set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -pg")
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg")
+  else()
+    message(FATAL_ERROR "Don't know how to enable profiling on your configuration")
+  endif()
+endif()
+
+
+if (CMAKE_COMPILER_IS_GNUCXX)
+  # "When creating a static library using binutils (ar) and there
+  # exist a duplicate object name (e.g. a/Foo.cpp.o, b/Foo.cpp.o), the
+  # resulting static library can end up having only one of the
+  # duplicate objects. [...] This bug only happens if there are many
+  # objects." The trick consists in replacing the "r" argument
+  # ("replace") provided to "ar" (as used in CMake < 3.1) by the "q"
+  # argument ("quick append"). This is because of the fact that CMake
+  # will invoke "ar" several times with several batches of ".o"
+  # objects, and using "r" would overwrite symbols defined in
+  # preceding batches. https://cmake.org/Bug/view.php?id=14874
+  set(CMAKE_CXX_ARCHIVE_APPEND "<CMAKE_AR> <LINK_FLAGS> q <TARGET> <OBJECTS>")
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/CMake/DownloadOrthancFramework.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,532 @@
+# Orthanc - A Lightweight, RESTful DICOM Store
+# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+# Department, University Hospital of Liege, Belgium
+# Copyright (C) 2017-2020 Osimis S.A., Belgium
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# In addition, as a special exception, the copyright holders of this
+# program give permission to link the code of its release with the
+# OpenSSL project's "OpenSSL" library (or with modified versions of it
+# that use the same license as the "OpenSSL" library), and distribute
+# the linked executables. You must obey the GNU General Public License
+# in all respects for all of the code used other than "OpenSSL". If you
+# modify file(s) with this exception, you may extend this exception to
+# your version of the file(s), but you are not obligated to do so. If
+# you do not wish to do so, delete this exception statement from your
+# version. If you delete this exception statement from all source files
+# in the program, then also delete it here.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+
+##
+## Check whether the parent script sets the mandatory variables
+##
+
+if (NOT DEFINED ORTHANC_FRAMEWORK_SOURCE OR
+    (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "web" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" AND
+     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "path"))
+  message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_SOURCE must be set to \"system\", \"hg\", \"web\", \"archive\" or \"path\"")
+endif()
+
+
+##
+## Detection of the requested version
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+  if (NOT DEFINED ORTHANC_FRAMEWORK_VERSION)
+    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_VERSION must be set")
+  endif()
+
+  if (DEFINED ORTHANC_FRAMEWORK_MAJOR OR
+      DEFINED ORTHANC_FRAMEWORK_MINOR OR
+      DEFINED ORTHANC_FRAMEWORK_REVISION OR
+      DEFINED ORTHANC_FRAMEWORK_MD5)
+    message(FATAL_ERROR "Some internal variable has been set")
+  endif()
+
+  set(ORTHANC_FRAMEWORK_MD5 "")
+
+  if (NOT DEFINED ORTHANC_FRAMEWORK_BRANCH)
+    if (ORTHANC_FRAMEWORK_VERSION STREQUAL "mainline")
+      set(ORTHANC_FRAMEWORK_BRANCH "default")
+      set(ORTHANC_FRAMEWORK_MAJOR 999)
+      set(ORTHANC_FRAMEWORK_MINOR 999)
+      set(ORTHANC_FRAMEWORK_REVISION 999)
+
+    else()
+      set(ORTHANC_FRAMEWORK_BRANCH "Orthanc-${ORTHANC_FRAMEWORK_VERSION}")
+
+      set(RE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
+      string(REGEX REPLACE ${RE} "\\1" ORTHANC_FRAMEWORK_MAJOR ${ORTHANC_FRAMEWORK_VERSION})
+      string(REGEX REPLACE ${RE} "\\2" ORTHANC_FRAMEWORK_MINOR ${ORTHANC_FRAMEWORK_VERSION})
+      string(REGEX REPLACE ${RE} "\\3" ORTHANC_FRAMEWORK_REVISION ${ORTHANC_FRAMEWORK_VERSION})
+
+      if (NOT ORTHANC_FRAMEWORK_MAJOR MATCHES "^[0-9]+$" OR
+          NOT ORTHANC_FRAMEWORK_MINOR MATCHES "^[0-9]+$" OR
+          NOT ORTHANC_FRAMEWORK_REVISION MATCHES "^[0-9]+$")
+        message("Bad version of the Orthanc framework: ${ORTHANC_FRAMEWORK_VERSION}")
+      endif()
+
+      if (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.1")
+        set(ORTHANC_FRAMEWORK_MD5 "dac95bd6cf86fb19deaf4e612961f378")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.2")
+        set(ORTHANC_FRAMEWORK_MD5 "d0ccdf68e855d8224331f13774992750")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.4.0")
+        set(ORTHANC_FRAMEWORK_MD5 "81e15f34d97ac32bbd7d26e85698835a")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.4.1")
+        set(ORTHANC_FRAMEWORK_MD5 "9b6f6114264b17ed421b574cd6476127")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.4.2")
+        set(ORTHANC_FRAMEWORK_MD5 "d1ee84927dcf668e60eb5868d24b9394")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.0")
+        set(ORTHANC_FRAMEWORK_MD5 "4429d8d9dea4ff6648df80ec3c64d79e")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.1")
+        set(ORTHANC_FRAMEWORK_MD5 "099671538865e5da96208b37494d6718")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.2")
+        set(ORTHANC_FRAMEWORK_MD5 "8867050f3e9a1ce6157c1ea7a9433b1b")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.3")
+        set(ORTHANC_FRAMEWORK_MD5 "bf2f5ed1adb8b0fc5f10d278e68e1dfe")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.4")
+        set(ORTHANC_FRAMEWORK_MD5 "404baef5d4c43e7c5d9410edda8ef5a5")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.5")
+        set(ORTHANC_FRAMEWORK_MD5 "cfc437e0687ae4bd725fd93dc1f08bc4")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.6")
+        set(ORTHANC_FRAMEWORK_MD5 "3c29de1e289b5472342947168f0105c0")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.7")
+        set(ORTHANC_FRAMEWORK_MD5 "e1b76f01116d9b5d4ac8cc39980560e3")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.8")
+        set(ORTHANC_FRAMEWORK_MD5 "82323e8c49a667f658a3639ea4dbc336")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.6.0")
+        set(ORTHANC_FRAMEWORK_MD5 "eab428d6e53f61e847fa360bb17ebe25")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.6.1")
+        set(ORTHANC_FRAMEWORK_MD5 "3971f5de96ba71dc9d3f3690afeaa7c0")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.0")
+        set(ORTHANC_FRAMEWORK_MD5 "ce5f689e852b01d3672bd3d2f952a5ef")
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.1")
+        set(ORTHANC_FRAMEWORK_MD5 "3c171217f930abe80246997bdbcaf7cc")
+
+      # Below this point are development snapshots that were used to
+      # release some plugin, before an official release of the Orthanc
+      # framework was available. Here is the command to be used to
+      # generate a proper archive:
+      #
+      #   $ hg archive /tmp/Orthanc-`hg id -i | sed 's/\+//'`.tar.gz
+      #
+      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "ae0e3fd609df")
+        # DICOMweb 1.1 (framework pre-1.6.0)
+        set(ORTHANC_FRAMEWORK_MD5 "7e09e9b530a2f527854f0b782d7e0645")
+      endif()
+    endif()
+  endif()
+
+elseif (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system")
+  message("Using the Orthanc framework from a path of the filesystem. Assuming mainline version.")
+  set(ORTHANC_FRAMEWORK_MAJOR 999)
+  set(ORTHANC_FRAMEWORK_MINOR 999)
+  set(ORTHANC_FRAMEWORK_REVISION 999)
+endif()
+
+
+
+##
+## Detection of the third-party software
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg")
+  find_program(ORTHANC_FRAMEWORK_HG hg)
+  
+  if (${ORTHANC_FRAMEWORK_HG} MATCHES "ORTHANC_FRAMEWORK_HG-NOTFOUND")
+    message(FATAL_ERROR "Please install Mercurial")
+  endif()
+endif()
+
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+  if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+    find_program(ORTHANC_FRAMEWORK_7ZIP 7z 
+      PATHS 
+      "$ENV{ProgramFiles}/7-Zip"
+      "$ENV{ProgramW6432}/7-Zip"
+      )
+
+    if (${ORTHANC_FRAMEWORK_7ZIP} MATCHES "ORTHANC_FRAMEWORK_7ZIP-NOTFOUND")
+      message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)")
+    endif()
+
+  else()
+    find_program(ORTHANC_FRAMEWORK_TAR tar)
+    if (${ORTHANC_FRAMEWORK_TAR} MATCHES "ORTHANC_FRAMEWORK_TAR-NOTFOUND")
+      message(FATAL_ERROR "Please install the 'tar' package")
+    endif()
+  endif()
+endif()
+
+
+
+##
+## Case of the Orthanc framework specified as a path on the filesystem
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path")
+  if (NOT DEFINED ORTHANC_FRAMEWORK_ROOT)
+    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ROOT must provide the path to the sources of Orthanc")
+  endif()
+  
+  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT})
+    message(FATAL_ERROR "Non-existing directory: ${ORTHANC_FRAMEWORK_ROOT}")
+  endif()
+  
+  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
+    message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_FRAMEWORK_ROOT}")
+  endif()
+endif()
+
+
+
+##
+## Case of the Orthanc framework cloned using Mercurial
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg")
+  if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
+    message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
+  endif()
+
+  set(ORTHANC_ROOT ${CMAKE_BINARY_DIR}/orthanc)
+
+  if (EXISTS ${ORTHANC_ROOT})
+    message("Updating the Orthanc source repository using Mercurial")
+    execute_process(
+      COMMAND ${ORTHANC_FRAMEWORK_HG} pull
+      WORKING_DIRECTORY ${ORTHANC_ROOT}
+      RESULT_VARIABLE Failure
+      )    
+  else()
+    message("Forking the Orthanc source repository using Mercurial")
+    execute_process(
+      COMMAND ${ORTHANC_FRAMEWORK_HG} clone "https://hg.orthanc-server.com/orthanc/"
+      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+      RESULT_VARIABLE Failure
+      )    
+  endif()
+
+  if (Failure OR NOT EXISTS ${ORTHANC_ROOT})
+    message(FATAL_ERROR "Cannot fork the Orthanc repository")
+  endif()
+
+  message("Setting branch of the Orthanc repository to: ${ORTHANC_FRAMEWORK_BRANCH}")
+
+  execute_process(
+    COMMAND ${ORTHANC_FRAMEWORK_HG} update -c ${ORTHANC_FRAMEWORK_BRANCH}
+    WORKING_DIRECTORY ${ORTHANC_ROOT}
+    RESULT_VARIABLE Failure
+    )
+
+  if (Failure)
+    message(FATAL_ERROR "Error while running Mercurial")
+  endif()
+
+  unset(ORTHANC_FRAMEWORK_ROOT CACHE)
+  set(ORTHANC_FRAMEWORK_ROOT "${ORTHANC_ROOT}/OrthancFramework" CACHE
+    STRING "Path to the Orthanc framework source directory")
+
+  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
+    message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_ROOT}")
+  endif()
+
+  unset(ORTHANC_ROOT)
+endif()
+
+
+
+##
+## Case of the Orthanc framework provided as a source archive on the
+## filesystem
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive")
+  if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE)
+    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ARCHIVE must provide the path to the sources of Orthanc")
+  endif()
+endif()
+
+
+
+##
+## Case of the Orthanc framework downloaded from the Web
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+  if (DEFINED ORTHANC_FRAMEWORK_URL)
+    string(REGEX REPLACE "^.*/" "" ORTHANC_FRAMEMORK_FILENAME "${ORTHANC_FRAMEWORK_URL}")
+  else()
+    # Default case: Download from the official Web site
+    set(ORTHANC_FRAMEMORK_FILENAME Orthanc-${ORTHANC_FRAMEWORK_VERSION}.tar.gz)
+    set(ORTHANC_FRAMEWORK_URL "http://orthanc.osimis.io/ThirdPartyDownloads/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}")
+  endif()
+
+  set(ORTHANC_FRAMEWORK_ARCHIVE "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${ORTHANC_FRAMEMORK_FILENAME}")
+
+  if (NOT EXISTS "${ORTHANC_FRAMEWORK_ARCHIVE}")
+    if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
+      message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
+    endif()
+
+    message("Downloading: ${ORTHANC_FRAMEWORK_URL}")
+
+    file(DOWNLOAD
+      "${ORTHANC_FRAMEWORK_URL}" "${ORTHANC_FRAMEWORK_ARCHIVE}" 
+      SHOW_PROGRESS EXPECTED_MD5 "${ORTHANC_FRAMEWORK_MD5}"
+      TIMEOUT 60
+      INACTIVITY_TIMEOUT 60
+      )
+  else()
+    message("Using local copy of: ${ORTHANC_FRAMEWORK_URL}")
+  endif()  
+endif()
+
+
+
+
+##
+## Uncompressing the Orthanc framework, if it was retrieved from a
+## source archive on the filesystem, or from the official Web site
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
+    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
+
+  if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE OR
+      NOT DEFINED ORTHANC_FRAMEWORK_VERSION OR
+      NOT DEFINED ORTHANC_FRAMEWORK_MD5)
+    message(FATAL_ERROR "Internal error")
+  endif()
+
+  if (ORTHANC_FRAMEWORK_MD5 STREQUAL "")
+    message(FATAL_ERROR "Unknown release of Orthanc: ${ORTHANC_FRAMEWORK_VERSION}")
+  endif()
+
+  file(MD5 ${ORTHANC_FRAMEWORK_ARCHIVE} ActualMD5)
+
+  if (NOT "${ActualMD5}" STREQUAL "${ORTHANC_FRAMEWORK_MD5}")
+    message(FATAL_ERROR "The MD5 hash of the Orthanc archive is invalid: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+  endif()
+
+  set(ORTHANC_ROOT "${CMAKE_BINARY_DIR}/Orthanc-${ORTHANC_FRAMEWORK_VERSION}")
+
+  if (NOT IS_DIRECTORY "${ORTHANC_ROOT}")
+    if (NOT ORTHANC_FRAMEWORK_ARCHIVE MATCHES ".tar.gz$")
+      message(FATAL_ERROR "Archive should have the \".tar.gz\" extension: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+    endif()
+    
+    message("Uncompressing: ${ORTHANC_FRAMEWORK_ARCHIVE}")
+
+    if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+      # How to silently extract files using 7-zip
+      # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
+
+      execute_process(
+        COMMAND ${ORTHANC_FRAMEWORK_7ZIP} e -y ${ORTHANC_FRAMEWORK_ARCHIVE}
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        RESULT_VARIABLE Failure
+        OUTPUT_QUIET
+        )
+      
+      if (Failure)
+        message(FATAL_ERROR "Error while running the uncompression tool")
+      endif()
+
+      get_filename_component(TMP_FILENAME "${ORTHANC_FRAMEWORK_ARCHIVE}" NAME)
+      string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}")
+
+      execute_process(
+        COMMAND ${ORTHANC_FRAMEWORK_7ZIP} x -y ${TMP_FILENAME2}
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        RESULT_VARIABLE Failure
+        OUTPUT_QUIET
+        )
+
+    else()
+      execute_process(
+        COMMAND sh -c "${ORTHANC_FRAMEWORK_TAR} xfz ${ORTHANC_FRAMEWORK_ARCHIVE}"
+        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+        RESULT_VARIABLE Failure
+        )
+    endif()
+   
+    if (Failure)
+      message(FATAL_ERROR "Error while running the uncompression tool")
+    endif()
+
+    if (NOT IS_DIRECTORY "${ORTHANC_ROOT}")
+      message(FATAL_ERROR "The Orthanc framework was not uncompressed at the proper location. Check the CMake instructions.")
+    endif()
+  endif()
+
+  unset(ORTHANC_FRAMEWORK_ROOT CACHE)
+  set(ORTHANC_FRAMEWORK_ROOT "${ORTHANC_ROOT}/OrthancFramework" CACHE
+    STRING "Path to the Orthanc framework source directory")
+
+  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
+    message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_ROOT}")
+  endif()
+
+  unset(ORTHANC_ROOT)
+endif()
+
+
+
+##
+## Case of the Orthanc framework installed as a shared library in a
+## GNU/Linux distribution (typically Debian). New in Orthanc 1.7.2.
+##
+
+if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system")
+  set(ORTHANC_FRAMEWORK_LIBDIR "" CACHE PATH "")
+
+  if (CMAKE_SYSTEM_NAME STREQUAL "Windows" AND
+      CMAKE_COMPILER_IS_GNUCXX) # MinGW
+    set(DYNAMIC_MINGW_STDLIB ON)   # Disable static linking against libc (to throw exceptions)
+    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++")
+    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
+  endif()
+  
+  include(CheckIncludeFile)
+  include(CheckIncludeFileCXX)
+  include(FindPythonInterp)
+  include(${CMAKE_CURRENT_LIST_DIR}/Compiler.cmake)
+  include(${CMAKE_CURRENT_LIST_DIR}/DownloadPackage.cmake)
+  include(${CMAKE_CURRENT_LIST_DIR}/AutoGeneratedCode.cmake)
+  set(EMBED_RESOURCES_PYTHON ${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py)
+
+  if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" OR
+      ORTHANC_FRAMEWORK_STATIC)
+    include_directories(${ORTHANC_FRAMEWORK_ROOT}/..)
+  else()
+    # Look for mandatory dependency JsonCpp (cf. JsonCppConfiguration.cmake)
+    find_path(JSONCPP_INCLUDE_DIR json/reader.h
+      /usr/include/jsoncpp
+      /usr/local/include/jsoncpp
+      )
+
+    message("JsonCpp include dir: ${JSONCPP_INCLUDE_DIR}")
+    include_directories(${JSONCPP_INCLUDE_DIR})
+    link_libraries(jsoncpp)
+
+    CHECK_INCLUDE_FILE_CXX(${JSONCPP_INCLUDE_DIR}/json/reader.h HAVE_JSONCPP_H)
+    if (NOT HAVE_JSONCPP_H)
+      message(FATAL_ERROR "Please install the libjsoncpp-dev package")
+    endif()
+
+    # Look for mandatory dependency Boost (cf. BoostConfiguration.cmake)
+    include(FindBoost)
+    find_package(Boost COMPONENTS filesystem thread system date_time regex)
+
+    if (NOT Boost_FOUND)
+      message(FATAL_ERROR "Unable to locate Boost on this system")
+    endif()
+    
+    include_directories(${Boost_INCLUDE_DIRS})
+    link_libraries(${Boost_LIBRARIES})
+
+    # Optional component - Lua
+    if (ENABLE_LUA)
+      include(FindLua)
+
+      if (NOT LUA_FOUND)
+        message(FATAL_ERROR "Please install the liblua-dev package")
+      endif()
+
+      include_directories(${LUA_INCLUDE_DIR})
+      link_libraries(${LUA_LIBRARIES})
+    endif()
+
+    # Optional component - SQLite
+    if (ENABLE_SQLITE)    
+      CHECK_INCLUDE_FILE(sqlite3.h HAVE_SQLITE_H)
+      if (NOT HAVE_SQLITE_H)
+        message(FATAL_ERROR "Please install the libsqlite3-dev package")
+      endif()
+      link_libraries(sqlite3)
+    endif()
+
+    # Optional component - Pugixml
+    if (ENABLE_PUGIXML)
+      CHECK_INCLUDE_FILE_CXX(pugixml.hpp HAVE_PUGIXML_H)
+      if (NOT HAVE_PUGIXML_H)
+        message(FATAL_ERROR "Please install the libpugixml-dev package")
+      endif()      
+      link_libraries(pugixml)
+    endif()
+
+    # Optional component - DCMTK
+    if (ENABLE_DCMTK)
+      include(FindDCMTK)
+      include_directories(${DCMTK_INCLUDE_DIRS})
+      link_libraries(${DCMTK_LIBRARIES})
+    endif()
+  endif()
+
+  # Look for Orthanc framework shared library
+  include(CheckCXXSymbolExists)
+
+  if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
+    set(ORTHANC_FRAMEWORK_INCLUDE_DIR ${ORTHANC_FRAMEWORK_ROOT})
+  else()
+    find_path(ORTHANC_FRAMEWORK_INCLUDE_DIR OrthancFramework.h
+      /usr/include/orthanc-framework
+      /usr/local/include/orthanc-framework
+      ${ORTHANC_FRAMEWORK_ROOT}
+      )
+  endif()
+
+  if (${ORTHANC_FRAMEWORK_INCLUDE_DIR} STREQUAL "ORTHANC_FRAMEWORK_INCLUDE_DIR-NOTFOUND")
+    message(FATAL_ERROR "Cannot locate the OrthancFramework.h header")
+  endif()
+  
+  message("Orthanc framework include dir: ${ORTHANC_FRAMEWORK_INCLUDE_DIR}")
+  include_directories(${ORTHANC_FRAMEWORK_INCLUDE_DIR})
+  
+  if ("${ORTHANC_FRAMEWORK_LIBDIR}" STREQUAL "")
+    set(ORTHANC_FRAMEWORK_LIBRARIES OrthancFramework)
+  else()
+    if (MSVC)
+      set(Suffix ".lib")
+      set(Prefix "")
+    else()
+      list(GET CMAKE_FIND_LIBRARY_PREFIXES 0 Prefix)
+      list(GET CMAKE_FIND_LIBRARY_SUFFIXES 0 Suffix)
+    endif()
+    set(ORTHANC_FRAMEWORK_LIBRARIES ${ORTHANC_FRAMEWORK_LIBDIR}/${Prefix}OrthancFramework${Suffix})
+  endif()
+
+  set(CMAKE_REQUIRED_INCLUDES "${ORTHANC_FRAMEWORK_INCLUDE_DIR}")
+  set(CMAKE_REQUIRED_LIBRARIES "${ORTHANC_FRAMEWORK_LIBRARIES}")
+  
+  check_cxx_symbol_exists("Orthanc::InitializeFramework" "OrthancFramework.h" HAVE_ORTHANC_FRAMEWORK)
+  if (NOT HAVE_ORTHANC_FRAMEWORK)
+    message(FATAL_ERROR "Cannot find the Orthanc framework")
+  endif()
+
+  if (NOT "${ORTHANC_FRAMEWORK_ROOT}" STREQUAL "")
+    include_directories(${ORTHANC_FRAMEWORK_ROOT})
+  endif()
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/CMake/DownloadPackage.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,258 @@
+macro(GetUrlFilename TargetVariable Url)
+  string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${Url}")
+endmacro()
+
+
+macro(GetUrlExtension TargetVariable Url)
+  #string(REGEX REPLACE "^.*/[^.]*\\." "" TMP "${Url}")
+  string(REGEX REPLACE "^.*\\." "" TMP "${Url}")
+  string(TOLOWER "${TMP}" "${TargetVariable}")
+endmacro()
+
+
+
+##
+## Setup the patch command-line tool
+##
+
+if (NOT ORTHANC_DISABLE_PATCH)
+  if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+    set(PATCH_EXECUTABLE ${CMAKE_CURRENT_LIST_DIR}/../ThirdParty/patch/patch.exe)
+    if (NOT EXISTS ${PATCH_EXECUTABLE})
+      message(FATAL_ERROR "Unable to find the patch.exe tool that is shipped with Orthanc")
+    endif()
+
+  else ()
+    find_program(PATCH_EXECUTABLE patch)
+    if (${PATCH_EXECUTABLE} MATCHES "PATCH_EXECUTABLE-NOTFOUND")
+      message(FATAL_ERROR "Please install the 'patch' standard command-line tool")
+    endif()
+  endif()
+endif()
+
+
+
+##
+## Check the existence of the required decompression tools
+##
+
+if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+  find_program(ZIP_EXECUTABLE 7z 
+    PATHS 
+    "$ENV{ProgramFiles}/7-Zip"
+    "$ENV{ProgramW6432}/7-Zip"
+    )
+
+  if (${ZIP_EXECUTABLE} MATCHES "ZIP_EXECUTABLE-NOTFOUND")
+    message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)")
+  endif()
+
+else()
+  find_program(UNZIP_EXECUTABLE unzip)
+  if (${UNZIP_EXECUTABLE} MATCHES "UNZIP_EXECUTABLE-NOTFOUND")
+    message(FATAL_ERROR "Please install the 'unzip' package")
+  endif()
+
+  find_program(TAR_EXECUTABLE tar)
+  if (${TAR_EXECUTABLE} MATCHES "TAR_EXECUTABLE-NOTFOUND")
+    message(FATAL_ERROR "Please install the 'tar' package")
+  endif()
+
+  find_program(GUNZIP_EXECUTABLE gunzip)
+  if (${GUNZIP_EXECUTABLE} MATCHES "GUNZIP_EXECUTABLE-NOTFOUND")
+    message(FATAL_ERROR "Please install the 'gzip' package")
+  endif()
+endif()
+
+
+macro(DownloadFile MD5 Url)
+  GetUrlFilename(TMP_FILENAME "${Url}")
+
+  set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}")
+  if (NOT EXISTS "${TMP_PATH}")
+    message("Downloading ${Url}")
+
+    # This fixes issue 6: "I think cmake shouldn't download the
+    # packages which are not in the system, it should stop and let
+    # user know."
+    # https://code.google.com/p/orthanc/issues/detail?id=6
+    if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
+      message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
+    endif()
+
+    if ("${MD5}" STREQUAL "no-check")
+      message(WARNING "Not checking the MD5 of: ${Url}")
+      file(DOWNLOAD "${Url}" "${TMP_PATH}"
+        SHOW_PROGRESS TIMEOUT 300 INACTIVITY_TIMEOUT 60
+        STATUS Failure)
+    else()
+      file(DOWNLOAD "${Url}" "${TMP_PATH}"
+        SHOW_PROGRESS TIMEOUT 300 INACTIVITY_TIMEOUT 60
+        EXPECTED_MD5 "${MD5}" STATUS Failure)
+    endif()
+
+    list(GET Failure 0 Status)
+    if (NOT Status EQUAL 0)
+      message(FATAL_ERROR "Cannot download file: ${Url}")
+    endif()
+    
+  else()
+    message("Using local copy of ${Url}")
+
+    if ("${MD5}" STREQUAL "no-check")
+      message(WARNING "Not checking the MD5 of: ${Url}")
+    else()
+      file(MD5 ${TMP_PATH} ActualMD5)
+      if (NOT "${ActualMD5}" STREQUAL "${MD5}")
+        message(FATAL_ERROR "The MD5 hash of a previously download file is invalid: ${TMP_PATH}")
+      endif()
+    endif()
+  endif()
+endmacro()
+
+
+macro(DownloadPackage MD5 Url TargetDirectory)
+  if (NOT IS_DIRECTORY "${TargetDirectory}")
+    DownloadFile("${MD5}" "${Url}")
+    
+    GetUrlExtension(TMP_EXTENSION "${Url}")
+    #message(${TMP_EXTENSION})
+    message("Uncompressing ${TMP_FILENAME}")
+
+    if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+      # How to silently extract files using 7-zip
+      # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
+
+      if (("${TMP_EXTENSION}" STREQUAL "gz") OR 
+          ("${TMP_EXTENSION}" STREQUAL "tgz") OR
+          ("${TMP_EXTENSION}" STREQUAL "xz"))
+        execute_process(
+          COMMAND ${ZIP_EXECUTABLE} e -y ${TMP_PATH}
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          OUTPUT_QUIET
+          )
+
+        if (Failure)
+          message(FATAL_ERROR "Error while running the uncompression tool")
+        endif()
+
+        if ("${TMP_EXTENSION}" STREQUAL "tgz")
+          string(REGEX REPLACE ".tgz$" ".tar" TMP_FILENAME2 "${TMP_FILENAME}")
+        elseif ("${TMP_EXTENSION}" STREQUAL "gz")
+          string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}")
+        elseif ("${TMP_EXTENSION}" STREQUAL "xz")
+          string(REGEX REPLACE ".xz" "" TMP_FILENAME2 "${TMP_FILENAME}")
+        endif()
+
+        execute_process(
+          COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_FILENAME2}
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          OUTPUT_QUIET
+          )
+      elseif ("${TMP_EXTENSION}" STREQUAL "zip")
+        execute_process(
+          COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_PATH}
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          OUTPUT_QUIET
+          )
+      else()
+        message(FATAL_ERROR "Unsupported package extension: ${TMP_EXTENSION}")
+      endif()
+
+    else()
+      if ("${TMP_EXTENSION}" STREQUAL "zip")
+        execute_process(
+          COMMAND sh -c "${UNZIP_EXECUTABLE} -q ${TMP_PATH}"
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+        )
+      elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz"))
+        #message("tar xvfz ${TMP_PATH}")
+        execute_process(
+          COMMAND sh -c "${TAR_EXECUTABLE} xfz ${TMP_PATH}"
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          )
+      elseif ("${TMP_EXTENSION}" STREQUAL "bz2")
+        execute_process(
+          COMMAND sh -c "${TAR_EXECUTABLE} xfj ${TMP_PATH}"
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          )
+      elseif ("${TMP_EXTENSION}" STREQUAL "xz")
+        execute_process(
+          COMMAND sh -c "${TAR_EXECUTABLE} xf ${TMP_PATH}"
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          )
+      else()
+        message(FATAL_ERROR "Unsupported package extension: ${TMP_EXTENSION}")
+      endif()
+    endif()
+   
+    if (Failure)
+      message(FATAL_ERROR "Error while running the uncompression tool")
+    endif()
+
+    if (NOT IS_DIRECTORY "${TargetDirectory}")
+      message(FATAL_ERROR "The package was not uncompressed at the proper location. Check the CMake instructions.")
+    endif()
+  endif()
+endmacro()
+
+
+
+macro(DownloadCompressedFile MD5 Url TargetFile)
+  if (NOT EXISTS "${TargetFile}")
+    DownloadFile("${MD5}" "${Url}")
+    
+    GetUrlExtension(TMP_EXTENSION "${Url}")
+    #message(${TMP_EXTENSION})
+    message("Uncompressing ${TMP_FILENAME}")
+
+    if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
+      # How to silently extract files using 7-zip
+      # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
+
+      if ("${TMP_EXTENSION}" STREQUAL "gz")
+        execute_process(
+          # "-so" writes uncompressed file to stdout
+          COMMAND ${ZIP_EXECUTABLE} e -so -y ${TMP_PATH}
+          OUTPUT_FILE "${TargetFile}"
+          WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+          RESULT_VARIABLE Failure
+          OUTPUT_QUIET
+          )
+
+        if (Failure)
+          message(FATAL_ERROR "Error while running the uncompression tool")
+        endif()
+
+      else()
+        message(FATAL_ERROR "Unsupported file extension: ${TMP_EXTENSION}")
+      endif()
+
+    else()
+      if ("${TMP_EXTENSION}" STREQUAL "gz")
+        execute_process(
+          COMMAND sh -c "${GUNZIP_EXECUTABLE} -c ${TMP_PATH}"
+          OUTPUT_FILE "${TargetFile}"
+          RESULT_VARIABLE Failure
+          )
+      else()
+        message(FATAL_ERROR "Unsupported file extension: ${TMP_EXTENSION}")
+      endif()
+    endif()
+   
+    if (Failure)
+      message(FATAL_ERROR "Error while running the uncompression tool")
+    endif()
+
+    if (NOT EXISTS "${TargetFile}")
+      message(FATAL_ERROR "The file was not uncompressed at the proper location. Check the CMake instructions.")
+    endif()
+  endif()
+endmacro()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/CMake/GoogleTestConfiguration.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,69 @@
+if (USE_GOOGLE_TEST_DEBIAN_PACKAGE)
+  find_path(GOOGLE_TEST_DEBIAN_SOURCES_DIR
+    NAMES src/gtest-all.cc
+    PATHS
+    ${CROSSTOOL_NG_IMAGE}/usr/src/gtest
+    ${CROSSTOOL_NG_IMAGE}/usr/src/googletest/googletest
+    PATH_SUFFIXES src
+    )
+
+  find_path(GOOGLE_TEST_DEBIAN_INCLUDE_DIR
+    NAMES gtest.h
+    PATHS
+    ${CROSSTOOL_NG_IMAGE}/usr/include/gtest
+    )
+
+  message("Path to the Debian Google Test sources: ${GOOGLE_TEST_DEBIAN_SOURCES_DIR}")
+  message("Path to the Debian Google Test includes: ${GOOGLE_TEST_DEBIAN_INCLUDE_DIR}")
+
+  set(GOOGLE_TEST_SOURCES
+    ${GOOGLE_TEST_DEBIAN_SOURCES_DIR}/src/gtest-all.cc
+    )
+
+  include_directories(${GOOGLE_TEST_DEBIAN_SOURCES_DIR})
+
+  if (NOT EXISTS ${GOOGLE_TEST_SOURCES} OR
+      NOT EXISTS ${GOOGLE_TEST_DEBIAN_INCLUDE_DIR}/gtest.h)
+    message(FATAL_ERROR "Please install the libgtest-dev package")
+  endif()
+
+elseif (STATIC_BUILD OR NOT USE_SYSTEM_GOOGLE_TEST)
+  set(GOOGLE_TEST_SOURCES_DIR ${CMAKE_BINARY_DIR}/googletest-release-1.8.1)
+  set(GOOGLE_TEST_URL "http://orthanc.osimis.io/ThirdPartyDownloads/gtest-1.8.1.tar.gz")
+  set(GOOGLE_TEST_MD5 "2e6fbeb6a91310a16efe181886c59596")
+
+  DownloadPackage(${GOOGLE_TEST_MD5} ${GOOGLE_TEST_URL} "${GOOGLE_TEST_SOURCES_DIR}")
+
+  include_directories(
+    ${GOOGLE_TEST_SOURCES_DIR}/googletest
+    ${GOOGLE_TEST_SOURCES_DIR}/googletest/include
+    ${GOOGLE_TEST_SOURCES_DIR}
+    )
+
+  set(GOOGLE_TEST_SOURCES
+    ${GOOGLE_TEST_SOURCES_DIR}/googletest/src/gtest-all.cc
+    )
+
+  # https://code.google.com/p/googletest/issues/detail?id=412
+  if (MSVC) # VS2012 does not support tuples correctly yet
+    add_definitions(/D _VARIADIC_MAX=10)
+  endif()
+  
+  if ("${CMAKE_SYSTEM_VERSION}" STREQUAL "LinuxStandardBase")
+    add_definitions(-DGTEST_HAS_CLONE=0)
+  endif()
+  
+  source_group(ThirdParty\\GoogleTest REGULAR_EXPRESSION ${GOOGLE_TEST_SOURCES_DIR}/.*)
+
+else()
+  include(FindGTest)
+  if (NOT GTEST_FOUND)
+    message(FATAL_ERROR "Unable to find GoogleTest")
+  endif()
+
+  include_directories(${GTEST_INCLUDE_DIRS})
+
+  # The variable GTEST_LIBRARIES contains the shared library of
+  # Google Test, create an alias for more uniformity
+  set(GOOGLE_TEST_LIBRARIES ${GTEST_LIBRARIES})
+endif()
--- a/Resources/Orthanc/DownloadOrthancFramework.cmake	Wed Jul 01 17:13:38 2020 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,532 +0,0 @@
-# Orthanc - A Lightweight, RESTful DICOM Store
-# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
-# Department, University Hospital of Liege, Belgium
-# Copyright (C) 2017-2020 Osimis S.A., Belgium
-#
-# This program is free software: you can redistribute it and/or
-# modify it under the terms of the GNU General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or (at your option) any later version.
-#
-# In addition, as a special exception, the copyright holders of this
-# program give permission to link the code of its release with the
-# OpenSSL project's "OpenSSL" library (or with modified versions of it
-# that use the same license as the "OpenSSL" library), and distribute
-# the linked executables. You must obey the GNU General Public License
-# in all respects for all of the code used other than "OpenSSL". If you
-# modify file(s) with this exception, you may extend this exception to
-# your version of the file(s), but you are not obligated to do so. If
-# you do not wish to do so, delete this exception statement from your
-# version. If you delete this exception statement from all source files
-# in the program, then also delete it here.
-# 
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-
-
-##
-## Check whether the parent script sets the mandatory variables
-##
-
-if (NOT DEFINED ORTHANC_FRAMEWORK_SOURCE OR
-    (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system" AND
-     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" AND
-     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "web" AND
-     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" AND
-     NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "path"))
-  message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_SOURCE must be set to \"system\", \"hg\", \"web\", \"archive\" or \"path\"")
-endif()
-
-
-##
-## Detection of the requested version
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg" OR
-    ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
-    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
-  if (NOT DEFINED ORTHANC_FRAMEWORK_VERSION)
-    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_VERSION must be set")
-  endif()
-
-  if (DEFINED ORTHANC_FRAMEWORK_MAJOR OR
-      DEFINED ORTHANC_FRAMEWORK_MINOR OR
-      DEFINED ORTHANC_FRAMEWORK_REVISION OR
-      DEFINED ORTHANC_FRAMEWORK_MD5)
-    message(FATAL_ERROR "Some internal variable has been set")
-  endif()
-
-  set(ORTHANC_FRAMEWORK_MD5 "")
-
-  if (NOT DEFINED ORTHANC_FRAMEWORK_BRANCH)
-    if (ORTHANC_FRAMEWORK_VERSION STREQUAL "mainline")
-      set(ORTHANC_FRAMEWORK_BRANCH "default")
-      set(ORTHANC_FRAMEWORK_MAJOR 999)
-      set(ORTHANC_FRAMEWORK_MINOR 999)
-      set(ORTHANC_FRAMEWORK_REVISION 999)
-
-    else()
-      set(ORTHANC_FRAMEWORK_BRANCH "Orthanc-${ORTHANC_FRAMEWORK_VERSION}")
-
-      set(RE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
-      string(REGEX REPLACE ${RE} "\\1" ORTHANC_FRAMEWORK_MAJOR ${ORTHANC_FRAMEWORK_VERSION})
-      string(REGEX REPLACE ${RE} "\\2" ORTHANC_FRAMEWORK_MINOR ${ORTHANC_FRAMEWORK_VERSION})
-      string(REGEX REPLACE ${RE} "\\3" ORTHANC_FRAMEWORK_REVISION ${ORTHANC_FRAMEWORK_VERSION})
-
-      if (NOT ORTHANC_FRAMEWORK_MAJOR MATCHES "^[0-9]+$" OR
-          NOT ORTHANC_FRAMEWORK_MINOR MATCHES "^[0-9]+$" OR
-          NOT ORTHANC_FRAMEWORK_REVISION MATCHES "^[0-9]+$")
-        message("Bad version of the Orthanc framework: ${ORTHANC_FRAMEWORK_VERSION}")
-      endif()
-
-      if (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.1")
-        set(ORTHANC_FRAMEWORK_MD5 "dac95bd6cf86fb19deaf4e612961f378")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.3.2")
-        set(ORTHANC_FRAMEWORK_MD5 "d0ccdf68e855d8224331f13774992750")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.4.0")
-        set(ORTHANC_FRAMEWORK_MD5 "81e15f34d97ac32bbd7d26e85698835a")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.4.1")
-        set(ORTHANC_FRAMEWORK_MD5 "9b6f6114264b17ed421b574cd6476127")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.4.2")
-        set(ORTHANC_FRAMEWORK_MD5 "d1ee84927dcf668e60eb5868d24b9394")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.0")
-        set(ORTHANC_FRAMEWORK_MD5 "4429d8d9dea4ff6648df80ec3c64d79e")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.1")
-        set(ORTHANC_FRAMEWORK_MD5 "099671538865e5da96208b37494d6718")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.2")
-        set(ORTHANC_FRAMEWORK_MD5 "8867050f3e9a1ce6157c1ea7a9433b1b")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.3")
-        set(ORTHANC_FRAMEWORK_MD5 "bf2f5ed1adb8b0fc5f10d278e68e1dfe")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.4")
-        set(ORTHANC_FRAMEWORK_MD5 "404baef5d4c43e7c5d9410edda8ef5a5")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.5")
-        set(ORTHANC_FRAMEWORK_MD5 "cfc437e0687ae4bd725fd93dc1f08bc4")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.6")
-        set(ORTHANC_FRAMEWORK_MD5 "3c29de1e289b5472342947168f0105c0")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.7")
-        set(ORTHANC_FRAMEWORK_MD5 "e1b76f01116d9b5d4ac8cc39980560e3")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.5.8")
-        set(ORTHANC_FRAMEWORK_MD5 "82323e8c49a667f658a3639ea4dbc336")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.6.0")
-        set(ORTHANC_FRAMEWORK_MD5 "eab428d6e53f61e847fa360bb17ebe25")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.6.1")
-        set(ORTHANC_FRAMEWORK_MD5 "3971f5de96ba71dc9d3f3690afeaa7c0")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.0")
-        set(ORTHANC_FRAMEWORK_MD5 "ce5f689e852b01d3672bd3d2f952a5ef")
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "1.7.1")
-        set(ORTHANC_FRAMEWORK_MD5 "3c171217f930abe80246997bdbcaf7cc")
-
-      # Below this point are development snapshots that were used to
-      # release some plugin, before an official release of the Orthanc
-      # framework was available. Here is the command to be used to
-      # generate a proper archive:
-      #
-      #   $ hg archive /tmp/Orthanc-`hg id -i | sed 's/\+//'`.tar.gz
-      #
-      elseif (ORTHANC_FRAMEWORK_VERSION STREQUAL "ae0e3fd609df")
-        # DICOMweb 1.1 (framework pre-1.6.0)
-        set(ORTHANC_FRAMEWORK_MD5 "7e09e9b530a2f527854f0b782d7e0645")
-      endif()
-    endif()
-  endif()
-
-elseif (NOT ORTHANC_FRAMEWORK_SOURCE STREQUAL "system")
-  message("Using the Orthanc framework from a path of the filesystem. Assuming mainline version.")
-  set(ORTHANC_FRAMEWORK_MAJOR 999)
-  set(ORTHANC_FRAMEWORK_MINOR 999)
-  set(ORTHANC_FRAMEWORK_REVISION 999)
-endif()
-
-
-
-##
-## Detection of the third-party software
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg")
-  find_program(ORTHANC_FRAMEWORK_HG hg)
-  
-  if (${ORTHANC_FRAMEWORK_HG} MATCHES "ORTHANC_FRAMEWORK_HG-NOTFOUND")
-    message(FATAL_ERROR "Please install Mercurial")
-  endif()
-endif()
-
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
-    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
-  if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
-    find_program(ORTHANC_FRAMEWORK_7ZIP 7z 
-      PATHS 
-      "$ENV{ProgramFiles}/7-Zip"
-      "$ENV{ProgramW6432}/7-Zip"
-      )
-
-    if (${ORTHANC_FRAMEWORK_7ZIP} MATCHES "ORTHANC_FRAMEWORK_7ZIP-NOTFOUND")
-      message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)")
-    endif()
-
-  else()
-    find_program(ORTHANC_FRAMEWORK_TAR tar)
-    if (${ORTHANC_FRAMEWORK_TAR} MATCHES "ORTHANC_FRAMEWORK_TAR-NOTFOUND")
-      message(FATAL_ERROR "Please install the 'tar' package")
-    endif()
-  endif()
-endif()
-
-
-
-##
-## Case of the Orthanc framework specified as a path on the filesystem
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "path")
-  if (NOT DEFINED ORTHANC_FRAMEWORK_ROOT)
-    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ROOT must provide the path to the sources of Orthanc")
-  endif()
-  
-  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT})
-    message(FATAL_ERROR "Non-existing directory: ${ORTHANC_FRAMEWORK_ROOT}")
-  endif()
-  
-  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
-    message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_FRAMEWORK_ROOT}")
-  endif()
-endif()
-
-
-
-##
-## Case of the Orthanc framework cloned using Mercurial
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "hg")
-  if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
-    message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
-  endif()
-
-  set(ORTHANC_ROOT ${CMAKE_BINARY_DIR}/orthanc)
-
-  if (EXISTS ${ORTHANC_ROOT})
-    message("Updating the Orthanc source repository using Mercurial")
-    execute_process(
-      COMMAND ${ORTHANC_FRAMEWORK_HG} pull
-      WORKING_DIRECTORY ${ORTHANC_ROOT}
-      RESULT_VARIABLE Failure
-      )    
-  else()
-    message("Forking the Orthanc source repository using Mercurial")
-    execute_process(
-      COMMAND ${ORTHANC_FRAMEWORK_HG} clone "https://hg.orthanc-server.com/orthanc/"
-      WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-      RESULT_VARIABLE Failure
-      )    
-  endif()
-
-  if (Failure OR NOT EXISTS ${ORTHANC_ROOT})
-    message(FATAL_ERROR "Cannot fork the Orthanc repository")
-  endif()
-
-  message("Setting branch of the Orthanc repository to: ${ORTHANC_FRAMEWORK_BRANCH}")
-
-  execute_process(
-    COMMAND ${ORTHANC_FRAMEWORK_HG} update -c ${ORTHANC_FRAMEWORK_BRANCH}
-    WORKING_DIRECTORY ${ORTHANC_ROOT}
-    RESULT_VARIABLE Failure
-    )
-
-  if (Failure)
-    message(FATAL_ERROR "Error while running Mercurial")
-  endif()
-
-  unset(ORTHANC_FRAMEWORK_ROOT CACHE)
-  set(ORTHANC_FRAMEWORK_ROOT "${ORTHANC_ROOT}/OrthancFramework" CACHE
-    STRING "Path to the Orthanc framework source directory")
-
-  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
-    message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_ROOT}")
-  endif()
-
-  unset(ORTHANC_ROOT)
-endif()
-
-
-
-##
-## Case of the Orthanc framework provided as a source archive on the
-## filesystem
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive")
-  if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE)
-    message(FATAL_ERROR "The variable ORTHANC_FRAMEWORK_ARCHIVE must provide the path to the sources of Orthanc")
-  endif()
-endif()
-
-
-
-##
-## Case of the Orthanc framework downloaded from the Web
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
-  if (DEFINED ORTHANC_FRAMEWORK_URL)
-    string(REGEX REPLACE "^.*/" "" ORTHANC_FRAMEMORK_FILENAME "${ORTHANC_FRAMEWORK_URL}")
-  else()
-    # Default case: Download from the official Web site
-    set(ORTHANC_FRAMEMORK_FILENAME Orthanc-${ORTHANC_FRAMEWORK_VERSION}.tar.gz)
-    set(ORTHANC_FRAMEWORK_URL "http://orthanc.osimis.io/ThirdPartyDownloads/orthanc-framework/${ORTHANC_FRAMEMORK_FILENAME}")
-  endif()
-
-  set(ORTHANC_FRAMEWORK_ARCHIVE "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${ORTHANC_FRAMEMORK_FILENAME}")
-
-  if (NOT EXISTS "${ORTHANC_FRAMEWORK_ARCHIVE}")
-    if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS)
-      message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON")
-    endif()
-
-    message("Downloading: ${ORTHANC_FRAMEWORK_URL}")
-
-    file(DOWNLOAD
-      "${ORTHANC_FRAMEWORK_URL}" "${ORTHANC_FRAMEWORK_ARCHIVE}" 
-      SHOW_PROGRESS EXPECTED_MD5 "${ORTHANC_FRAMEWORK_MD5}"
-      TIMEOUT 60
-      INACTIVITY_TIMEOUT 60
-      )
-  else()
-    message("Using local copy of: ${ORTHANC_FRAMEWORK_URL}")
-  endif()  
-endif()
-
-
-
-
-##
-## Uncompressing the Orthanc framework, if it was retrieved from a
-## source archive on the filesystem, or from the official Web site
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "archive" OR
-    ORTHANC_FRAMEWORK_SOURCE STREQUAL "web")
-
-  if (NOT DEFINED ORTHANC_FRAMEWORK_ARCHIVE OR
-      NOT DEFINED ORTHANC_FRAMEWORK_VERSION OR
-      NOT DEFINED ORTHANC_FRAMEWORK_MD5)
-    message(FATAL_ERROR "Internal error")
-  endif()
-
-  if (ORTHANC_FRAMEWORK_MD5 STREQUAL "")
-    message(FATAL_ERROR "Unknown release of Orthanc: ${ORTHANC_FRAMEWORK_VERSION}")
-  endif()
-
-  file(MD5 ${ORTHANC_FRAMEWORK_ARCHIVE} ActualMD5)
-
-  if (NOT "${ActualMD5}" STREQUAL "${ORTHANC_FRAMEWORK_MD5}")
-    message(FATAL_ERROR "The MD5 hash of the Orthanc archive is invalid: ${ORTHANC_FRAMEWORK_ARCHIVE}")
-  endif()
-
-  set(ORTHANC_ROOT "${CMAKE_BINARY_DIR}/Orthanc-${ORTHANC_FRAMEWORK_VERSION}")
-
-  if (NOT IS_DIRECTORY "${ORTHANC_ROOT}")
-    if (NOT ORTHANC_FRAMEWORK_ARCHIVE MATCHES ".tar.gz$")
-      message(FATAL_ERROR "Archive should have the \".tar.gz\" extension: ${ORTHANC_FRAMEWORK_ARCHIVE}")
-    endif()
-    
-    message("Uncompressing: ${ORTHANC_FRAMEWORK_ARCHIVE}")
-
-    if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows")
-      # How to silently extract files using 7-zip
-      # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly
-
-      execute_process(
-        COMMAND ${ORTHANC_FRAMEWORK_7ZIP} e -y ${ORTHANC_FRAMEWORK_ARCHIVE}
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        OUTPUT_QUIET
-        )
-      
-      if (Failure)
-        message(FATAL_ERROR "Error while running the uncompression tool")
-      endif()
-
-      get_filename_component(TMP_FILENAME "${ORTHANC_FRAMEWORK_ARCHIVE}" NAME)
-      string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}")
-
-      execute_process(
-        COMMAND ${ORTHANC_FRAMEWORK_7ZIP} x -y ${TMP_FILENAME2}
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        OUTPUT_QUIET
-        )
-
-    else()
-      execute_process(
-        COMMAND sh -c "${ORTHANC_FRAMEWORK_TAR} xfz ${ORTHANC_FRAMEWORK_ARCHIVE}"
-        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-        RESULT_VARIABLE Failure
-        )
-    endif()
-   
-    if (Failure)
-      message(FATAL_ERROR "Error while running the uncompression tool")
-    endif()
-
-    if (NOT IS_DIRECTORY "${ORTHANC_ROOT}")
-      message(FATAL_ERROR "The Orthanc framework was not uncompressed at the proper location. Check the CMake instructions.")
-    endif()
-  endif()
-
-  unset(ORTHANC_FRAMEWORK_ROOT CACHE)
-  set(ORTHANC_FRAMEWORK_ROOT "${ORTHANC_ROOT}/OrthancFramework" CACHE
-    STRING "Path to the Orthanc framework source directory")
-
-  if (NOT EXISTS ${ORTHANC_FRAMEWORK_ROOT}/Resources/CMake/OrthancFrameworkParameters.cmake)
-    message(FATAL_ERROR "Directory not containing the source code of the Orthanc framework: ${ORTHANC_ROOT}")
-  endif()
-
-  unset(ORTHANC_ROOT)
-endif()
-
-
-
-##
-## Case of the Orthanc framework installed as a shared library in a
-## GNU/Linux distribution (typically Debian)
-##
-
-if (ORTHANC_FRAMEWORK_SOURCE STREQUAL "system")
-  set(ORTHANC_FRAMEWORK_LIBDIR "" CACHE PATH "")
-
-  if (CMAKE_SYSTEM_NAME STREQUAL "Windows" AND
-      CMAKE_COMPILER_IS_GNUCXX) # MinGW
-    set(DYNAMIC_MINGW_STDLIB ON)   # Disable static linking against libc (to throw exceptions)
-    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libstdc++")
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++")
-  endif()
-  
-  include(CheckIncludeFile)
-  include(CheckIncludeFileCXX)
-  include(FindPythonInterp)
-  include(${CMAKE_CURRENT_LIST_DIR}/Compiler.cmake)
-  include(${CMAKE_CURRENT_LIST_DIR}/DownloadPackage.cmake)
-  include(${CMAKE_CURRENT_LIST_DIR}/AutoGeneratedCode.cmake)
-  set(EMBED_RESOURCES_PYTHON ${CMAKE_CURRENT_LIST_DIR}/EmbedResources.py)
-
-  if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows" OR
-      ORTHANC_FRAMEWORK_STATIC)
-    include_directories(${ORTHANC_FRAMEWORK_ROOT}/..)
-  else()
-    # Look for mandatory dependency JsonCpp (cf. JsonCppConfiguration.cmake)
-    find_path(JSONCPP_INCLUDE_DIR json/reader.h
-      /usr/include/jsoncpp
-      /usr/local/include/jsoncpp
-      )
-
-    message("JsonCpp include dir: ${JSONCPP_INCLUDE_DIR}")
-    include_directories(${JSONCPP_INCLUDE_DIR})
-    link_libraries(jsoncpp)
-
-    CHECK_INCLUDE_FILE_CXX(${JSONCPP_INCLUDE_DIR}/json/reader.h HAVE_JSONCPP_H)
-    if (NOT HAVE_JSONCPP_H)
-      message(FATAL_ERROR "Please install the libjsoncpp-dev package")
-    endif()
-
-    # Look for mandatory dependency Boost (cf. BoostConfiguration.cmake)
-    include(FindBoost)
-    find_package(Boost COMPONENTS filesystem thread system date_time regex)
-
-    if (NOT Boost_FOUND)
-      message(FATAL_ERROR "Unable to locate Boost on this system")
-    endif()
-    
-    include_directories(${Boost_INCLUDE_DIRS})
-    link_libraries(${Boost_LIBRARIES})
-
-    # Optional component - Lua
-    if (ENABLE_LUA)
-      include(FindLua)
-
-      if (NOT LUA_FOUND)
-        message(FATAL_ERROR "Please install the liblua-dev package")
-      endif()
-
-      include_directories(${LUA_INCLUDE_DIR})
-      link_libraries(${LUA_LIBRARIES})
-    endif()
-
-    # Optional component - SQLite
-    if (ENABLE_SQLITE)    
-      CHECK_INCLUDE_FILE(sqlite3.h HAVE_SQLITE_H)
-      if (NOT HAVE_SQLITE_H)
-        message(FATAL_ERROR "Please install the libsqlite3-dev package")
-      endif()
-      link_libraries(sqlite3)
-    endif()
-
-    # Optional component - Pugixml
-    if (ENABLE_PUGIXML)
-      CHECK_INCLUDE_FILE_CXX(pugixml.hpp HAVE_PUGIXML_H)
-      if (NOT HAVE_PUGIXML_H)
-        message(FATAL_ERROR "Please install the libpugixml-dev package")
-      endif()      
-      link_libraries(pugixml)
-    endif()
-
-    # Optional component - DCMTK
-    if (ENABLE_DCMTK)
-      include(FindDCMTK)
-      include_directories(${DCMTK_INCLUDE_DIRS})
-      link_libraries(${DCMTK_LIBRARIES})
-    endif()
-  endif()
-
-  # Optional component - Google Test
-  if (ENABLE_GOOGLE_TEST)
-    set(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test")
-    set(USE_GOOGLE_TEST_DEBIAN_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)")
-    mark_as_advanced(USE_GOOGLE_TEST_DEBIAN_PACKAGE)
-    include(${CMAKE_CURRENT_LIST_DIR}/GoogleTestConfiguration.cmake)
-  endif()
-
-  # Look for Orthanc framework shared library
-  include(CheckCXXSymbolExists)
-
-  if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
-    set(ORTHANC_FRAMEWORK_INCLUDE_DIR ${ORTHANC_FRAMEWORK_ROOT})
-  else()
-    find_path(ORTHANC_FRAMEWORK_INCLUDE_DIR OrthancFramework.h
-      /usr/include/orthanc-framework
-      /usr/local/include/orthanc-framework
-      ${ORTHANC_FRAMEWORK_ROOT}
-      )
-  endif()
-  
-  message("Orthanc framework include dir: ${ORTHANC_FRAMEWORK_INCLUDE_DIR}")
-  include_directories(${ORTHANC_FRAMEWORK_INCLUDE_DIR})
-  
-  set(CMAKE_REQUIRED_INCLUDES "${ORTHANC_FRAMEWORK_INCLUDE_DIR}")
-
-  if (NOT "${ORTHANC_FRAMEWORK_LIBDIR}" STREQUAL "")
-    set(CMAKE_REQUIRED_LIBRARIES "-L${ORTHANC_FRAMEWORK_LIBDIR} -lOrthancFramework")
-  else()
-    set(CMAKE_REQUIRED_LIBRARIES "OrthancFramework")
-  endif()
-  
-  check_cxx_symbol_exists("Orthanc::InitializeFramework" "OrthancFramework.h" HAVE_ORTHANC_FRAMEWORK)
-  if(NOT HAVE_ORTHANC_FRAMEWORK)
-    message(FATAL_ERROR "Cannot find the Orthanc framework")
-  endif()
-
-  if (NOT "${ORTHANC_FRAMEWORK_ROOT}" STREQUAL "")
-    include_directories(${ORTHANC_FRAMEWORK_ROOT})
-  endif()
-
-  if (NOT "${ORTHANC_FRAMEWORK_LIBDIR}" STREQUAL "")
-    link_directories(${ORTHANC_FRAMEWORK_LIBDIR})
-  endif()
-endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/EmbedResources.py	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,455 @@
+#!/usr/bin/python
+
+# Orthanc - A Lightweight, RESTful DICOM Store
+# Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+# Department, University Hospital of Liege, Belgium
+# Copyright (C) 2017-2020 Osimis S.A., Belgium
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# In addition, as a special exception, the copyright holders of this
+# program give permission to link the code of its release with the
+# OpenSSL project's "OpenSSL" library (or with modified versions of it
+# that use the same license as the "OpenSSL" library), and distribute
+# the linked executables. You must obey the GNU General Public License
+# in all respects for all of the code used other than "OpenSSL". If you
+# modify file(s) with this exception, you may extend this exception to
+# your version of the file(s), but you are not obligated to do so. If
+# you do not wish to do so, delete this exception statement from your
+# version. If you delete this exception statement from all source files
+# in the program, then also delete it here.
+# 
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+import sys
+import os
+import os.path
+import pprint
+import re
+
+UPCASE_CHECK = True
+USE_SYSTEM_EXCEPTION = False
+EXCEPTION_CLASS = 'OrthancException'
+OUT_OF_RANGE_EXCEPTION = '::Orthanc::OrthancException(::Orthanc::ErrorCode_ParameterOutOfRange)'
+INEXISTENT_PATH_EXCEPTION = '::Orthanc::OrthancException(::Orthanc::ErrorCode_InexistentItem)'
+NAMESPACE = 'Orthanc.EmbeddedResources'
+FRAMEWORK_PATH = None
+
+ARGS = []
+for i in range(len(sys.argv)):
+    if not sys.argv[i].startswith('--'):
+        ARGS.append(sys.argv[i])
+    elif sys.argv[i].lower() == '--no-upcase-check':
+        UPCASE_CHECK = False
+    elif sys.argv[i].lower() == '--system-exception':
+        USE_SYSTEM_EXCEPTION = True
+        EXCEPTION_CLASS = '::std::runtime_error'
+        OUT_OF_RANGE_EXCEPTION = '%s("Parameter out of range")' % EXCEPTION_CLASS
+        INEXISTENT_PATH_EXCEPTION = '%s("Unknown path in a directory resource")' % EXCEPTION_CLASS
+    elif sys.argv[i].startswith('--namespace='):
+        NAMESPACE = sys.argv[i][sys.argv[i].find('=') + 1 : ]
+    elif sys.argv[i].startswith('--framework-path='):
+        FRAMEWORK_PATH = sys.argv[i][sys.argv[i].find('=') + 1 : ]
+
+if len(ARGS) < 2 or len(ARGS) % 2 != 0:
+    print ('Usage:')
+    print ('python %s [--no-upcase-check] [--system-exception] [--namespace=<Namespace>] <TargetBaseFilename> [ <Name> <Source> ]*' % sys.argv[0])
+    exit(-1)
+
+TARGET_BASE_FILENAME = ARGS[1]
+SOURCES = ARGS[2:]
+
+try:
+    # Make sure the destination directory exists
+    os.makedirs(os.path.normpath(os.path.join(TARGET_BASE_FILENAME, '..')))
+except:
+    pass
+
+
+#####################################################################
+## Read each resource file
+#####################################################################
+
+def CheckNoUpcase(s):
+    global UPCASE_CHECK
+    if (UPCASE_CHECK and
+        re.search('[A-Z]', s) != None):
+        raise Exception("Path in a directory with an upcase letter: %s" % s)
+
+resources = {}
+
+counter = 0
+i = 0
+while i < len(SOURCES):
+    resourceName = SOURCES[i].upper()
+    pathName = SOURCES[i + 1]
+
+    if not os.path.exists(pathName):
+        raise Exception("Non existing path: %s" % pathName)
+
+    if resourceName in resources:
+        raise Exception("Twice the same resource: " + resourceName)
+    
+    if os.path.isdir(pathName):
+        # The resource is a directory: Recursively explore its files
+        content = {}
+        for root, dirs, files in os.walk(pathName):
+            dirs.sort()
+            files.sort()
+            base = os.path.relpath(root, pathName)
+
+            # Fix issue #24 (Build fails on OSX when directory has .DS_Store files):
+            # Ignore folders whose name starts with a dot (".")
+            if base.find('/.') != -1:
+                print('Ignoring folder: %s' % root)
+                continue
+
+            for f in files:
+                if f.find('~') == -1:  # Ignore Emacs backup files
+                    if base == '.':
+                        r = f
+                    else:
+                        r = os.path.join(base, f)
+
+                    CheckNoUpcase(r)
+                    r = '/' + r.replace('\\', '/')
+                    if r in content:
+                        raise Exception("Twice the same filename (check case): " + r)
+
+                    content[r] = {
+                        'Filename' : os.path.join(root, f),
+                        'Index' : counter
+                        }
+                    counter += 1
+
+        resources[resourceName] = {
+            'Type' : 'Directory',
+            'Files' : content
+            }
+
+    elif os.path.isfile(pathName):
+        resources[resourceName] = {
+            'Type' : 'File',
+            'Index' : counter,
+            'Filename' : pathName
+            }
+        counter += 1
+
+    else:
+        raise Exception("Not a regular file, nor a directory: " + pathName)
+
+    i += 2
+
+#pprint.pprint(resources)
+
+
+#####################################################################
+## Write .h header
+#####################################################################
+
+header = open(TARGET_BASE_FILENAME + '.h', 'w')
+
+header.write("""
+#pragma once
+
+#include <string>
+#include <list>
+
+#if defined(_MSC_VER)
+#  pragma warning(disable: 4065)  // "Switch statement contains 'default' but no 'case' labels"
+#endif
+
+""")
+
+
+for ns in NAMESPACE.split('.'):
+    header.write('namespace %s {\n' % ns)
+    
+
+header.write("""
+    enum FileResourceId
+    {
+""")
+
+isFirst = True
+for name in resources:
+    if resources[name]['Type'] == 'File':
+        if isFirst:
+            isFirst = False
+        else:    
+            header.write(',\n')
+        header.write('      %s' % name)
+
+header.write("""
+    };
+
+    enum DirectoryResourceId
+    {
+""")
+
+isFirst = True
+for name in resources:
+    if resources[name]['Type'] == 'Directory':
+        if isFirst:
+            isFirst = False
+        else:    
+            header.write(',\n')
+        header.write('      %s' % name)
+
+header.write("""
+    };
+
+    const void* GetFileResourceBuffer(FileResourceId id);
+    size_t GetFileResourceSize(FileResourceId id);
+    void GetFileResource(std::string& result, FileResourceId id);
+
+    const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path);
+    size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path);
+    void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path);
+
+    void ListResources(std::list<std::string>& result, DirectoryResourceId id);
+
+""")
+
+
+for ns in NAMESPACE.split('.'):
+    header.write('}\n')
+
+header.close()
+
+
+
+#####################################################################
+## Write the resource content in the .cpp source
+#####################################################################
+
+PYTHON_MAJOR_VERSION = sys.version_info[0]
+
+def WriteResource(cpp, item):
+    cpp.write('    static const uint8_t resource%dBuffer[] = {' % item['Index'])
+
+    f = open(item['Filename'], "rb")
+    content = f.read()
+    f.close()
+
+    # http://stackoverflow.com/a/1035360
+    pos = 0
+    buffer = []  # instead of appending a few bytes at a time to the cpp file, 
+                 # we first append each chunk to a list, join it and write it 
+                 # to the file.  We've measured that it was 2-3 times faster in python3.
+                 # Note that speed is important since if generation is too slow,
+                 # cmake might try to compile the EmbeddedResources.cpp file while it is
+                 # still being generated !
+    for b in content:
+        if PYTHON_MAJOR_VERSION == 2:
+            c = ord(b[0])
+        else:
+            c = b
+
+        if pos > 0:
+            buffer.append(",")
+
+        if (pos % 16) == 0:
+            buffer.append("\n")
+
+        if c < 0:
+            raise Exception("Internal error")
+
+        buffer.append("0x%02x" % c)
+        pos += 1
+
+    cpp.write("".join(buffer))
+    # Zero-size array are disallowed, so we put one single void character in it.
+    if pos == 0:
+        cpp.write('  0')
+
+    cpp.write('  };\n')
+    cpp.write('    static const size_t resource%dSize = %d;\n' % (item['Index'], pos))
+
+
+cpp = open(TARGET_BASE_FILENAME + '.cpp', 'w')
+
+cpp.write('#include "%s.h"\n' % os.path.basename(TARGET_BASE_FILENAME))
+
+if USE_SYSTEM_EXCEPTION:
+    cpp.write('#include <stdexcept>')
+elif FRAMEWORK_PATH != None:
+    cpp.write('#include "%s/OrthancException.h"' % FRAMEWORK_PATH)
+else:
+    cpp.write('#include <OrthancException.h>')
+
+cpp.write("""
+#include <stdint.h>
+#include <string.h>
+
+""")
+
+for ns in NAMESPACE.split('.'):
+    cpp.write('namespace %s {\n' % ns)
+
+
+for name in resources:
+    if resources[name]['Type'] == 'File':
+        WriteResource(cpp, resources[name])
+    else:
+        for f in resources[name]['Files']:
+            WriteResource(cpp, resources[name]['Files'][f])
+
+
+
+#####################################################################
+## Write the accessors to the file resources in .cpp
+#####################################################################
+
+cpp.write("""
+    const void* GetFileResourceBuffer(FileResourceId id)
+    {
+      switch (id)
+      {
+""")
+for name in resources:
+    if resources[name]['Type'] == 'File':
+        cpp.write('      case %s:\n' % name)
+        cpp.write('        return resource%dBuffer;\n' % resources[name]['Index'])
+
+cpp.write("""
+      default:
+        throw %s;
+      }
+    }
+
+    size_t GetFileResourceSize(FileResourceId id)
+    {
+      switch (id)
+      {
+""" % OUT_OF_RANGE_EXCEPTION)
+
+for name in resources:
+    if resources[name]['Type'] == 'File':
+        cpp.write('      case %s:\n' % name)
+        cpp.write('        return resource%dSize;\n' % resources[name]['Index'])
+
+cpp.write("""
+      default:
+        throw %s;
+      }
+    }
+""" % OUT_OF_RANGE_EXCEPTION)
+
+
+
+#####################################################################
+## Write the accessors to the directory resources in .cpp
+#####################################################################
+
+cpp.write("""
+    const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path)
+    {
+      switch (id)
+      {
+""")
+
+for name in resources:
+    if resources[name]['Type'] == 'Directory':
+        cpp.write('      case %s:\n' % name)
+        isFirst = True
+        for path in resources[name]['Files']:
+            cpp.write('        if (!strcmp(path, "%s"))\n' % path)
+            cpp.write('          return resource%dBuffer;\n' % resources[name]['Files'][path]['Index'])
+        cpp.write('        throw %s;\n\n' % INEXISTENT_PATH_EXCEPTION)
+
+cpp.write("""      default:
+        throw %s;
+      }
+    }
+
+    size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path)
+    {
+      switch (id)
+      {
+""" % OUT_OF_RANGE_EXCEPTION)
+
+for name in resources:
+    if resources[name]['Type'] == 'Directory':
+        cpp.write('      case %s:\n' % name)
+        isFirst = True
+        for path in resources[name]['Files']:
+            cpp.write('        if (!strcmp(path, "%s"))\n' % path)
+            cpp.write('          return resource%dSize;\n' % resources[name]['Files'][path]['Index'])
+        cpp.write('        throw %s;\n\n' % INEXISTENT_PATH_EXCEPTION)
+
+cpp.write("""      default:
+        throw %s;
+      }
+    }
+""" % OUT_OF_RANGE_EXCEPTION)
+
+
+
+
+#####################################################################
+## List the resources in a directory
+#####################################################################
+
+cpp.write("""
+    void ListResources(std::list<std::string>& result, DirectoryResourceId id)
+    {
+      result.clear();
+
+      switch (id)
+      {
+""")
+
+for name in resources:
+    if resources[name]['Type'] == 'Directory':
+        cpp.write('      case %s:\n' % name)
+        for path in sorted(resources[name]['Files']):
+            cpp.write('        result.push_back("%s");\n' % path)
+        cpp.write('        break;\n\n')
+
+cpp.write("""      default:
+        throw %s;
+      }
+    }
+""" % OUT_OF_RANGE_EXCEPTION)
+
+
+
+
+#####################################################################
+## Write the convenience wrappers in .cpp
+#####################################################################
+
+cpp.write("""
+    void GetFileResource(std::string& result, FileResourceId id)
+    {
+      size_t size = GetFileResourceSize(id);
+      result.resize(size);
+      if (size > 0)
+        memcpy(&result[0], GetFileResourceBuffer(id), size);
+    }
+
+    void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path)
+    {
+      size_t size = GetDirectoryResourceSize(id, path);
+      result.resize(size);
+      if (size > 0)
+        memcpy(&result[0], GetDirectoryResourceBuffer(id, path), size);
+    }
+""")
+
+
+for ns in NAMESPACE.split('.'):
+    cpp.write('}\n')
+
+cpp.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/ExportedSymbolsPlugins.list	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,7 @@
+# This is the list of the symbols that must be exported by Orthanc
+# plugins, if targeting OS X
+
+_OrthancPluginInitialize
+_OrthancPluginFinalize
+_OrthancPluginGetName
+_OrthancPluginGetVersion
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/OrthancPluginsExports.cmake	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,12 @@
+# In Orthanc <= 1.7.1, the instructions below were part of
+# "Compiler.cmake", and were protected by the (now unused) option
+# "ENABLE_PLUGINS_VERSION_SCRIPT" in CMake
+
+if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "kFreeBSD" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD" OR
+    ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
+  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${CMAKE_CURRENT_LIST_DIR}/VersionScriptPlugins.map")
+elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
+  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -exported_symbols_list ${CMAKE_CURRENT_LIST_DIR}/ExportedSymbolsPlugins.list")
+endif()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Resources/Orthanc/Plugins/VersionScriptPlugins.map	Mon Jul 06 12:04:00 2020 +0200
@@ -0,0 +1,12 @@
+# This is a version-script for Orthanc plugins
+
+{
+global:
+  OrthancPluginInitialize;
+  OrthancPluginFinalize;
+  OrthancPluginGetName;
+  OrthancPluginGetVersion;
+
+local:
+  *;
+};
--- a/Resources/SyncOrthancFolder.py	Wed Jul 01 17:13:38 2020 +0200
+++ b/Resources/SyncOrthancFolder.py	Mon Jul 06 12:04:00 2020 +0200
@@ -15,14 +15,22 @@
 REPOSITORY = 'https://hg.orthanc-server.com/orthanc/raw-file'
 
 FILES = [
-    ('OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake', '.'),
+    ('OrthancFramework/Resources/CMake/AutoGeneratedCode.cmake', 'CMake'),
+    ('OrthancFramework/Resources/CMake/Compiler.cmake', 'CMake'),
+    ('OrthancFramework/Resources/CMake/DownloadOrthancFramework.cmake', 'CMake'),
+    ('OrthancFramework/Resources/CMake/DownloadPackage.cmake', 'CMake'),
+    ('OrthancFramework/Resources/CMake/GoogleTestConfiguration.cmake', 'CMake'),
+    ('OrthancFramework/Resources/EmbedResources.py', '.'),
     ('OrthancFramework/Resources/Toolchains/LinuxStandardBaseToolchain.cmake', '.'),
     ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain32.cmake', '.'),
     ('OrthancFramework/Resources/Toolchains/MinGW-W64-Toolchain64.cmake', '.'),
     ('OrthancFramework/Resources/Toolchains/MinGWToolchain.cmake', '.'),
+    ('OrthancServer/Plugins/Samples/Common/ExportedSymbolsPlugins.list', 'Plugins'),
     ('OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.cpp', 'Plugins'),
     ('OrthancServer/Plugins/Samples/Common/OrthancPluginCppWrapper.h', 'Plugins'),
     ('OrthancServer/Plugins/Samples/Common/OrthancPluginException.h', 'Plugins'),
+    ('OrthancServer/Plugins/Samples/Common/OrthancPluginsExports.cmake', 'Plugins'),
+    ('OrthancServer/Plugins/Samples/Common/VersionScriptPlugins.map', 'Plugins'),
     ('OrthancServer/Sources/Search/DatabaseConstraint.cpp', 'Databases'),
     ('OrthancServer/Sources/Search/DatabaseConstraint.h', 'Databases'),
     ('OrthancServer/Sources/Search/ISqlLookupFormatter.cpp', 'Databases'),
--- a/SQLite/CMakeLists.txt	Wed Jul 01 17:13:38 2020 +0200
+++ b/SQLite/CMakeLists.txt	Mon Jul 06 12:04:00 2020 +0200
@@ -25,6 +25,12 @@
   SQLITE_PREPARE_INDEX ${CMAKE_SOURCE_DIR}/Plugins/PrepareIndex.sql
   )
 
+add_custom_target(
+  AutogeneratedTarget
+  DEPENDS 
+  ${AUTOGENERATED_SOURCES}
+  )
+
 add_library(OrthancSQLiteIndex SHARED
   ${ORTHANC_DATABASES_ROOT}/Framework/Plugins/PluginInitialization.cpp
   Plugins/IndexPlugin.cpp
@@ -34,6 +40,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(OrthancSQLiteIndex AutogeneratedTarget)
+
 message("Setting the version of the libraries to ${ORTHANC_PLUGIN_VERSION}")
 
 add_definitions(
@@ -66,6 +74,8 @@
   ${AUTOGENERATED_SOURCES}
   )
 
+add_dependencies(UnitTests AutogeneratedTarget)
+
 target_link_libraries(UnitTests ${GOOGLE_TEST_LIBRARIES})
 set_target_properties(UnitTests PROPERTIES
   COMPILE_FLAGS -DORTHANC_ENABLE_LOGGING_PLUGIN=0