diff --git a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt index 51cd8aad24..1cef5c595e 100644 --- a/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt +++ b/Applications/PluginGenerator/ProjectTemplate/CMakeLists.txt @@ -1,339 +1,339 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR) # Change project and application name to your own set(MY_PROJECT_NAME $(project-name)) set(MY_APP_NAME $(project-app-name)) #----------------------------------------------------------------------------- # Set the language standard (MITK requires C++14) #----------------------------------------------------------------------------- set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED 1) set(CMAKE_CXX_EXTENSIONS 0) #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(${MY_PROJECT_NAME}_USE_SUPERBUILD "Build ${MY_PROJECT_NAME} and the projects it depends on via SuperBuild.cmake." ON) if(${MY_PROJECT_NAME}_USE_SUPERBUILD) project(${MY_PROJECT_NAME}-superbuild) set(${MY_PROJECT_NAME}_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(${MY_PROJECT_NAME}_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(${MY_PROJECT_NAME}) endif() #----------------------------------------------------------------------------- # See http://cmake.org/cmake/help/cmake-2-8-docs.html#section_Policies for details #----------------------------------------------------------------------------- set(project_policies CMP0001 # NEW: CMAKE_BACKWARDS_COMPATIBILITY should no longer be used. CMP0002 # NEW: Logical target names must be globally unique. CMP0003 # NEW: Libraries linked via full path no longer produce linker search paths. CMP0004 # NEW: Libraries linked may NOT have leading or trailing whitespace. CMP0005 # NEW: Preprocessor definition values are now escaped automatically. CMP0006 # NEW: Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION. CMP0007 # NEW: List command no longer ignores empty elements. CMP0008 # NEW: Libraries linked by full-path must have a valid library file name. CMP0009 # NEW: FILE GLOB_RECURSE calls should not follow symlinks by default. CMP0010 # NEW: Bad variable reference syntax is an error. CMP0011 # NEW: Included scripts do automatic cmake_policy PUSH and POP. CMP0012 # NEW: if() recognizes numbers and boolean constants. CMP0013 # NEW: Duplicate binary directories are not allowed. CMP0014 # NEW: Input directories must have CMakeLists.txt CMP0020 # NEW: Automatically link Qt executables to qtmain target on Windows. CMP0028 # NEW: Double colon in target name means ALIAS or IMPORTED target. ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # Update CMake module path #------------------------------------------------------------------------------ set(CMAKE_MODULE_PATH ${${MY_PROJECT_NAME}_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- include(MacroEmptyExternalProject) #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- foreach(type LIBRARY RUNTIME ARCHIVE) set(output_dir ${${MY_PROJECT_NAME}_BINARY_DIR}/bin) set(CMAKE_${type}_OUTPUT_DIRECTORY ${output_dir} CACHE INTERNAL "Single output directory for building all libraries.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Additional Options (also shown during superbuild) #----------------------------------------------------------------------------- option(BUILD_SHARED_LIBS "Build ${MY_PROJECT_NAME} with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) option(${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS "Build all ${MY_PROJECT_NAME} plugins" OFF) mark_as_advanced(${MY_PROJECT_NAME}_INSTALL_RPATH_RELATIVE ${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS ) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(${MY_PROJECT_NAME}_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # Prerequesites #----------------------------------------------------------------------------- set(${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR "${PROJECT_SOURCE_DIR}/CMake/PackageDepends") set(MODULES_PACKAGE_DEPENDS_DIRS ${${PROJECT_NAME}_MODULES_PACKAGE_DEPENDS_DIR}) find_package(MITK 2016.11.00 REQUIRED) if(COMMAND mitkFunctionCheckMitkCompatibility) mitkFunctionCheckMitkCompatibility(VERSIONS MITK_VERSION_PLUGIN_SYSTEM 1 REQUIRED) else() message(SEND_ERROR "Your MITK version is too old. Please use Git hash b86bf28 or newer") endif() link_directories(${MITK_LINK_DIRECTORIES}) #----------------------------------------------------------------------------- # CMake Function(s) and Macro(s) #----------------------------------------------------------------------------- set(CMAKE_MODULE_PATH ${MITK_SOURCE_DIR}/CMake ${CMAKE_MODULE_PATH} ) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionGetGccVersion) include(mitkFunctionGetVersion) #----------------------------------------------------------------------------- # Set project specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- set(${PROJECT_NAME}_VERSION_MAJOR "0") set(${PROJECT_NAME}_VERSION_MINOR "1") set(${PROJECT_NAME}_VERSION_PATCH "1") set(${PROJECT_NAME}_VERSION_STRING "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}") # Ask the user if a console window should be shown with the applications option(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting GUI Applications" ON) mark_as_advanced(${PROJECT_NAME}_SHOW_CONSOLE_WINDOW) if(NOT UNIX) set(MITK_WIN32_FORCE_STATIC "STATIC") endif() #----------------------------------------------------------------------------- # Get project version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${PROJECT_SOURCE_DIR} ${PROJECT_NAME}) #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- -# on Mac OSX all CTK plugins get copied into every +# on macOS all CTK plugins get copied into every # application bundle (.app directory) specified here set(MACOSX_BUNDLE_NAMES) if(APPLE) list(APPEND MACOSX_BUNDLE_NAMES ${MY_APP_NAME}) endif(APPLE) #----------------------------------------------------------------------------- # Set symbol visibility Flags #----------------------------------------------------------------------------- if(CMAKE_COMPILER_IS_GNUCXX) # The MITK module build system does not yet support default hidden visibility set(VISIBILITY_CXX_FLAGS ) # "-fvisibility=hidden -fvisibility-inlines-hidden") endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if(CMAKE_COMPILER_IS_GNUCXX) set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # Project C/CXX Flags #----------------------------------------------------------------------------- set(${PROJECT_NAME}_C_FLAGS "${MITK_C_FLAGS} ${COVERAGE_C_FLAGS}") set(${PROJECT_NAME}_C_FLAGS_DEBUG ${MITK_C_FLAGS_DEBUG}) set(${PROJECT_NAME}_C_FLAGS_RELEASE ${MITK_C_FLAGS_RELEASE}) set(${PROJECT_NAME}_CXX_FLAGS "${MITK_CXX_FLAGS} ${VISIBILITY_CXX_FLAGS} ${COVERAGE_CXX_FLAGS}") set(${PROJECT_NAME}_CXX_FLAGS_DEBUG ${MITK_CXX_FLAGS_DEBUG}) set(${PROJECT_NAME}_CXX_FLAGS_RELEASE ${MITK_CXX_FLAGS_RELEASE}) set(${PROJECT_NAME}_EXE_LINKER_FLAGS ${MITK_EXE_LINKER_FLAGS}) set(${PROJECT_NAME}_SHARED_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(${PROJECT_NAME}_MODULE_LINKER_FLAGS ${MITK_MODULE_LINKER_FLAGS}) #----------------------------------------------------------------------------- # Set C/CXX Flags #----------------------------------------------------------------------------- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${${PROJECT_NAME}_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${${PROJECT_NAME}_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${${PROJECT_NAME}_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${PROJECT_NAME}_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${${PROJECT_NAME}_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${${PROJECT_NAME}_CXX_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS ${${PROJECT_NAME}_EXE_LINKER_FLAGS}) set(CMAKE_SHARED_LINKER_FLAGS ${${PROJECT_NAME}_SHARED_LINKER_FLAGS}) set(CMAKE_MODULE_LINKER_FLAGS ${${PROJECT_NAME}_MODULE_LINKER_FLAGS}) #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") endif() #----------------------------------------------------------------------------- # ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR isn't defined, it means this project is # *NOT* build using Superbuild. In that specific case, ${MY_PROJECT_NAME}_SUPERBUILD_BINARY_DIR # should default to PROJECT_BINARY_DIR if(NOT DEFINED ${PROJECT_NAME}_SUPERBUILD_BINARY_DIR) set(${PROJECT_NAME}_SUPERBUILD_BINARY_DIR ${PROJECT_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # MITK modules #----------------------------------------------------------------------------- #add_subdirectory(Modules) #----------------------------------------------------------------------------- # CTK plugins #----------------------------------------------------------------------------- # The CMake code in this section *must* be in the top-level CMakeLists.txt file macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin "^$(project-plugin-base)_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin OUTPUT_VARIABLE ${varname}) endmacro() include(${CMAKE_CURRENT_SOURCE_DIR}/Plugins/Plugins.cmake) ctkMacroSetupPlugins(${PROJECT_PLUGINS} BUILD_OPTION_PREFIX ${MY_PROJECT_NAME}_ BUILD_ALL ${${MY_PROJECT_NAME}_BUILD_ALL_PLUGINS}) #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Apps/$(project-app-name)) #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables include(mitkSetupCPack) # Customize CPack variables for this project include(CPackSetup) list(APPEND CPACK_CREATE_DESKTOP_LINKS "${MY_APP_NAME}") configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/${PROJECT_NAME}CPackOptions.cmake") # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- diff --git a/Applications/Solstice/CMakeLists.txt b/Applications/Solstice/CMakeLists.txt index 9cc9b05aa8..53779edb5f 100644 --- a/Applications/Solstice/CMakeLists.txt +++ b/Applications/Solstice/CMakeLists.txt @@ -1,68 +1,68 @@ project(Solstice) set(_app_options) if(MITK_SHOW_CONSOLE_WINDOW) list(APPEND _app_options SHOW_CONSOLE) endif() set(MITK_EXTAPP_PROVISIONING_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MitkWorkbench.provisioning") # Plug-ins listed below will not be # - added as a build-time dependency to the executable # - listed in the provisioning file for the executable # - installed if they are external plug-ins set(_exclude_plugins org.blueberry.test org.blueberry.uitest org.mitk.gui.qt.coreapplication org.mitk.gui.qt.diffusionimagingapp ) FunctionCreateBlueBerryApplication( NAME MitkSolstice DESCRIPTION "MITK Workbench" EXCLUDE_PLUGINS ${_exclude_plugins} ${_app_options} ) add_executable(${OSGI_APP} MACOSX_BUNDLE "src/application/berryMain.cpp") target_link_libraries(${OSGI_APP} PRIVATE ${PROJECT_NAME} mbilog) if(_ctk_test_plugins) add_dependencies(${OSGI_APP} ${_ctk_test_plugins}) add_dependencies(BlueBerry ${OSGI_APP}) set_property(TARGET ${OSGI_APP} APPEND PROPERTY LABELS BlueBerry) endif() configure_file(src/application/solstice.ini ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OSGI_APP}.ini) add_executable(${OSGI_UI_APP} MACOSX_BUNDLE "src/application/berryMainUI.cpp") target_link_libraries(${OSGI_UI_APP} PRIVATE ${PROJECT_NAME} mbilog) if(MITK_USE_Qt5) target_link_libraries(${OSGI_UI_APP} PRIVATE Qt5::Widgets) endif() if(_ctk_test_plugins) add_dependencies(${OSGI_UI_APP} ${_ctk_test_plugins}) add_dependencies(BlueBerry ${OSGI_UI_APP}) set_property(TARGET ${OSGI_UI_APP} APPEND PROPERTY LABELS BlueBerry) endif() configure_file(src/application/solstice.ini ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OSGI_UI_APP}.ini) # Add meta dependencies (e.g. on auto-load modules from depending modules) if(TARGET ${CMAKE_PROJECT_NAME}-autoload) add_dependencies(MitkWorkbench ${CMAKE_PROJECT_NAME}-autoload) endif() -#Setting application icon for mac os x systems +#Setting application icon for macOS systems set_target_properties(MitkWorkbench PROPERTIES MACOSX_BUNDLE_ICON_FILE "icon.icns") if(APPLE) install(FILES "icons/icon.icns" DESTINATION "MitkWorkbench.app/Contents/Resources") endif(APPLE) diff --git a/Applications/Workbench/CMakeLists.txt b/Applications/Workbench/CMakeLists.txt index 1696623d65..c2ad329f0f 100644 --- a/Applications/Workbench/CMakeLists.txt +++ b/Applications/Workbench/CMakeLists.txt @@ -1,57 +1,57 @@ project(Workbench) set(_app_options) if(MITK_SHOW_CONSOLE_WINDOW) list(APPEND _app_options SHOW_CONSOLE) endif() # Create a cache entry for the provisioning file which is used to export # the file name in the MITKConfig.cmake file. This will keep external projects # which rely on this file happy. set(MITK_EXTAPP_PROVISIONING_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/MitkWorkbench.provisioning" CACHE INTERNAL "MitkWorkbench provisioning file" FORCE) # Plug-ins listed below will not be # - added as a build-time dependency to the executable # - listed in the provisioning file for the executable # - installed if they are external plug-ins set(_exclude_plugins org.blueberry.test org.blueberry.uitest org.mitk.gui.qt.coreapplication org.mitk.gui.qt.diffusionimagingapp org.mitk.example.gui.customviewer org.mitk.example.gui.customviewer.views org.mitk.example.gui.selectionservicemitk org.mitk.example.gui.selectionservicemitk.views org.mitk.example.gui.selectionserviceqt org.mitk.example.gui.extensionpointcontribution org.mitk.example.gui.extensionpointdefinition org.mitk.example.gui.minimalapplication org.mitk.example.gui.multipleperspectives ) mitkFunctionCreateBlueBerryApplication( NAME MitkWorkbench DESCRIPTION "MITK Workbench" EXCLUDE_PLUGINS ${_exclude_plugins} ${_app_options} ) mitk_use_modules(TARGET MitkWorkbench MODULES MitkAppUtil) # Add meta dependencies (e.g. on auto-load modules from depending modules) if(TARGET ${CMAKE_PROJECT_NAME}-autoload) add_dependencies(MitkWorkbench ${CMAKE_PROJECT_NAME}-autoload) endif() -#Setting application icon for mac os x systems +#Setting application icon for macOS systems set_target_properties(MitkWorkbench PROPERTIES MACOSX_BUNDLE_ICON_FILE "icon.icns") if(APPLE) install(FILES "icons/icon.icns" DESTINATION "MitkWorkbench.app/Contents/Resources") endif(APPLE) # Add a build time dependency to legacy BlueBerry bundles. if(MITK_MODULES_ENABLED_PLUGINS) add_dependencies(MitkWorkbench ${MITK_MODULES_ENABLED_PLUGINS}) endif() diff --git a/CMake/GetPrerequisites.cmake b/CMake/GetPrerequisites.cmake index 09f5d0f465..be5e8548cb 100644 --- a/CMake/GetPrerequisites.cmake +++ b/CMake/GetPrerequisites.cmake @@ -1,1095 +1,1095 @@ # Special version of GetPrerequisites that implements a caching mechanism. # Thank you to Daniel Maleike for the contribution message("Using MITK version of GetPrerequisites.cmake") # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #.rst: # GetPrerequisites # ---------------- # # Functions to analyze and list executable file prerequisites. # # This module provides functions to list the .dll, .dylib or .so files # that an executable or shared library file depends on. (Its # prerequisites.) # # It uses various tools to obtain the list of required shared library # files: # # :: # # dumpbin (Windows) # ldd (Linux/Unix) -# otool (Mac OSX) +# otool (macOS) # # The following functions are provided by this module: # # :: # # get_prerequisites # list_prerequisites # list_prerequisites_by_glob # gp_append_unique # is_file_executable # gp_item_default_embedded_path # (projects can override with gp_item_default_embedded_path_override) # gp_resolve_item # (projects can override with gp_resolve_item_override) # gp_resolved_file_type # (projects can override with gp_resolved_file_type_override) # gp_file_type # # Requires CMake 2.6 or greater because it uses function, break, return # and PARENT_SCOPE. # # :: # # GET_PREREQUISITES( # []) # # Get the list of shared library files required by . The list # in the variable named should be empty on first # entry to this function. On exit, will contain the # list of required shared library files. # # is the full path to an executable file. # is the name of a CMake variable to contain the results. # must be 0 or 1 indicating whether to include or # exclude "system" prerequisites. If is set to 1 all # prerequisites will be found recursively, if set to 0 only direct # prerequisites are listed. is the path to the top level # executable used for @executable_path replacment on the Mac. is # a list of paths where libraries might be found: these paths are # searched first when a target without any path info is given. Then # standard system locations are also searched: PATH, Framework # locations, /usr/lib... # # :: # # LIST_PREREQUISITES( [ [ []]]) # # Print a message listing the prerequisites of . # # is the name of a shared library or executable target or the # full path to a shared library or executable file. If is set # to 1 all prerequisites will be found recursively, if set to 0 only # direct prerequisites are listed. must be 0 or 1 # indicating whether to include or exclude "system" prerequisites. With # set to 0 only the full path names of the prerequisites are # printed, set to 1 extra informatin will be displayed. # # :: # # LIST_PREREQUISITES_BY_GLOB( ) # # Print the prerequisites of shared library and executable files # matching a globbing pattern. is GLOB or GLOB_RECURSE and # is a globbing expression used with "file(GLOB" or # "file(GLOB_RECURSE" to retrieve a list of matching files. If a # matching file is executable, its prerequisites are listed. # # Any additional (optional) arguments provided are passed along as the # optional arguments to the list_prerequisites calls. # # :: # # GP_APPEND_UNIQUE( ) # # Append to the list variable only if the value is # not already in the list. # # :: # # IS_FILE_EXECUTABLE( ) # # Return 1 in if is a binary executable, 0 # otherwise. # # :: # # GP_ITEM_DEFAULT_EMBEDDED_PATH( ) # # Return the path that others should refer to the item by when the item # is embedded inside a bundle. # # Override on a per-project basis by providing a project-specific # gp_item_default_embedded_path_override function. # # :: # # GP_RESOLVE_ITEM( # []) # # Resolve an item into an existing full path file. # # Override on a per-project basis by providing a project-specific # gp_resolve_item_override function. # # :: # # GP_RESOLVED_FILE_TYPE( # []) # # Return the type of with respect to . String # describing type of prerequisite is returned in variable named # . # # Use and if necessary to resolve non-absolute # values -- but only for non-embedded items. # # Possible types are: # # :: # # system # local # embedded # other # # Override on a per-project basis by providing a project-specific # gp_resolved_file_type_override function. # # :: # # GP_FILE_TYPE( ) # # Return the type of with respect to . String # describing type of prerequisite is returned in variable named # . # # Possible types are: # # :: # # system # local # embedded # other function(gp_append_unique list_var value) set(contains 0) foreach(item ${${list_var}}) if(item STREQUAL "${value}") set(contains 1) break() endif() endforeach() if(NOT contains) set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE) endif() endfunction() function(is_file_executable file result_var) # # A file is not executable until proven otherwise: # set(${result_var} 0 PARENT_SCOPE) get_filename_component(file_full "${file}" ABSOLUTE) string(TOLOWER "${file_full}" file_full_lower) # If file name ends in .exe on Windows, *assume* executable: # if(WIN32 AND NOT UNIX) if("${file_full_lower}" MATCHES "\\.exe$") set(${result_var} 1 PARENT_SCOPE) return() endif() # A clause could be added here that uses output or return value of dumpbin # to determine ${result_var}. In 99%+? practical cases, the exe name # match will be sufficient... # endif() # Use the information returned from the Unix shell command "file" to # determine if ${file_full} should be considered an executable file... # # If the file command's output contains "executable" and does *not* contain # "text" then it is likely an executable suitable for prerequisite analysis # via the get_prerequisites macro. # if(UNIX) if(NOT file_cmd) find_program(file_cmd "file") mark_as_advanced(file_cmd) endif() if(file_cmd) execute_process(COMMAND "${file_cmd}" "${file_full}" RESULT_VARIABLE file_rv OUTPUT_VARIABLE file_ov ERROR_VARIABLE file_ev OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT file_rv STREQUAL "0") message(FATAL_ERROR "${file_cmd} failed: ${file_rv}\n${file_ev}") endif() # Replace the name of the file in the output with a placeholder token # (the string " _file_full_ ") so that just in case the path name of # the file contains the word "text" or "executable" we are not fooled # into thinking "the wrong thing" because the file name matches the # other 'file' command output we are looking for... # string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") string(TOLOWER "${file_ov}" file_ov) #message(STATUS "file_ov='${file_ov}'") if("${file_ov}" MATCHES "executable") #message(STATUS "executable!") if("${file_ov}" MATCHES "text") #message(STATUS "but text, so *not* a binary executable!") else() set(${result_var} 1 PARENT_SCOPE) return() endif() endif() # Also detect position independent executables on Linux, # where "file" gives "shared object ... (uses shared libraries)" if("${file_ov}" MATCHES "shared object.*\(uses shared libs\)") set(${result_var} 1 PARENT_SCOPE) return() endif() # "file" version 5.22 does not print "(used shared libraries)" # but uses "interpreter" if("${file_ov}" MATCHES "shared object.*interpreter") set(${result_var} 1 PARENT_SCOPE) return() endif() else() message(STATUS "warning: No 'file' command, skipping execute_process...") endif() endif() endfunction() function(gp_item_default_embedded_path item default_embedded_path_var) # On Windows and Linux, "embed" prerequisites in the same directory # as the executable by default: # set(path "@executable_path") set(overridden 0) # On the Mac, relative to the executable depending on the type # of the thing we are embedding: # if(APPLE) # # The assumption here is that all executables in the bundle will be # in same-level-directories inside the bundle. The parent directory # of an executable inside the bundle should be MacOS or a sibling of # MacOS and all embedded paths returned from here will begin with # "@executable_path/../" and will work from all executables in all # such same-level-directories inside the bundle. # # By default, embed things right next to the main bundle executable: # set(path "@executable_path/../../Contents/MacOS") # Embed .dylibs right next to the main bundle executable: # if(item MATCHES "\\.dylib$") set(path "@executable_path/../MacOS") set(overridden 1) endif() # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS): # if(NOT overridden) if(item MATCHES "[^/]+\\.framework/") set(path "@executable_path/../Frameworks") set(overridden 1) endif() endif() endif() # Provide a hook so that projects can override the default embedded location # of any given library by whatever logic they choose: # if(COMMAND gp_item_default_embedded_path_override) gp_item_default_embedded_path_override("${item}" path) endif() set(${default_embedded_path_var} "${path}" PARENT_SCOPE) endfunction() function(gp_resolve_item context item exepath dirs resolved_item_var) set(resolved 0) set(resolved_item "${item}") if(ARGC GREATER 5) set(rpaths "${ARGV5}") else() set(rpaths "") endif() # Is it already resolved? # if(IS_ABSOLUTE "${resolved_item}" AND EXISTS "${resolved_item}") set(resolved 1) endif() if(NOT resolved) if(item MATCHES "^@executable_path") # # @executable_path references are assumed relative to exepath # string(REPLACE "@executable_path" "${exepath}" ri "${item}") get_filename_component(ri "${ri}" ABSOLUTE) if(EXISTS "${ri}") #message(STATUS "info: embedded item exists (${ri})") set(resolved 1) set(resolved_item "${ri}") else() message(STATUS "warning: embedded item does not exist '${ri}'") endif() endif() endif() if(NOT resolved) if(item MATCHES "^@loader_path") # # @loader_path references are assumed relative to the # PATH of the given "context" (presumably another library) # get_filename_component(contextpath "${context}" PATH) string(REPLACE "@loader_path" "${contextpath}" ri "${item}") get_filename_component(ri "${ri}" ABSOLUTE) if(EXISTS "${ri}") #message(STATUS "info: embedded item exists (${ri})") set(resolved 1) set(resolved_item "${ri}") else() message(STATUS "warning: embedded item does not exist '${ri}'") endif() endif() endif() if(NOT resolved) if(item MATCHES "^@rpath") # # @rpath references are relative to the paths built into the binaries with -rpath # We handle this case like we do for other Unixes # string(REPLACE "@rpath/" "" norpath_item "${item}") set(ri "ri-NOTFOUND") find_file(ri "${norpath_item}" ${exepath} ${dirs} ${rpaths} NO_DEFAULT_PATH) if(ri) #message(STATUS "info: 'find_file' in exepath/dirs/rpaths (${ri})") set(resolved 1) set(resolved_item "${ri}") set(ri "ri-NOTFOUND") endif() endif() endif() if(NOT resolved) set(ri "ri-NOTFOUND") find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) get_filename_component(basename_item "${item}" NAME) find_file(ri "${basename_item}" PATHS ${exepath} ${dirs} NO_DEFAULT_PATH) find_file(ri "${basename_item}" PATHS /usr/lib) if(ri) #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") set(resolved 1) set(resolved_item "${ri}") set(ri "ri-NOTFOUND") endif() endif() if(NOT resolved) if(item MATCHES "[^/]+\\.framework/") set(fw "fw-NOTFOUND") find_file(fw "${item}" "~/Library/Frameworks" "/Library/Frameworks" "/System/Library/Frameworks" ) if(fw) #message(STATUS "info: 'find_file' found framework (${fw})") set(resolved 1) set(resolved_item "${fw}") set(fw "fw-NOTFOUND") endif() endif() endif() # Using find_program on Windows will find dll files that are in the PATH. # (Converting simple file names into full path names if found.) # if(WIN32 AND NOT UNIX) if(NOT resolved) set(ri "ri-NOTFOUND") find_program(ri "${item}" PATHS ${exepath} ${dirs} NO_DEFAULT_PATH) find_program(ri "${item}" PATHS ${exepath} ${dirs}) if(ri) #message(STATUS "info: 'find_program' in exepath/dirs (${ri})") set(resolved 1) set(resolved_item "${ri}") set(ri "ri-NOTFOUND") endif() endif() endif() # Provide a hook so that projects can override item resolution # by whatever logic they choose: # if(COMMAND gp_resolve_item_override) gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved) endif() if(NOT resolved) message(STATUS " warning: cannot resolve item '${item}' possible problems: need more directories? need to use InstallRequiredSystemLibraries? run in install tree instead of build tree? ") # message(STATUS " #****************************************************************************** #warning: cannot resolve item '${item}' # # possible problems: # need more directories? # need to use InstallRequiredSystemLibraries? # run in install tree instead of build tree? # # context='${context}' # item='${item}' # exepath='${exepath}' # dirs='${dirs}' # resolved_item_var='${resolved_item_var}' #****************************************************************************** #") endif() set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE) endfunction() function(gp_resolved_file_type original_file file exepath dirs type_var) if(ARGC GREATER 5) set(rpaths "${ARGV5}") else() set(rpaths "") endif() #message(STATUS "**") if(NOT IS_ABSOLUTE "${original_file}") message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file") endif() if(IS_ABSOLUTE "${original_file}") get_filename_component(original_file "${original_file}" ABSOLUTE) # canonicalize path endif() set(is_embedded 0) set(is_local 0) set(is_system 0) set(resolved_file "${file}") if("${file}" MATCHES "^@(executable|loader)_path") set(is_embedded 1) endif() if(NOT is_embedded) if(NOT IS_ABSOLUTE "${file}") gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file "${rpaths}") endif() if(IS_ABSOLUTE "${resolved_file}") get_filename_component(resolved_file "${resolved_file}" ABSOLUTE) # canonicalize path endif() string(TOLOWER "${original_file}" original_lower) string(TOLOWER "${resolved_file}" lower) if(UNIX) if(resolved_file MATCHES "^(/lib/|/lib32/|/libx32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/libx32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)") set(is_system 1) endif() endif() if(APPLE) if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)") set(is_system 1) endif() endif() if(WIN32) string(TOLOWER "$ENV{SystemRoot}" sysroot) file(TO_CMAKE_PATH "${sysroot}" sysroot) string(TOLOWER "$ENV{windir}" windir) file(TO_CMAKE_PATH "${windir}" windir) if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*(msvc|api-ms-win-)[^/]+dll)") set(is_system 1) endif() if(UNIX) # if cygwin, we can get the properly formed windows paths from cygpath find_program(CYGPATH_EXECUTABLE cygpath) if(CYGPATH_EXECUTABLE) execute_process(COMMAND ${CYGPATH_EXECUTABLE} -W RESULT_VARIABLE env_rv OUTPUT_VARIABLE env_windir ERROR_VARIABLE env_ev OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT env_rv STREQUAL "0") message(FATAL_ERROR "${CYGPATH_EXECUTABLE} -W failed: ${env_rv}\n${env_ev}") endif() execute_process(COMMAND ${CYGPATH_EXECUTABLE} -S RESULT_VARIABLE env_rv OUTPUT_VARIABLE env_sysdir ERROR_VARIABLE env_ev OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT env_rv STREQUAL "0") message(FATAL_ERROR "${CYGPATH_EXECUTABLE} -S failed: ${env_rv}\n${env_ev}") endif() string(TOLOWER "${env_windir}" windir) string(TOLOWER "${env_sysdir}" sysroot) if(lower MATCHES "^(${sysroot}/sys(tem|wow)|${windir}/sys(tem|wow)|(.*/)*(msvc|api-ms-win-)[^/]+dll)") set(is_system 1) endif() endif() endif() endif() if(NOT is_system) get_filename_component(original_path "${original_lower}" PATH) get_filename_component(path "${lower}" PATH) if(original_path STREQUAL path) set(is_local 1) else() string(LENGTH "${original_path}/" original_length) string(LENGTH "${lower}" path_length) if(${path_length} GREATER ${original_length}) string(SUBSTRING "${lower}" 0 ${original_length} path) if("${original_path}/" STREQUAL path) set(is_embedded 1) endif() endif() endif() endif() endif() # Return type string based on computed booleans: # set(type "other") if(is_system) set(type "system") elseif(is_embedded) set(type "embedded") elseif(is_local) set(type "local") endif() #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'") #message(STATUS " type: '${type}'") if(NOT is_embedded) if(NOT IS_ABSOLUTE "${resolved_file}") if(lower MATCHES "^(msvc|api-ms-win-)[^/]+dll" AND is_system) message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'") else() message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect") endif() endif() endif() # Provide a hook so that projects can override the decision on whether a # library belongs to the system or not by whatever logic they choose: # if(COMMAND gp_resolved_file_type_override) gp_resolved_file_type_override("${resolved_file}" type) endif() set(${type_var} "${type}" PARENT_SCOPE) #message(STATUS "**") endfunction() function(gp_file_type original_file file type_var) if(NOT IS_ABSOLUTE "${original_file}") message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file") endif() get_filename_component(exepath "${original_file}" PATH) set(type "") gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type) set(${type_var} "${type}" PARENT_SCOPE) endfunction() function(get_prerequisites_clear_cache) set_property(GLOBAL PROPERTY prerequisites_cachevariables "") endfunction(get_prerequisites_clear_cache) function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs) # See if we know the answer from our cache. If so, we are done early # incorporate all parameters into cache key string(SHA1 param_hash "${exclude_system}_${recurse}_${exepath}_${dirs}") set(prerequisites_cache_var_name "prerequisites_cache_${target}_${param_hash}") string(TOLOWER "${prerequisites_cache_var_name}" prerequisites_cache_var_name) string(REGEX REPLACE "[:-\\/.]" "_" prerequisites_cache_var_name "${prerequisites_cache_var_name}") get_property(cache_value GLOBAL PROPERTY ${prerequisites_cache_var_name} SET) if (cache_value) get_property(cache_value GLOBAL PROPERTY ${prerequisites_cache_var_name}) # if defined, then get value if (cache_value) # already something non-empty -> append set(${prerequisites_var} "${${prerequisites_var}};${cache_value}" PARENT_SCOPE) endif() return() endif() set(verbose 0) set(eol_char "E") if(ARGC GREATER 6) set(rpaths "${ARGV6}") else() set(rpaths "") endif() if(NOT IS_ABSOLUTE "${target}") message("warning: target '${target}' is not absolute...") endif() if(NOT EXISTS "${target}") message("warning: target '${target}' does not exist...") set(${prerequisites_var} "" PARENT_SCOPE) return() endif() set(gp_cmd_paths ${gp_cmd_paths} "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\14.0;InstallDir]/../../VC/bin" "$ENV{VS140COMNTOOLS}/../../VC/bin" "C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\12.0;InstallDir]/../../VC/bin" "$ENV{VS120COMNTOOLS}/../../VC/bin" "C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\11.0;InstallDir]/../../VC/bin" "$ENV{VS110COMNTOOLS}/../../VC/bin" "C:/Program Files (x86)/Microsoft Visual Studio 11.0/VC/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\10.0;InstallDir]/../../VC/bin" "$ENV{VS100COMNTOOLS}/../../VC/bin" "C:/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\9.0;InstallDir]/../../VC/bin" "$ENV{VS90COMNTOOLS}/../../VC/bin" "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin" "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0;InstallDir]/../../VC/bin" "$ENV{VS80COMNTOOLS}/../../VC/bin" "C:/Program Files/Microsoft Visual Studio 8/VC/BIN" "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]/../../VC7/bin" "$ENV{VS71COMNTOOLS}/../../VC7/bin" "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN" "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN" "/usr/local/bin" "/usr/bin" ) # # # Try to choose the right tool by default. Caller can set gp_tool prior to # calling this function to force using a different tool. # if(NOT gp_tool) set(gp_tool "ldd") if(APPLE) set(gp_tool "otool") endif() if(WIN32 AND NOT UNIX) # This is how to check for cygwin, har! find_program(gp_dumpbin "dumpbin" PATHS ${gp_cmd_paths}) if(gp_dumpbin) set(gp_tool "dumpbin") else() # Try harder. set(gp_tool "objdump") endif() endif() endif() find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths}) if(NOT gp_cmd) message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...") return() endif() set(gp_cmd_maybe_filter) # optional command to pre-filter gp_tool results if(gp_tool STREQUAL "ldd") set(gp_cmd_args "") set(gp_regex "^[\t ]*[^\t ]+ => ([^\t\(]+) .*${eol_char}$") set(gp_regex_error "not found${eol_char}$") set(gp_regex_fallback "^[\t ]*([^\t ]+) => ([^\t ]+).*${eol_char}$") set(gp_regex_cmp_count 1) elseif(gp_tool STREQUAL "otool") set(gp_cmd_args "-L") set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$") set(gp_regex_error "") set(gp_regex_fallback "") set(gp_regex_cmp_count 3) elseif(gp_tool STREQUAL "dumpbin") set(gp_cmd_args "/dependents") set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$") set(gp_regex_error "") set(gp_regex_fallback "") set(gp_regex_cmp_count 1) elseif(gp_tool STREQUAL "objdump") set(gp_cmd_args "-p") set(gp_regex "^\t*DLL Name: (.*\\.[Dd][Ll][Ll])${eol_char}$") set(gp_regex_error "") set(gp_regex_fallback "") set(gp_regex_cmp_count 1) # objdump generates copious output so we create a grep filter to pre-filter results if(WIN32) find_program(gp_grep_cmd findstr) else() find_program(gp_grep_cmd grep) endif() if(gp_grep_cmd) set(gp_cmd_maybe_filter COMMAND ${gp_grep_cmd} "-a" "^[[:blank:]]*DLL Name: ") endif() else() message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...") message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'") message(STATUS "Valid gp_tool values are dumpbin, ldd, objdump and otool.") return() endif() if(gp_tool STREQUAL "dumpbin") # When running dumpbin, it also needs the "Common7/IDE" directory in the # PATH. It will already be in the PATH if being run from a Visual Studio # command prompt. Add it to the PATH here in case we are running from a # different command prompt. # get_filename_component(gp_cmd_dir "${gp_cmd}" PATH) get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE) # Use cmake paths as a user may have a PATH element ending with a backslash. # This will escape the list delimiter and create havoc! if(EXISTS "${gp_cmd_dlls_dir}") # only add to the path if it is not already in the path set(gp_found_cmd_dlls_dir 0) file(TO_CMAKE_PATH "$ENV{PATH}" env_path) foreach(gp_env_path_element ${env_path}) if(gp_env_path_element STREQUAL gp_cmd_dlls_dir) set(gp_found_cmd_dlls_dir 1) endif() endforeach() if(NOT gp_found_cmd_dlls_dir) file(TO_NATIVE_PATH "${gp_cmd_dlls_dir}" gp_cmd_dlls_dir) set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}") endif() endif() endif() # # if(gp_tool STREQUAL "ldd") set(old_ld_env "$ENV{LD_LIBRARY_PATH}") set(new_ld_env "${exepath}") foreach(dir ${dirs}) string(APPEND new_ld_env ":${dir}") endforeach() set(ENV{LD_LIBRARY_PATH} "${new_ld_env}:$ENV{LD_LIBRARY_PATH}") endif() # Track new prerequisites at each new level of recursion. Start with an # empty list at each level: # set(unseen_prereqs) # Run gp_cmd on the target: # execute_process( COMMAND ${gp_cmd} ${gp_cmd_args} ${target} ${gp_cmd_maybe_filter} RESULT_VARIABLE gp_rv OUTPUT_VARIABLE gp_cmd_ov ERROR_VARIABLE gp_ev ) if(gp_tool STREQUAL "dumpbin") # Exclude delay load dependencies under windows (they are listed in dumpbin output after the message below) string(FIND "${gp_cmd_ov}" "Image has the following delay load dependencies" gp_delayload_pos) if (${gp_delayload_pos} GREATER -1) string(SUBSTRING "${gp_cmd_ov}" 0 ${gp_delayload_pos} gp_cmd_ov_no_delayload_deps) string(SUBSTRING "${gp_cmd_ov}" ${gp_delayload_pos} -1 gp_cmd_ov_delayload_deps) if (verbose) message(STATUS "GetPrequisites(${target}) : ignoring the following delay load dependencies :\n ${gp_cmd_ov_delayload_deps}") endif() set(gp_cmd_ov ${gp_cmd_ov_no_delayload_deps}) endif() endif() if(NOT gp_rv STREQUAL "0") if(gp_tool STREQUAL "dumpbin") # dumpbin error messages seem to go to stdout message(FATAL_ERROR "${gp_cmd} failed: ${gp_rv}\n${gp_ev}\n${gp_cmd_ov}") else() message(FATAL_ERROR "${gp_cmd} failed: ${gp_rv}\n${gp_ev}") endif() endif() if(gp_tool STREQUAL "ldd") set(ENV{LD_LIBRARY_PATH} "${old_ld_env}") endif() if(verbose) message(STATUS "") message(STATUS "gp_cmd_ov='${gp_cmd_ov}'") message(STATUS "") endif() get_filename_component(target_dir "${target}" PATH) # Convert to a list of lines: # string(REPLACE ";" "\\;" candidates "${gp_cmd_ov}") string(REPLACE "\n" "${eol_char};" candidates "${candidates}") # check for install id and remove it from list, since otool -L can include a # reference to itself set(gp_install_id) if(gp_tool STREQUAL "otool") execute_process( COMMAND otool -D ${target} RESULT_VARIABLE otool_rv OUTPUT_VARIABLE gp_install_id_ov ERROR_VARIABLE otool_ev ) if(NOT otool_rv STREQUAL "0") message(FATAL_ERROR "otool -D failed: ${otool_rv}\n${otool_ev}") endif() # second line is install name string(REGEX REPLACE ".*:\n" "" gp_install_id "${gp_install_id_ov}") if(gp_install_id) # trim string(REGEX MATCH "[^\n ].*[^\n ]" gp_install_id "${gp_install_id}") #message("INSTALL ID is \"${gp_install_id}\"") endif() endif() # Analyze each line for file names that match the regular expression: # list(LENGTH ${prerequisites_var} list_length_before_candidates) set(targets_added "") foreach(candidate ${candidates}) if("${candidate}" MATCHES "${gp_regex}") # Extract information from each candidate: if(gp_regex_error AND "${candidate}" MATCHES "${gp_regex_error}") string(REGEX REPLACE "${gp_regex_fallback}" "\\1" raw_item "${candidate}") else() string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}") endif() if(gp_regex_cmp_count GREATER 1) string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}") endif() if(gp_regex_cmp_count GREATER 2) string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}") string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}") endif() # Use the raw_item as the list entries returned by this function. Use the # gp_resolve_item function to resolve it to an actual full path file if # necessary. # set(item "${raw_item}") # Add each item unless it is excluded: # set(add_item 1) if(item STREQUAL gp_install_id) set(add_item 0) endif() if(add_item AND ${exclude_system}) set(type "") gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type "${rpaths}") if(type STREQUAL "system") set(add_item 0) endif() endif() if(add_item) list(LENGTH ${prerequisites_var} list_length_before_append) gp_append_unique(${prerequisites_var} "${item}") list(LENGTH ${prerequisites_var} list_length_after_append) if(${recurse}) # If item was really added, this is the first time we have seen it. # Add it to unseen_prereqs so that we can recursively add *its* # prerequisites... # # But first: resolve its name to an absolute full path name such # that the analysis tools can simply accept it as input. # if(NOT list_length_before_append EQUAL list_length_after_append) gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item "${rpaths}") if(EXISTS "${resolved_item}") # Recurse only if we could resolve the item. # Otherwise the prerequisites_var list will be cleared set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") endif() endif() endif() endif() else() if(verbose) message(STATUS "ignoring non-matching line: '${candidate}'") endif() endif() endforeach() list(LENGTH ${prerequisites_var} prerequisites_var_length) if(prerequisites_var_length GREATER 0) list(SORT ${prerequisites_var}) endif() if(${recurse}) set(more_inputs ${unseen_prereqs}) foreach(input ${more_inputs}) get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}" "${rpaths}") endforeach() endif() # Make result visible to caller set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE) # See if we added anything list(LENGTH ${prerequisites_var} list_length_after_candidates) if(list_length_after_candidates GREATER ${list_length_before_candidates}) # Something has been added to prerequisites. Note this in cache set(targets_added "${${prerequisites_var}}") if (list_length_before_candidates GREATER 0) foreach(i RANGE 1 ${list_length_before_candidates}) # from 1 to old list length, remove first item, i.e. remove all pre-existing items list(REMOVE_AT targets_added 0) # not the most elegant way of cutting the list start. Simplifications welcome endforeach() endif() endif() # Update our cache set_property(GLOBAL PROPERTY ${prerequisites_cache_var_name} "${targets_added}") get_property(cache_variables GLOBAL PROPERTY prerequisites_cachevariables) if (cache_variables) list(APPEND cache_variables ${prerequisites_cache_var_name}) list(LENGTH cache_variables len) else() set(cache_variables ${prerequisites_cache_var_name}) endif() set_property(GLOBAL PROPERTY prerequisites_cachevariables ${cache_variables}) message("Analyzed prerequisites of ${target}") endfunction() function(list_prerequisites target) if(ARGC GREATER 1 AND NOT "${ARGV1}" STREQUAL "") set(all "${ARGV1}") else() set(all 1) endif() if(ARGC GREATER 2 AND NOT "${ARGV2}" STREQUAL "") set(exclude_system "${ARGV2}") else() set(exclude_system 0) endif() if(ARGC GREATER 3 AND NOT "${ARGV3}" STREQUAL "") set(verbose "${ARGV3}") else() set(verbose 0) endif() set(count 0) set(count_str "") set(print_count "${verbose}") set(print_prerequisite_type "${verbose}") set(print_target "${verbose}") set(type_str "") get_filename_component(exepath "${target}" PATH) set(prereqs "") get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "") if(print_target) message(STATUS "File '${target}' depends on:") endif() foreach(d ${prereqs}) math(EXPR count "${count} + 1") if(print_count) set(count_str "${count}. ") endif() if(print_prerequisite_type) gp_file_type("${target}" "${d}" type) set(type_str " (${type})") endif() message(STATUS "${count_str}${d}${type_str}") endforeach() endfunction() function(list_prerequisites_by_glob glob_arg glob_exp) message(STATUS "=============================================================================") message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'") message(STATUS "") file(${glob_arg} file_list ${glob_exp}) foreach(f ${file_list}) is_file_executable("${f}" is_f_executable) if(is_f_executable) message(STATUS "=============================================================================") list_prerequisites("${f}" ${ARGN}) message(STATUS "") endif() endforeach() endfunction() diff --git a/CMake/PackageDepends/MITK_Boost_Config.cmake b/CMake/PackageDepends/MITK_Boost_Config.cmake index 808ce4a1de..967e1e8124 100644 --- a/CMake/PackageDepends/MITK_Boost_Config.cmake +++ b/CMake/PackageDepends/MITK_Boost_Config.cmake @@ -1,17 +1,17 @@ if(MITK_USE_Boost_LIBRARIES) - find_package(Boost 1.65.1 REQUIRED COMPONENTS ${MITK_USE_Boost_LIBRARIES} QUIET) + find_package(Boost 1.68.0 REQUIRED COMPONENTS ${MITK_USE_Boost_LIBRARIES} QUIET) else() - find_package(Boost 1.65.1 REQUIRED QUIET) + find_package(Boost 1.68.0 REQUIRED QUIET) endif() list(APPEND ALL_INCLUDE_DIRECTORIES ${Boost_INCLUDE_DIRS}) if(Boost_LIBRARIES) if(WIN32) # Force dynamic linking list(APPEND ALL_COMPILE_OPTIONS -DBOOST_ALL_DYN_LINK) else() # Boost has an auto link feature (pragma comment lib) for Windows list(APPEND ALL_LIBRARIES ${Boost_LIBRARIES}) endif() endif() diff --git a/CMake/mitkFunctionCreateModule.cmake b/CMake/mitkFunctionCreateModule.cmake index 9ec5cd1148..ce984559eb 100644 --- a/CMake/mitkFunctionCreateModule.cmake +++ b/CMake/mitkFunctionCreateModule.cmake @@ -1,653 +1,659 @@ ################################################################## # # mitk_create_module # #! Creates a module for the automatic module dependency system within MITK. #! #! Example: #! #! \code #! mitk_create_module( #! DEPENDS PUBLIC MitkCore #! PACKAGE_DEPENDS #! PRIVATE Qt5|Xml+Networking #! PUBLIC ITK|Watershed #! \endcode #! #! The parameter specifies the name of the module which is used #! to create a logical target name. The parameter is optional in case the #! MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME variable evaluates to TRUE. The #! module name will then be derived from the directory name in which this #! function is called. #! #! If set, the following variables will be used to validate the module name: #! #! MITK_MODULE_NAME_REGEX_MATCH The module name must match this regular expression. #! MITK_MODULE_NAME_REGEX_NOT_MATCH The module name must not match this regular expression. #! #! If the MITK_MODULE_NAME_PREFIX variable is set, the module name will be prefixed #! with its contents. #! #! A modules source files are specified in a separate CMake file usually #! called files.cmake, located in the module root directory. The #! mitk_create_module() macro evaluates the following CMake variables #! from the files.cmake file: #! #! - CPP_FILES A list of .cpp files #! - H_FILES A list of .h files without a corresponding .cpp file #! - TXX_FILES A list of .txx files #! - RESOURCE_FILES A list of files (resources) which are embedded into the module #! - MOC_H_FILES A list of Qt header files which should be processed by the MOC #! - UI_FILES A list of .ui Qt UI files #! - QRC_FILES A list of .qrc Qt resource files #! - DOX_FILES A list of .dox Doxygen files #! #! List of variables available after the function is called: #! - MODULE_NAME #! - MODULE_TARGET #! - MODULE_IS_ENABLED #! - MODULE_SUBPROJECTS #! #! \sa mitk_create_executable #! #! Parameters (all optional): #! #! \param The module name (also used as target name) #! \param FILES_CMAKE File name of a CMake file setting source list variables #! (defaults to files.cmake) #! \param VERSION Module version number, e.g. "1.2.0" #! \param AUTOLOAD_WITH A module target name identifying the module which will #! trigger the automatic loading of this module #! \param DEPRECATED_SINCE Marks this modules as deprecated since #! \param DESCRIPTION A description for this module #! #! Multi-value Parameters (all optional): #! + #! \param SUBPROJECTS List of CDash labels #! \param INCLUDE_DIRS Include directories for this module: #! \verbatim #! [[PUBLIC|PRIVATE|INTERFACE] ...]... #! \endverbatim #! The default scope for include directories is PUBLIC. #! \param DEPENDS List of module dependencies: #! \verbatim #! [[PUBLIC|PRIVATE|INTERFACE] ...]... #! \endverbatim #! The default scope for module dependencies is PUBLIC. #! \param PACKAGE_DEPENDS List of public packages dependencies (e.g. Qt, VTK, etc.). #! Package dependencies have the following syntax: #! \verbatim #! [PUBLIC|PRIVATE|INTERFACE] PACKAGE[|COMPONENT1[+COMPONENT2]...] #! \endverbatim #! The default scope for package dependencies is PRIVATE. #! \param ADDITIONAL_LIBS List of additional private libraries linked to this module. #! The folder containing the library will be added to the global list of library search paths. #! \param CPP_FILES List of source files for this module. If the list is non-empty, #! the module does not need to provide a files.cmake file or FILES_CMAKE argument. #! \param H_FILES List of public header files for this module. It is recommended to use #! a files.cmake file instead. #! #! Options (optional) #! #! \param FORCE_STATIC Force building this module as a static library #! \param GCC_DEFAULT_VISIBILITY Do not use gcc visibility flags - all #! symbols will be exported #! \param NO_INIT Do not create CppMicroServices initialization code #! \param NO_FEATURE_INFO Do not create a feature info by calling add_feature_info() #! \param WARNINGS_NO_ERRORS Do not treat compiler warnings as errors # ################################################################## function(mitk_create_module) set(_macro_params VERSION # module version number, e.g. "1.2.0" EXPORT_DEFINE # export macro name for public symbols of this module (DEPRECATED) AUTOLOAD_WITH # a module target name identifying the module which will trigger the # automatic loading of this module FILES_CMAKE # file name of a CMake file setting source list variables # (defaults to files.cmake) DEPRECATED_SINCE # marks this modules as deprecated DESCRIPTION # a description for this module ) set(_macro_multiparams SUBPROJECTS # list of CDash labels INCLUDE_DIRS # include directories: [PUBLIC|PRIVATE|INTERFACE] INTERNAL_INCLUDE_DIRS # include dirs internal to this module (DEPRECATED) DEPENDS # list of modules this module depends on: [PUBLIC|PRIVATE|INTERFACE] DEPENDS_INTERNAL # list of modules this module internally depends on (DEPRECATED) PACKAGE_DEPENDS # list of "packages this module depends on (e.g. Qt, VTK, etc.): [PUBLIC|PRIVATE|INTERFACE] TARGET_DEPENDS # list of CMake targets this module should depend on ADDITIONAL_LIBS # list of addidtional private libraries linked to this module. CPP_FILES # list of cpp files H_FILES # list of header files: [PUBLIC|PRIVATE] ) set(_macro_options FORCE_STATIC # force building this module as a static library HEADERS_ONLY # this module is a headers-only library GCC_DEFAULT_VISIBILITY # do not use gcc visibility flags - all symbols will be exported NO_DEFAULT_INCLUDE_DIRS # do not add default include directories like "include" or "." NO_INIT # do not create CppMicroServices initialization code NO_FEATURE_INFO # do not create a feature info by calling add_feature_info() WARNINGS_NO_ERRORS # do not treat compiler warnings as errors EXECUTABLE # create an executable; do not use directly, use mitk_create_executable() instead C_MODULE # compile all source files as C sources CXX_MODULE # compile all source files as C++ sources ) cmake_parse_arguments(MODULE "${_macro_options}" "${_macro_params}" "${_macro_multiparams}" ${ARGN}) set(MODULE_NAME ${MODULE_UNPARSED_ARGUMENTS}) # ----------------------------------------------------------------- # Sanity checks if(NOT MODULE_NAME) if(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME) get_filename_component(MODULE_NAME ${CMAKE_CURRENT_SOURCE_DIR} NAME) else() message(SEND_ERROR "The module name must not be empty") endif() endif() set(_deprecated_args INTERNAL_INCLUDE_DIRS DEPENDS_INTERNAL EXPORT_DEFINE TARGET_DEPENDS HEADERS_ONLY) foreach(_deprecated_arg ${_deprecated_args}) if(MODULE_${_deprecated_arg}) message(WARNING "The ${_deprecated_arg} argument is deprecated") endif() endforeach() set(_module_type module) set(_Module_type Module) if(MODULE_EXECUTABLE) set(_module_type executable) set(_Module_type Executable) endif() if(MITK_MODULE_NAME_REGEX_MATCH) if(NOT ${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_MATCH}) message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" does not match the regular expression \"${MITK_MODULE_NAME_REGEX_MATCH}\".") endif() endif() if(MITK_MODULE_NAME_REGEX_NOT_MATCH) if(${MODULE_NAME} MATCHES ${MITK_MODULE_NAME_REGEX_NOT_MATCH}) message(SEND_ERROR "The ${_module_type} name \"${MODULE_NAME}\" must not match the regular expression \"${MITK_MODULE_NAME_REGEX_NOT_MATCH}\".") endif() endif() if(MITK_MODULE_NAME_PREFIX AND NOT MODULE_NAME MATCHES "^${MITK_MODULE_NAME_PREFIX}.*$") set(MODULE_NAME "${MITK_MODULE_NAME_PREFIX}${MODULE_NAME}") endif() if(NOT MODULE_FILES_CMAKE) set(MODULE_FILES_CMAKE files.cmake) endif() if(NOT IS_ABSOLUTE ${MODULE_FILES_CMAKE}) set(MODULE_FILES_CMAKE ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_FILES_CMAKE}) endif() if(NOT MODULE_SUBPROJECTS) if(MITK_DEFAULT_SUBPROJECTS) set(MODULE_SUBPROJECTS ${MITK_DEFAULT_SUBPROJECTS}) elseif(TARGET MITK-Modules) set(MODULE_SUBPROJECTS MITK-Modules) endif() endif() # check if the subprojects exist as targets if(MODULE_SUBPROJECTS) foreach(subproject ${MODULE_SUBPROJECTS}) if(NOT TARGET ${subproject}) message(SEND_ERROR "The subproject ${subproject} does not have a corresponding target") endif() endforeach() endif() # ----------------------------------------------------------------- # Check if module should be build set(MODULE_TARGET ${MODULE_NAME}) # assume worst case set(MODULE_IS_ENABLED 0) # first we check if we have an explicit module build list if(MITK_MODULES_TO_BUILD) list(FIND MITK_MODULES_TO_BUILD ${MODULE_NAME} _MOD_INDEX) if(_MOD_INDEX EQUAL -1) set(MODULE_IS_EXCLUDED 1) endif() endif() if(NOT MODULE_IS_EXCLUDED) # first of all we check for the dependencies _mitk_parse_package_args(${MODULE_PACKAGE_DEPENDS}) mitk_check_module_dependencies(MODULES ${MODULE_DEPENDS} PACKAGES ${PACKAGE_NAMES} MISSING_DEPENDENCIES_VAR _MISSING_DEP PACKAGE_DEPENDENCIES_VAR PACKAGE_NAMES) if(_MISSING_DEP) if(MODULE_NO_FEATURE_INFO) message("${_Module_type} ${MODULE_NAME} won't be built, missing dependency: ${_MISSING_DEP}") endif() set(MODULE_IS_ENABLED 0) else() set(MODULE_IS_ENABLED 1) # now check for every package if it is enabled. This overlaps a bit with # MITK_CHECK_MODULE ... foreach(_package ${PACKAGE_NAMES}) if((DEFINED MITK_USE_${_package}) AND NOT (MITK_USE_${_package})) message("${_Module_type} ${MODULE_NAME} won't be built. Turn on MITK_USE_${_package} if you want to use it.") set(MODULE_IS_ENABLED 0) break() endif() endforeach() endif() endif() # ----------------------------------------------------------------- # Start creating the module if(MODULE_IS_ENABLED) # clear variables defined in files.cmake set(RESOURCE_FILES ) set(CPP_FILES ) set(H_FILES ) set(TXX_FILES ) set(DOX_FILES ) set(UI_FILES ) set(MOC_H_FILES ) set(QRC_FILES ) # clear other variables set(Q${KITNAME}_GENERATED_CPP ) set(Q${KITNAME}_GENERATED_MOC_CPP ) set(Q${KITNAME}_GENERATED_QRC_CPP ) set(Q${KITNAME}_GENERATED_UI_CPP ) # check and set-up auto-loading if(MODULE_AUTOLOAD_WITH) if(NOT TARGET "${MODULE_AUTOLOAD_WITH}") message(SEND_ERROR "The module target \"${MODULE_AUTOLOAD_WITH}\" specified as the auto-loading module for \"${MODULE_NAME}\" does not exist") endif() endif() set(_module_autoload_meta_target "${CMAKE_PROJECT_NAME}-autoload") # create a meta-target if it does not already exist if(NOT TARGET ${_module_autoload_meta_target}) add_custom_target(${_module_autoload_meta_target}) endif() if(NOT MODULE_EXPORT_DEFINE) set(MODULE_EXPORT_DEFINE ${MODULE_NAME}_EXPORT) endif() if(MITK_GENERATE_MODULE_DOT) message("MODULEDOTNAME ${MODULE_NAME}") foreach(dep ${MODULE_DEPENDS}) message("MODULEDOT \"${MODULE_NAME}\" -> \"${dep}\" ; ") endforeach(dep) endif(MITK_GENERATE_MODULE_DOT) if (EXISTS ${MODULE_FILES_CMAKE}) include(${MODULE_FILES_CMAKE}) endif() if(MODULE_CPP_FILES) list(APPEND CPP_FILES ${MODULE_CPP_FILES}) endif() if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src") # Preprend the "src" directory to the cpp file list set(_cpp_files ${CPP_FILES}) set(CPP_FILES ) foreach(_cpp_file ${_cpp_files}) list(APPEND CPP_FILES "src/${_cpp_file}") endforeach() endif() if(CPP_FILES OR RESOURCE_FILES OR UI_FILES OR MOC_H_FILES OR QRC_FILES) set(MODULE_HEADERS_ONLY 0) if(MODULE_C_MODULE) set_source_files_properties(${CPP_FILES} PROPERTIES LANGUAGE C) elseif(MODULE_CXX_MODULE) set_source_files_properties(${CPP_FILES} PROPERTIES LANGUAGE CXX) endif() else() set(MODULE_HEADERS_ONLY 1) if(MODULE_AUTOLOAD_WITH) message(SEND_ERROR "A headers only module cannot be auto-loaded") endif() endif() set(module_c_flags ) set(module_c_flags_debug ) set(module_c_flags_release ) set(module_cxx_flags ) set(module_cxx_flags_debug ) set(module_cxx_flags_release ) if(MODULE_GCC_DEFAULT_VISIBILITY OR NOT CMAKE_COMPILER_IS_GNUCXX) # We only support hidden visibility for gcc for now. Clang still has troubles with # correctly marking template declarations and explicit template instantiations as exported. # See http://comments.gmane.org/gmane.comp.compilers.clang.scm/50028 # and http://llvm.org/bugs/show_bug.cgi?id=10113 set(CMAKE_CXX_VISIBILITY_PRESET default) set(CMAKE_VISIBILITY_INLINES_HIDDEN 0) else() set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) endif() if(NOT MODULE_WARNINGS_NO_ERRORS) if(MSVC_VERSION) mitkFunctionCheckCAndCXXCompilerFlags("/WX" module_c_flags module_cxx_flags) + # this would turn on unused parameter warnings, but unfortunately MSVC cannot + # distinguish yet between internal and external headers so this would be triggered + # a lot by external code. There is support for it on the way so this line could be + # reactivated after https://gitlab.kitware.com/cmake/cmake/issues/17904 has been fixed. + # mitkFunctionCheckCAndCXXCompilerFlags("/w34100" module_c_flags module_cxx_flags) else() mitkFunctionCheckCAndCXXCompilerFlags(-Werror module_c_flags module_cxx_flags) # The flag "c++0x-static-nonintegral-init" has been renamed in newer Clang # versions to "static-member-init", see # http://clang-developers.42468.n3.nabble.com/Wc-0x-static-nonintegral-init-gone-td3999651.html # # Also, older Clang and seemingly all gcc versions do not warn if unknown # "-no-*" flags are used, so CMake will happily append any -Wno-* flag to the # command line. This may get confusing if unrelated compiler errors happen and # the error output then additionally contains errors about unknown flags (which # is not the case if there were no compile errors). # # So instead of using -Wno-* we use -Wno-error=*, which will be properly rejected by # the compiler and if applicable, prints the specific warning as a real warning and # not as an error (although -Werror was given). mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=c++0x-static-nonintegral-init" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=static-member-init" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=unknown-warning" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=gnu" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=class-memaccess" module_c_flags module_cxx_flags) mitkFunctionCheckCAndCXXCompilerFlags("-Wno-error=inconsistent-missing-override" module_c_flags module_cxx_flags) endif() endif() if(MODULE_FORCE_STATIC) set(_STATIC STATIC) else() set(_STATIC ) endif(MODULE_FORCE_STATIC) if(NOT MODULE_HEADERS_ONLY) if(NOT MODULE_NO_INIT OR RESOURCE_FILES) find_package(CppMicroServices QUIET NO_MODULE REQUIRED) endif() if(NOT MODULE_NO_INIT) usFunctionGenerateModuleInit(CPP_FILES) endif() set(binary_res_files ) set(source_res_files ) if(RESOURCE_FILES) if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/resource") set(res_dir resource) elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Resources") set(res_dir Resources) else() message(SEND_ERROR "Resources specified but ${CMAKE_CURRENT_SOURCE_DIR}/resource directory not found.") endif() foreach(res_file ${RESOURCE_FILES}) if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${res_dir}/${res_file}) list(APPEND binary_res_files "${res_file}") else() list(APPEND source_res_files "${res_file}") endif() endforeach() # Add a source level dependencies on resource files usFunctionGetResourceSource(TARGET ${MODULE_TARGET} OUT CPP_FILES) endif() endif() if(MITK_USE_Qt5) if(UI_FILES) qt5_wrap_ui(Q${KITNAME}_GENERATED_UI_CPP ${UI_FILES}) endif() if(MOC_H_FILES) qt5_wrap_cpp(Q${KITNAME}_GENERATED_MOC_CPP ${MOC_H_FILES} OPTIONS -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) endif() if(QRC_FILES) qt5_add_resources(Q${KITNAME}_GENERATED_QRC_CPP ${QRC_FILES}) endif() endif() set(Q${KITNAME}_GENERATED_CPP ${Q${KITNAME}_GENERATED_CPP} ${Q${KITNAME}_GENERATED_UI_CPP} ${Q${KITNAME}_GENERATED_MOC_CPP} ${Q${KITNAME}_GENERATED_QRC_CPP}) mitkFunctionOrganizeSources( SOURCE ${CPP_FILES} HEADER ${H_FILES} TXX ${TXX_FILES} DOC ${DOX_FILES} UI ${UI_FILES} QRC ${QRC_FILES} MOC ${Q${KITNAME}_GENERATED_MOC_CPP} GEN_QRC ${Q${KITNAME}_GENERATED_QRC_CPP} GEN_UI ${Q${KITNAME}_GENERATED_UI_CPP} ) set(coverage_sources ${CPP_FILES} ${H_FILES} ${GLOBBED__H_FILES} ${CORRESPONDING__H_FILES} ${TXX_FILES} ${TOOL_CPPS} ${TOOL_GUI_CPPS}) if(MODULE_SUBPROJECTS) set_property(SOURCE ${coverage_sources} APPEND PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) endif() # --------------------------------------------------------------- # Create the actual module target if(MODULE_HEADERS_ONLY) add_library(${MODULE_TARGET} INTERFACE) else() if(MODULE_EXECUTABLE) add_executable(${MODULE_TARGET} ${MODULE_CPP_FILES} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) set(_us_module_name main) else() add_library(${MODULE_TARGET} ${_STATIC} ${coverage_sources} ${CPP_FILES_GENERATED} ${Q${KITNAME}_GENERATED_CPP} ${DOX_FILES} ${UI_FILES} ${QRC_FILES}) set(_us_module_name ${MODULE_TARGET}) endif() # Apply properties to the module target. target_compile_definitions(${MODULE_TARGET} PRIVATE US_MODULE_NAME=${_us_module_name}) if(MODULE_C_MODULE) if(module_c_flags) string(REPLACE " " ";" module_c_flags "${module_c_flags}") target_compile_options(${MODULE_TARGET} PRIVATE ${module_c_flags}) endif() if(module_c_flags_debug) string(REPLACE " " ";" module_c_flags_debug "${module_c_flags_debug}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_c_flags_debug}>) endif() if(module_c_flags_release) string(REPLACE " " ";" module_c_flags_release "${module_c_flags_release}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_c_flags_release}>) endif() else() if(module_cxx_flags) string(REPLACE " " ";" module_cxx_flags "${module_cxx_flags}") target_compile_options(${MODULE_TARGET} PRIVATE ${module_cxx_flags}) endif() if(module_cxx_flags_debug) string(REPLACE " " ";" module_cxx_flags_debug "${module_cxx_flags_debug}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_cxx_flags_debug}>) endif() if(module_cxx_flags_release) string(REPLACE " " ";" module_cxx_flags_release "${module_cxx_flags_release}") target_compile_options(${MODULE_TARGET} PRIVATE $<$:${module_cxx_flags_release}>) endif() endif() set_property(TARGET ${MODULE_TARGET} PROPERTY US_MODULE_NAME ${_us_module_name}) # Add additional library search directories to a global property which # can be evaluated by other CMake macros, e.g. our install scripts. if(MODULE_ADDITIONAL_LIBS) target_link_libraries(${MODULE_TARGET} PRIVATE ${MODULE_ADDITIONAL_LIBS}) get_property(_mitk_additional_library_search_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) foreach(_lib_filepath ${MODULE_ADDITIONAL_LIBS}) get_filename_component(_search_path "${_lib_filepath}" PATH) if(_search_path) list(APPEND _mitk_additional_library_search_paths "${_search_path}") endif() endforeach() if(_mitk_additional_library_search_paths) list(REMOVE_DUPLICATES _mitk_additional_library_search_paths) set_property(GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS ${_mitk_additional_library_search_paths}) endif() endif() # add the target name to a global property which is used in the top-level # CMakeLists.txt file to export the target set_property(GLOBAL APPEND PROPERTY MITK_MODULE_TARGETS ${MODULE_TARGET}) if(MODULE_AUTOLOAD_WITH) # for auto-loaded modules, adapt the output directory add_dependencies(${_module_autoload_meta_target} ${MODULE_TARGET}) if(WIN32) set(_module_output_prop RUNTIME_OUTPUT_DIRECTORY) else() set(_module_output_prop LIBRARY_OUTPUT_DIRECTORY) endif() set(_module_output_dir ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) get_target_property(_module_is_imported ${MODULE_AUTOLOAD_WITH} IMPORTED) if(NOT _module_is_imported) # if the auto-loading module is not imported, get its location # and put the auto-load module relative to it. get_target_property(_module_output_dir ${MODULE_AUTOLOAD_WITH} ${_module_output_prop}) set_target_properties(${MODULE_TARGET} PROPERTIES ${_module_output_prop} ${_module_output_dir}/${MODULE_AUTOLOAD_WITH}) else() set_target_properties(${MODULE_TARGET} PROPERTIES ${_module_output_prop} ${CMAKE_${_module_output_prop}}/${MODULE_AUTOLOAD_WITH}) endif() set_target_properties(${MODULE_TARGET} PROPERTIES MITK_AUTOLOAD_DIRECTORY ${MODULE_AUTOLOAD_WITH}) # add the auto-load module name as a property set_property(TARGET ${MODULE_AUTOLOAD_WITH} APPEND PROPERTY MITK_AUTOLOAD_TARGETS ${MODULE_TARGET}) endif() if(binary_res_files) usFunctionAddResources(TARGET ${MODULE_TARGET} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${res_dir} FILES ${binary_res_files}) endif() if(source_res_files) usFunctionAddResources(TARGET ${MODULE_TARGET} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${res_dir} FILES ${source_res_files}) endif() if(binary_res_files OR source_res_files) usFunctionEmbedResources(TARGET ${MODULE_TARGET}) endif() if(MODULE_DEPRECATED_SINCE) set_property(TARGET ${MODULE_TARGET} PROPERTY MITK_MODULE_DEPRECATED_SINCE ${MODULE_DEPRECATED_SINCE}) endif() # create export macros if (NOT MODULE_EXECUTABLE) set(_export_macro_name ) if(MITK_LEGACY_EXPORT_MACRO_NAME) set(_export_macro_names EXPORT_MACRO_NAME ${MODULE_EXPORT_DEFINE} NO_EXPORT_MACRO_NAME ${MODULE_NAME}_NO_EXPORT DEPRECATED_MACRO_NAME ${MODULE_NAME}_DEPRECATED NO_DEPRECATED_MACRO_NAME ${MODULE_NAME}_NO_DEPRECATED ) endif() generate_export_header(${MODULE_NAME} ${_export_macro_names} EXPORT_FILE_NAME ${MODULE_NAME}Exports.h ) endif() target_include_directories(${MODULE_TARGET} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) endif() # --------------------------------------------------------------- # Properties for both header-only and compiled modules if(MODULE_HEADERS_ONLY) set(_module_property_type INTERFACE) else() set(_module_property_type PUBLIC) endif() if(MODULE_TARGET_DEPENDS) add_dependencies(${MODULE_TARGET} ${MODULE_TARGET_DEPENDS}) endif() if(MODULE_SUBPROJECTS AND NOT MODULE_HEADERS_ONLY) set_property(TARGET ${MODULE_TARGET} PROPERTY LABELS ${MODULE_SUBPROJECTS} MITK) foreach(subproject ${MODULE_SUBPROJECTS}) add_dependencies(${subproject} ${MODULE_TARGET}) endforeach() endif() set(DEPENDS "${MODULE_DEPENDS}") if(NOT MODULE_NO_INIT AND NOT MODULE_HEADERS_ONLY) # Add a CppMicroServices dependency implicitly, since it is # needed for the generated "module initialization" code. set(DEPENDS "CppMicroServices;${DEPENDS}") endif() if(DEPENDS OR MODULE_PACKAGE_DEPENDS) mitk_use_modules(TARGET ${MODULE_TARGET} MODULES ${DEPENDS} PACKAGES ${MODULE_PACKAGE_DEPENDS} ) endif() if(NOT MODULE_C_MODULE) target_compile_features(${MODULE_TARGET} ${_module_property_type} ${MITK_CXX_FEATURES}) endif() # add include directories if(MODULE_INTERNAL_INCLUDE_DIRS) target_include_directories(${MODULE_TARGET} PRIVATE ${MODULE_INTERNAL_INCLUDE_DIRS}) endif() if(NOT MODULE_NO_DEFAULT_INCLUDE_DIRS) if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/include) target_include_directories(${MODULE_TARGET} ${_module_property_type} include) else() target_include_directories(${MODULE_TARGET} ${_module_property_type} .) endif() if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/src) target_include_directories(${MODULE_TARGET} PRIVATE src) endif() endif() target_include_directories(${MODULE_TARGET} ${_module_property_type} ${MODULE_INCLUDE_DIRS}) endif() # ----------------------------------------------------------------- # Record missing dependency information if(_MISSING_DEP) if(MODULE_DESCRIPTION) set(MODULE_DESCRIPTION "${MODULE_DESCRIPTION} (missing dependencies: ${_MISSING_DEP})") else() set(MODULE_DESCRIPTION "(missing dependencies: ${_MISSING_DEP})") endif() endif() if(NOT MODULE_NO_FEATURE_INFO) add_feature_info(${MODULE_NAME} MODULE_IS_ENABLED "${MODULE_DESCRIPTION}") endif() set(MODULE_NAME ${MODULE_NAME} PARENT_SCOPE) set(MODULE_TARGET ${MODULE_TARGET} PARENT_SCOPE) set(MODULE_IS_ENABLED ${MODULE_IS_ENABLED} PARENT_SCOPE) set(MODULE_SUBPROJECTS ${MODULE_SUBPROJECTS} PARENT_SCOPE) endfunction() diff --git a/CMake/mitkSetupCPack.cmake b/CMake/mitkSetupCPack.cmake index 53e40e34b4..11471e6c53 100644 --- a/CMake/mitkSetupCPack.cmake +++ b/CMake/mitkSetupCPack.cmake @@ -1,124 +1,152 @@ # # First, set the generator variable # if(NOT CPACK_GENERATOR) if(WIN32) find_program(NSIS_MAKENSIS NAMES makensis PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\NSIS] DOC "Where is makensis.exe located" ) if(NOT NSIS_MAKENSIS) set(CPACK_GENERATOR ZIP) else() set(CPACK_GENERATOR "NSIS;ZIP") endif(NOT NSIS_MAKENSIS) else() if(APPLE) set(CPACK_GENERATOR DragNDrop) else() set(CPACK_GENERATOR TGZ) endif() endif() endif(NOT CPACK_GENERATOR) # Set Redistributable information for windows if(${CMAKE_SYSTEM_NAME} MATCHES Windows) include(mitkFunctionGetMSVCVersion) mitkFunctionGetMSVCVersion() set(CPACK_VISUAL_STUDIO_VERSION_MAJOR "${VISUAL_STUDIO_VERSION_MAJOR}") set(CPACK_VISUAL_STUDIO_PRODUCT_NAME "${VISUAL_STUDIO_PRODUCT_NAME}") set(CPACK_LIBRARY_ARCHITECTURE "${CMAKE_LIBRARY_ARCHITECTURE}") - set(CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE "" CACHE FILEPATH "Path to the appropriate Microsoft Visual Studio Redistributable") + + # Visual Studio 2017 already comes with redistributable installers. + # Try to find the right one. + + set(vswhere "$ENV{PROGRAMFILES\(X86\)}\\Microsoft Visual Studio\\Installer\\vswhere.exe") + + if(EXISTS ${vswhere}) + execute_process(COMMAND ${vswhere} -latest -property installationPath + OUTPUT_VARIABLE installationPath + OUTPUT_STRIP_TRAILING_WHITESPACE) + file(TO_CMAKE_PATH ${installationPath} installationPath) + set(redistPath "${installationPath}/VC/Redist/MSVC") + file(GLOB redistPath "${installationPath}/VC/Redist/MSVC/*") + list(LENGTH redistPath length) + if(length EQUAL 1) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(redistPath "${redistPath}/vc_redist.x64.exe") + else() + set(redistPath "${redistPath}/vc_redist.x86.exe") + endif() + if(EXISTS ${redistPath}) + set(CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE ${redistPath} CACHE FILEPATH "Path to the appropriate Microsoft Visual Studio Redistributable") + endif() + endif() + endif() + + if(NOT DEFINED CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE) + set(CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE "" CACHE FILEPATH "Path to the appropriate Microsoft Visual Studio Redistributable") + endif() endif() if(EXISTS ${CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE} ) install(PROGRAMS ${CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE} DESTINATION thirdpartyinstallers) get_filename_component(CPACK_REDISTRIBUTABLE_FILE_NAME ${CMAKE_${CPACK_VISUAL_STUDIO_PRODUCT_NAME}_REDISTRIBUTABLE} NAME ) endif() # On windows set default install directory appropriately for 32 and 64 bit # installers if not already set if(WIN32 AND NOT CPACK_NSIS_INSTALL_ROOT) if(CMAKE_CL_64) set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES64") else() set(CPACK_NSIS_INSTALL_ROOT "$PROGRAMFILES") endif() endif() # By default, do not warn when built on machines using only VS Express if(NOT DEFINED CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS) set(CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS_NO_WARNINGS ON) endif() # include required mfc libraries include(InstallRequiredSystemLibraries) set(CPACK_PACKAGE_NAME "MITK") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MITK is a medical image processing tool") set(CPACK_PACKAGE_VENDOR "German Cancer Research Center (DKFZ)") set(CPACK_PACKAGE_DESCRIPTION_FILE "${MITK_SOURCE_DIR}/LICENSE.txt") set(CPACK_RESOURCE_FILE_LICENSE "${MITK_SOURCE_DIR}/LICENSE.txt") set(CPACK_PACKAGE_VERSION_MAJOR "${MITK_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${MITK_VERSION_MINOR}") # tell cpack to strip all debug symbols from all files set(CPACK_STRIP_FILES ON) # append revision number if available if(MITK_REVISION_ID AND MITK_VERSION_PATCH STREQUAL "99") if(MITK_WC_TYPE STREQUAL "git") set(git_hash ${MITK_REVISION_ID}) string(LENGTH "${git_hash}" hash_length) if(hash_length GREATER 6) string(SUBSTRING ${git_hash} 0 6 git_hash) endif() set(CPACK_PACKAGE_VERSION_PATCH "${MITK_VERSION_PATCH}_r${git_hash}") else() set(CPACK_PACKAGE_VERSION_PATCH "${MITK_VERSION_PATCH}_r${MITK_REVISION_ID}") endif() else() set(CPACK_PACKAGE_VERSION_PATCH "${MITK_VERSION_PATCH}") endif() # set version set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") # determine possible system specific extension set(CPACK_PACKAGE_ARCH "unkown-architecture") if(${CMAKE_SYSTEM_NAME} MATCHES Windows) if(CMAKE_CL_64) set(CPACK_PACKAGE_ARCH "win64") elseif(WIN32) set(CPACK_PACKAGE_ARCH "win32") endif() endif(${CMAKE_SYSTEM_NAME} MATCHES Windows) if(${CMAKE_SYSTEM_NAME} MATCHES Linux) if(${CMAKE_SYSTEM_PROCESSOR} MATCHES i686) set(CPACK_PACKAGE_ARCH "linux32") elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES x86_64) if(${CMAKE_CXX_FLAGS} MATCHES " -m32 ") set(CPACK_PACKAGE_ARCH "linux32") else() set(CPACK_PACKAGE_ARCH "linux64") endif(${CMAKE_CXX_FLAGS} MATCHES " -m32 ") else() set(CPACK_PACKAGE_ARCH "linux") endif() endif(${CMAKE_SYSTEM_NAME} MATCHES Linux) if(${CMAKE_SYSTEM_NAME} MATCHES Darwin) set(CPACK_PACKAGE_ARCH "mac64") endif(${CMAKE_SYSTEM_NAME} MATCHES Darwin) set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${CPACK_PACKAGE_ARCH}") diff --git a/CMakeExternals/Boost.cmake b/CMakeExternals/Boost.cmake index 76b7ff7aec..636c90e7e8 100644 --- a/CMakeExternals/Boost.cmake +++ b/CMakeExternals/Boost.cmake @@ -1,216 +1,208 @@ #----------------------------------------------------------------------------- # Boost #----------------------------------------------------------------------------- include(mitkFunctionGetMSVCVersion) # Sanity checks if(DEFINED BOOST_ROOT AND NOT EXISTS ${BOOST_ROOT}) message(FATAL_ERROR "BOOST_ROOT variable is defined but corresponds to non-existing directory") endif() string(REPLACE "^^" ";" MITK_USE_Boost_LIBRARIES "${MITK_USE_Boost_LIBRARIES}") set(proj Boost) set(proj_DEPENDENCIES ) set(Boost_DEPENDS ${proj}) if(NOT DEFINED BOOST_ROOT AND NOT MITK_USE_SYSTEM_Boost) - set(_boost_version 1_65_1) + set(_boost_version 1_68_0) set(_boost_install_include_dir include/boost) if(WIN32) set(_boost_install_include_dir include/boost-${_boost_version}/boost) endif() set(_boost_libs ) set(_with_boost_libs ) set(_install_lib_dir ) # Set the boost root to the libraries install directory set(BOOST_ROOT "${ep_prefix}") if(MITK_USE_Boost_LIBRARIES) string(REPLACE ";" "," _boost_libs "${MITK_USE_Boost_LIBRARIES}") foreach(_boost_lib ${MITK_USE_Boost_LIBRARIES}) list(APPEND _with_boost_libs ${_with_boost_libs} --with-${_boost_lib}) endforeach() endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_boost_address_model "address-model=64") else() set(_boost_address_model "address-model=32") endif() if(WIN32) set(_shell_extension .bat) set(_boost_layout) if(MSVC) mitkFunctionGetMSVCVersion() # Work around due to BOOST toolset limitations # Remove if task T24222 is fixed if(VISUAL_STUDIO_VERSION_MAJOR EQUAL 14 AND VISUAL_STUDIO_VERSION_MINOR GREATER 0) set(VISUAL_STUDIO_VERSION_MINOR 1) endif() # End Work around set(_boost_with_toolset "vc${VISUAL_STUDIO_VERSION_MAJOR}") if(${VISUAL_STUDIO_VERSION_MINOR}) set(_boost_with_toolset "${_boost_with_toolset}${VISUAL_STUDIO_VERSION_MINOR}") endif() set(_boost_toolset "msvc-${VISUAL_STUDIO_VERSION_MAJOR}.${VISUAL_STUDIO_VERSION_MINOR}") endif() set(_install_lib_dir "--libdir=/bin") set(WIN32_CMAKE_SCRIPT ${ep_prefix}/src/${proj}-cmake/MoveBoostLibsToLibDirForWindows.cmake) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeExternals/MoveBoostLibsToLibDirForWindows.cmake.in ${WIN32_CMAKE_SCRIPT} @ONLY) set(_windows_move_libs_cmd COMMAND ${CMAKE_COMMAND} -P ${WIN32_CMAKE_SCRIPT}) else() set(_shell_extension .sh) set(_boost_layout "--layout=tagged") endif() if(UNIX AND NOT APPLE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(_boost_with_toolset "gcc") elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(_boost_with_toolset "clang") else() message(FATAL_ERROR "Compiler '${CMAKE_CXX_COMPILER_ID}' not supported. Use GNU or Clang instead.") endif() get_filename_component(_cxx_compiler_name "${CMAKE_CXX_COMPILER}" NAME) string(REGEX MATCH "^[0-9]+\\.[0-9]+" _compiler_version "${CMAKE_CXX_COMPILER_VERSION}") if(_cxx_compiler_name MATCHES "${_compiler_version}") set(_boost_toolset "${_boost_with_toolset}-${_compiler_version}") endif() endif() if(_boost_toolset) set(_boost_toolset "--toolset=${_boost_toolset}") endif() set (APPLE_SYSROOT_FLAG) if(APPLE) set(APPLE_CMAKE_SCRIPT ${ep_prefix}/src/${proj}-cmake/ChangeBoostLibsInstallNameForMac.cmake) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeExternals/ChangeBoostLibsInstallNameForMac.cmake.in ${APPLE_CMAKE_SCRIPT} @ONLY) set(_macos_change_install_name_cmd COMMAND ${CMAKE_COMMAND} -P ${APPLE_CMAKE_SCRIPT}) # Set OSX_SYSROOT if (NOT ${CMAKE_OSX_SYSROOT} STREQUAL "") set (APPLE_SYSROOT_FLAG --sysroot=${CMAKE_OSX_SYSROOT}) endif() endif() set(_boost_variant "$<$:debug>$<$:release>") set(_boost_link shared) if(NOT BUILD_SHARED_LIBS) set(_boost_link static) endif() set(_boost_cxxflags ) if(CMAKE_CXX_FLAGS OR MITK_CXX14_FLAG) set(_boost_cxxflags "cxxflags=${MITK_CXX14_FLAG} ${CMAKE_CXX_FLAGS}") endif() set(_boost_linkflags ) if(BUILD_SHARED_LIBS AND _install_rpath_linkflag) set(_boost_linkflags "linkflags=${_install_rpath_linkflag}") endif() set(_build_cmd "/b2" ${APPLE_SYSROOT_FLAG} ${_boost_toolset} ${_boost_layout} "--prefix=" ${_install_lib_dir} ${_with_boost_libs} # Use the option below to view the shell commands (for debugging) #-d+4 variant=${_boost_variant} link=${_boost_link} ${_boost_cxxflags} ${_boost_linkflags} ${_boost_address_model} threading=multi runtime-link=shared # Some distributions site config breaks boost build # For example on Gentoo: http://stackoverflow.com/questions/23013433/how-to-install-modular-boost --ignore-site-config -q ) if(MITK_USE_Boost_LIBRARIES) set(_boost_build_cmd BUILD_COMMAND ${_build_cmd} install ${_macos_change_install_name_cmd} ${_windows_move_libs_cmd}) else() set(_boost_build_cmd BUILD_COMMAND ${CMAKE_COMMAND} -E echo "copying Boost headers..." COMMAND ${CMAKE_COMMAND} -E copy_directory "/boost" "/${_boost_install_include_dir}") endif() - set(_boost_patch_cmd ) - - if(WIN32) - if(MSVC) - if(NOT (VISUAL_STUDIO_VERSION_MAJOR LESS 14)) - set(_boost_patch_cmd PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/Boost.patch) - endif() - endif() - endif() + set(_boost_patch_cmd PATCH_COMMAND ${PATCH_COMMAND} --binary -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/Boost.patch) ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/boost_${_boost_version}.7z - URL_MD5 72ab92cb936f93d33b8b313aee2dd47a + URL_MD5 ae25f29cdb82cf07e8e26187ddf7d330 BINARY_DIR "${ep_prefix}/src/${proj}" ${_boost_patch_cmd} CONFIGURE_COMMAND "/bootstrap${_shell_extension}" --with-toolset=${_boost_with_toolset} --with-libraries=${_boost_libs} "--prefix=" ${_boost_build_cmd} INSTALL_COMMAND "" # done in BUILD_COMMAND DEPENDS ${proj_DEPENDENCIES} ) ExternalProject_Get_Property(${proj} install_dir) if(WIN32) set(BOOST_LIBRARYDIR "${install_dir}/lib") endif() # Manual install commands (for a MITK super-build install) # until the Boost CMake system is used. # We just copy the include directory install(DIRECTORY "${install_dir}/${_boost_install_include_dir}" DESTINATION "include" COMPONENT dev ) if(MITK_USE_Boost_LIBRARIES) # Copy the boost libraries file(GLOB _boost_libs "${install_dir}/lib/libboost*.so*" "${install_dir}/lib/libboost*.dylib") install(FILES ${_boost_libs} DESTINATION "lib" COMPONENT runtime) file(GLOB _boost_libs "${install_dir}/bin/libboost*.dll") install(FILES ${_boost_libs} DESTINATION "bin" COMPONENT runtime) file(GLOB _boost_libs "${install_dir}/lib/libboost*.lib" "${install_dir}/lib/libboost*.a") install(FILES ${_boost_libs} DESTINATION "lib" COMPONENT dev) endif() else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeExternals/Boost.patch b/CMakeExternals/Boost.patch index e902ac3699..225b537f47 100644 --- a/CMakeExternals/Boost.patch +++ b/CMakeExternals/Boost.patch @@ -1,14 +1,12 @@ ---- original/tools/build/src/engine/config_toolset.bat Sat Sep 02 12:56:19 2017 -+++ modified/tools/build/src/engine/config_toolset.bat Thu Oct 19 13:04:51 2017 -@@ -170,7 +170,10 @@ - if "_%BOOST_JAM_ARCH%_" == "__" set BOOST_JAM_ARCH=x86 - set BOOST_JAM_ARGS=%BOOST_JAM_ARGS% %BOOST_JAM_ARCH% - --if "_%VSINSTALLDIR%_" == "__" call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%Auxiliary\Build\vcvarsall.bat" %BOOST_JAM_ARGS% -+if "_%VSINSTALLDIR%_" == "__" ( -+ set VSCMD_START_DIR=%CD% -+ call :Call_If_Exists "%BOOST_JAM_TOOLSET_ROOT%Auxiliary\Build\vcvarsall.bat" %BOOST_JAM_ARGS% -+) - set "BOOST_JAM_CC=cl /nologo /RTC1 /Zi /MTd /Fobootstrap/ /Fdbootstrap/ -DNT -DYYDEBUG -wd4996 kernel32.lib advapi32.lib user32.lib" - set "BOOST_JAM_OPT_JAM=/Febootstrap\jam0" - set "BOOST_JAM_OPT_MKJAMBASE=/Febootstrap\mkjambase0" +--- boost_1_68_0.orig/boost/iostreams/detail/config/fpos.hpp 2018-08-01 22:50:55.000000000 +0200 ++++ boost_1_68_0/boost/iostreams/detail/config/fpos.hpp 2018-09-30 13:48:02.395309975 +0200 +@@ -25,7 +25,8 @@ + #include + + # if (defined(_YVALS) || defined(_CPPLIB_VER)) && !defined(__SGI_STL_PORT) && \ +- !defined(_STLPORT_VERSION) && !defined(__QNX__) && !defined(_VX_CPU) && !defined(__VXWORKS__) ++ !defined(_STLPORT_VERSION) && !defined(__QNX__) && !defined(_VX_CPU) && !defined(__VXWORKS__) \ ++ && !(defined(BOOST_MSVC) && _MSVC_STL_VERSION >= 141) + /**/ + + #include diff --git a/CMakeExternals/ChangeBoostLibsInstallNameForMac.cmake.in b/CMakeExternals/ChangeBoostLibsInstallNameForMac.cmake.in index a01d1f542d..e01d3a73bd 100644 --- a/CMakeExternals/ChangeBoostLibsInstallNameForMac.cmake.in +++ b/CMakeExternals/ChangeBoostLibsInstallNameForMac.cmake.in @@ -1,23 +1,23 @@ # Scan the MITK-Superbuild/ep/lib directory for *.dylib files and change their install names for mac -# On Mac OS X system each shared library usually has a install name which is the absolute path of the library. +# On macOS system each shared library usually has a install name which is the absolute path of the library. # For some reasons boost libs do not contain the absolute path but just their name # (e.g. "libboost_thread.dylib" should be named "") # Get all the shared libraries which are located in the Boost-install/lib directory file(GLOB dylibFiles @BOOST_ROOT@/lib/libboost*.dylib) # For each shared library call the install_name_tool in order to change the install name of the according library foreach(_dylib ${dylibFiles}) message("Fixing boost install name for lib: ${_dylib}") get_filename_component(_dylib_name ${_dylib} NAME) execute_process(COMMAND install_name_tool -id \@rpath/${_dylib_name} ${_dylib}) foreach(_dep_dylib ${dylibFiles}) get_filename_component(_dep_dylib_name ${_dep_dylib} NAME) execute_process(COMMAND install_name_tool -change ${_dep_dylib_name} \@rpath/${_dep_dylib_name} ${_dylib}) endforeach() endforeach() diff --git a/CMakeExternals/ITK-VNL-2018-05-16.patch b/CMakeExternals/ITK-VNL-2018-05-16.patch deleted file mode 100644 index 4832f7f38d..0000000000 --- a/CMakeExternals/ITK-VNL-2018-05-16.patch +++ /dev/null @@ -1,2048 +0,0 @@ -diff --git a/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt -index 2b85b7bc79..4c66ee43b4 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/CMakeLists.txt -@@ -12,26 +12,51 @@ - # Root vxl - # - # vxl-maintainers@lists.sf.net --cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR) -- --# Set policies for cmake --if( POLICY CMP0003 ) -- cmake_policy(SET CMP0003 NEW) --endif() --# Use @rpath on OS X --if( POLICY CMP0042 ) -- cmake_policy(SET CMP0042 NEW) -+if( "${CMAKE_CXX_STANDARD}" MATCHES "(11|14|17|20)") -+ # If building for modern C++ language standards, -+ # require use of newer cmake version -+ cmake_minimum_required(VERSION 3.9.5 FATAL_ERROR) -+else() -+ cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR) - endif() -+# Set policies consistent with newer versions of cmake -+# to ease integration with projects that require newer -+# cmake versions. -+ -+foreach(p -+ ## Only policies introduced after the cmake_minimum_required -+ ## version need to explicitly be set to NEW. -+ -+ ##----- Policies Introduced by CMake 3.10¶ -+ CMP0071 #: Let AUTOMOC and AUTOUIC process GENERATED files. -+ CMP0070 #: Define file(GENERATE) behavior for relative paths. -+ ##----- Policies Introduced by CMake 3.9 -+ CMP0069 #: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. -+ CMP0068 #: RPATH settings on macOS do not affect install_name. -+ ##----- Policies Introduced by CMake 3.8 -+ CMP0067 #: Honor language standard in try_compile() source-file signature. -+ ##----- Policies Introduced by CMake 3.7 -+ CMP0066 #: Honor per-config flags in try_compile() source-file signature. -+ ##----- Policies Introduced by CMake 3.4 -+ CMP0065 #: Do not add flags to export symbols from executables without the ENABLE_EXPORTS target property. -+ CMP0064 #: Support new TEST if() operator. -+ ) -+ if(POLICY ${p}) -+ cmake_policy(SET ${p} NEW) -+ endif() -+endforeach() - --# Honor visibility properties for static libraries --if( POLICY CMP0063 ) -- cmake_policy(SET CMP0063 NEW) --endif() - - project(vxl) - - include(CMakeDependentOption) - -+#Disable overzealous compiler warning. If the definition is truely missing a link error will be created. -+include(CheckCXXCompilerFlag) -+CHECK_CXX_COMPILER_FLAG(-Wno-undefined-var-template HAS_NO_UNDEFINED_VAR_TEMPLATE) -+if( HAS_NO_UNDEFINED_VAR_TEMPLATE ) -+ add_definitions( -Wno-undefined-var-template ) -+endif() - - find_program( MEMORYCHECK_COMMAND valgrind ) - if(MEMORYCHECK_COMMAND) -@@ -113,6 +138,7 @@ option(VXL_LEGACY_ERROR_REPORTING "Use old error reporting methods rather than e - if(VXL_LEGACY_ERROR_REPORTING) - add_definitions( -DVXL_LEGACY_ERROR_REPORTING ) - endif() -+option(VXL_RUN_FAILING_TESTS "Enable long-time failing tests. If tests are failing for a long time, turn them off by default." OFF) - - # Option to build Windows Unicode support, the string - # type of which is wchar_t, each character is a 16-bit unsigned integer. -@@ -232,7 +258,7 @@ add_subdirectory(core) - - # Optionally build the contributed libraries - if( EXISTS ${CMAKE_CURRENT_LIST_DIR}/contrib/CMakeLists.txt ) -- CMAKE_DEPENDENT_OPTION(BUILD_CONTRIB "Build the contributed libraries?" ON "BUILD_CORE_GEOMETRY;BUILD_CORE_NUMERICS;BUILD_CORE_UTILITIES;BUILD_CORE_SERIALISATION;BUILD_CORE_IMAGING" OFF) -+ CMAKE_DEPENDENT_OPTION(BUILD_CONTRIB "Build the contributed libraries?" OFF "BUILD_CORE_GEOMETRY;BUILD_CORE_NUMERICS;BUILD_CORE_UTILITIES;BUILD_CORE_SERIALISATION;BUILD_CORE_IMAGING" OFF) - add_subdirectory(contrib) - endif() - -diff --git a/Modules/ThirdParty/VNL/src/vxl/CTestConfig.cmake b/Modules/ThirdParty/VNL/src/vxl/CTestConfig.cmake -deleted file mode 100644 -index f2620f7bf6..0000000000 ---- a/Modules/ThirdParty/VNL/src/vxl/CTestConfig.cmake -+++ /dev/null -@@ -1,8 +0,0 @@ --# CTest Configuration for VXL --set(CTEST_PROJECT_NAME "VXL") --set(CTEST_NIGHTLY_START_TIME "22:00:00 EST") -- --set(CTEST_DROP_METHOD "http") --set(CTEST_DROP_SITE "open.cdash.org") --set(CTEST_DROP_LOCATION "/submit.php?project=vxl") --set(CTEST_DROP_SITE_CDASH TRUE) -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/FindClipper.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/FindClipper.cmake -new file mode 100644 -index 0000000000..ad941254ff ---- /dev/null -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/FindClipper.cmake -@@ -0,0 +1,41 @@ -+# -+# Find a CLIPPER library -+# -+# This file is used to manage using either a natively provided CLIPPER library or the one in v3p if provided. -+# -+# -+# As per the standard scheme the following definitions are used -+# CLIPPER_INCLUDE_DIR - where to find clipper.hxx -+# CLIPPER_LIBRARIES - the set of libraries to include to use CLIPPER. -+# CLIPPER_FOUND - TRUE, if available somewhere on the system. -+ -+# Additionally -+# VXL_USING_NATIVE_CLIPPER - True if we are using a CLIPPER library provided outside vxl (or v3p) -+ -+if( NOT CLIPPER_FOUND ) -+ -+ # If this FORCE variable is unset or is FALSE, try to find a native library. -+ if( NOT VXL_FORCE_V3P_CLIPPER ) -+ # ./FindGEOTIFF.cmake does this instead... -+ #include( ${MODULE_PATH}/NewCMake/FindGEOTIFF.cmake ) -+ find_package( CLIPPER QUIET ) -+ if( CLIPPER_FOUND ) -+ set(VXL_USING_NATIVE_CLIPPER "YES") -+ endif() -+ endif() -+ -+ # -+ # At some point, in a "release" version, it is possible that someone -+ # will not have the v3p clipper library, so make sure the headers -+ # exist. -+ # -+ if( NOT CLIPPER_FOUND ) -+ if(EXISTS ${VXL_ROOT_SOURCE_DIR}/v3p/clipper/clipper.h) -+ set( CLIPPER_FOUND "YES" ) -+ set( CLIPPER_INCLUDE_DIR ${clipper_BINARY_DIR} ${clipper_SOURCE_DIR}) -+ set( CLIPPER_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_DIR}/include/vxl/v3p/clipper) -+ set( CLIPPER_LIBRARIES clipper ) -+ endif() -+ endif() -+ -+endif() -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake -index 69e9ea9371..9ba8283a63 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/FindOpenCL.cmake -@@ -69,9 +69,11 @@ if(APPLE) - endif() - - if(UNIX) -- find_path( OPENCL_INCLUDE_PATH CL/cl_gl.h PATHS /usr/include /usr/include/nvidia-current /usr/local/cuda/include) -- find_path(OPENCL_LIBRARY_PATH libOpenCL.so PATHS /usr/lib /usr/lib/nvidia-current /usr/local/cuda/lib64 ${OPENCL_LIBRARY_PATH} ) -- find_library(OPENCL_LIBRARIES NAMES libOpenCL.so PATHS /usr/lib /usr/lib/nvidia-current ${OPENCL_LIBRARY_PATH} ) -+ file(GLOB AMD_DIR /opt/AMDAPPSDK-*/include) -+ find_path( OPENCL_INCLUDE_PATH CL/cl_gl.h PATHS /usr/include /usr/include/nvidia-current /usr/local/cuda/include HINTS ${AMD_DIR}) -+ file(GLOB AMD_DIR /opt/AMDAPPSDK-*/lib/x86_64/sdk /opt/AMDAPPSDK-*/lib/x86_64) -+ find_path(OPENCL_LIBRARY_PATH libOpenCL.so PATHS /usr/lib /usr/lib64 /usr/lib/nvidia-current /usr/local/cuda/lib64 ${OPENCL_LIBRARY_PATH} HINTS ${AMD_DIR} ) -+ find_library(OPENCL_LIBRARIES NAMES libOpenCL.so PATHS /usr/lib /usr/lib64 /usr/lib/nvidia-current ${OPENCL_LIBRARY_PATH} ) - if(OPENCL_INCLUDE_PATH) - if(OPENCL_LIBRARIES) - set(OPENCL_FOUND "YES") -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt -index b69c359257..9387e9b15c 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/NewCMake/readme.txt -@@ -5,9 +5,9 @@ To facilitate the deprecation of modules, place code similar to the - following in the FindXXX.cmake as soon as it becomes part of a CMake - release: - --# FIXME: When cmake_minimum_version reaches 2.6.2 the FindXXX -+# FIXME: When cmake_minimum_version reaches 3.3.0 the FindXXX - # module in this directory is not needed anymore. --IF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 2.6.1) -+IF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 3.3.0) - MESSAGE(FATAL_ERROR - "FindXXX not needed in vxl; it is now available in CMake.") --ENDIF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 2.6.1) -+ENDIF(CMAKE_MINIMUM_REQUIRED_VERSION GREATER 3.3.0) -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake -index b0d7dd49cd..ad54658342 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/Modules/VXLGenerateExportHeader.cmake -@@ -1,13 +1,5 @@ --# This version of GenerateExportHeader extends CMake's version to provide the --# _TEMPLATE_EXPORT macro. For templated class declarations, Windows --# must not have the export specification, while GCC must have the export --# specification. --# --# This macro is for templates with explicit instantiations built into a library. --# --# To avoid inadvertently overriding CMake's or another package's --# GenerateExportHeader, this version is named differently and adds a prefix to --# all global identifiers. -+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -+# file Copyright.txt or https://cmake.org/licensing for details. - - #.rst: - # VXLGenerateExportHeader -@@ -28,10 +20,12 @@ - # [EXPORT_FILE_NAME ] - # [DEPRECATED_MACRO_NAME ] - # [NO_EXPORT_MACRO_NAME ] -+# [INCLUDE_GUARD_NAME ] - # [STATIC_DEFINE ] - # [NO_DEPRECATED_MACRO_NAME ] - # [DEFINE_NO_DEPRECATED] - # [PREFIX_NAME ] -+# [CUSTOM_CONTENT_FROM_VARIABLE ] - # ) - # - # -@@ -71,9 +65,10 @@ - # - # The CMake fragment will generate a file in the - # ``${CMAKE_CURRENT_BINARY_DIR}`` called ``somelib_export.h`` containing the --# macros ``SOMELIB_EXPORT``, ``SOMELIB_TEMPLATE_EXPORT``, ``SOMELIB_NO_EXPORT``, --# ``SOMELIB_DEPRECATED``, ``SOMELIB_DEPRECATED_EXPORT`` and --# ``SOMELIB_DEPRECATED_NO_EXPORT``. -+# macros ``SOMELIB_EXPORT``, ``SOMELIB_NO_EXPORT``, ``SOMELIB_DEPRECATED``, -+# ``SOMELIB_DEPRECATED_EXPORT`` and ``SOMELIB_DEPRECATED_NO_EXPORT``. -+# They will be followed by content taken from the variable specified by -+# the ``CUSTOM_CONTENT_FROM_VARIABLE`` option, if any. - # The resulting file should be installed with other headers in the library. - # - # The ``BASE_NAME`` argument can be used to override the file name and the -@@ -91,7 +86,7 @@ - # ``OTHER_NAME_EXPORT``, ``OTHER_NAME_NO_EXPORT`` and ``OTHER_NAME_DEPRECATED`` - # etc. - # --# The ``BASE_NAME`` may be overridden by specifiying other options in the -+# The ``BASE_NAME`` may be overridden by specifying other options in the - # function. For example: - # - # .. code-block:: cmake -@@ -191,19 +186,6 @@ - # :prop_tgt:`CXX_VISIBILITY_PRESET <_VISIBILITY_PRESET>` and - # :prop_tgt:`VISIBILITY_INLINES_HIDDEN` instead. - --#============================================================================= --# Copyright 2011 Stephen Kelly --# --# Distributed under the OSI-approved BSD License (the "License"); --# see accompanying file Copyright.txt for details. --# --# This software is distributed WITHOUT ANY WARRANTY; without even the --# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --# See the License for more information. --#============================================================================= --# (To distribute this file outside of CMake, substitute the full --# License text for the above reference.) -- - include(CMakeParseArguments) - include(CheckCXXCompilerFlag) - -@@ -218,7 +200,7 @@ macro(_vxl_test_compiler_hidden_visibility) - - if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2") - set(GCC_TOO_OLD TRUE) -- elseif(CMAKE_COMPILER_IS_GNUC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") -+ elseif(CMAKE_COMPILER_IS_GNUCC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") - set(GCC_TOO_OLD TRUE) - elseif(CMAKE_CXX_COMPILER_ID MATCHES Intel AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0") - set(_INTEL_TOO_OLD TRUE) -@@ -236,14 +218,15 @@ macro(_vxl_test_compiler_hidden_visibility) - check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) - check_cxx_compiler_flag(-fvisibility-inlines-hidden - COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) -- option(USE_COMPILER_HIDDEN_VISIBILITY -- "Use HIDDEN visibility support if available." ON) -- mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) - endif() - endmacro() - - macro(_vxl_test_compiler_has_deprecated) -+ # NOTE: Some Embarcadero compilers silently compile __declspec(deprecated) -+ # without error, but this is not a documented feature and the attribute does -+ # not actually generate any warnings. - if(CMAKE_CXX_COMPILER_ID MATCHES Borland -+ OR CMAKE_CXX_COMPILER_ID MATCHES Embarcadero - OR CMAKE_CXX_COMPILER_ID MATCHES HP - OR GCC_TOO_OLD - OR CMAKE_CXX_COMPILER_ID MATCHES PGI -@@ -270,8 +253,6 @@ macro(_VXL_DO_SET_MACRO_VALUES TARGET_LIBRARY) - set(DEFINE_DEPRECATED) - set(DEFINE_EXPORT) - set(DEFINE_IMPORT) -- set(DEFINE_TEMPLATE_EXPORT) -- set(DEFINE_TEMPLATE_IMPORT) - set(DEFINE_NO_EXPORT) - - if (COMPILER_HAS_DEPRECATED_ATTR) -@@ -288,12 +269,12 @@ macro(_VXL_DO_SET_MACRO_VALUES TARGET_LIBRARY) - set(DEFINE_IMPORT "__declspec(dllimport)") - set(DEFINE_TEMPLATE_EXPORT) - set(DEFINE_TEMPLATE_IMPORT) -- elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) -+ elseif(COMPILER_HAS_HIDDEN_VISIBILITY) - set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") - set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") -+ set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") - set(DEFINE_TEMPLATE_EXPORT "${DEFINE_EXPORT}") - set(DEFINE_TEMPLATE_IMPORT "${DEFINE_IMPORT}") -- set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") - endif() - endif() - endmacro() -@@ -301,10 +282,10 @@ endmacro() - macro(_VXL_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) - # Option overrides - set(options DEFINE_NO_DEPRECATED) -- set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME -- TEMPLATE_EXPORT_MACRO_NAME EXPORT_FILE_NAME -+ set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME EXPORT_FILE_NAME -+ TEMPLATE_EXPORT_MACRO_NAME - DEPRECATED_MACRO_NAME NO_EXPORT_MACRO_NAME STATIC_DEFINE -- NO_DEPRECATED_MACRO_NAME) -+ NO_DEPRECATED_MACRO_NAME CUSTOM_CONTENT_FROM_VARIABLE INCLUDE_GUARD_NAME) - set(multiValueArgs) - - cmake_parse_arguments(_GEH "${options}" "${oneValueArgs}" "${multiValueArgs}" -@@ -339,9 +320,7 @@ macro(_VXL_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) - if(_GEH_TEMPLATE_EXPORT_MACRO_NAME) - set(TEMPLATE_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_TEMPLATE_EXPORT_MACRO_NAME}) - endif() -- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) -- string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) -- endif() -+ string(MAKE_C_IDENTIFIER ${EXPORT_MACRO_NAME} EXPORT_MACRO_NAME) - if(_GEH_EXPORT_FILE_NAME) - if(IS_ABSOLUTE ${_GEH_EXPORT_FILE_NAME}) - set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) -@@ -352,43 +331,47 @@ macro(_VXL_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) - if(_GEH_DEPRECATED_MACRO_NAME) - set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) - endif() -- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) -- string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) -- endif() -+ string(MAKE_C_IDENTIFIER ${DEPRECATED_MACRO_NAME} DEPRECATED_MACRO_NAME) - if(_GEH_NO_EXPORT_MACRO_NAME) - set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) - endif() -- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) -- string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) -- endif() -+ string(MAKE_C_IDENTIFIER ${NO_EXPORT_MACRO_NAME} NO_EXPORT_MACRO_NAME) - if(_GEH_STATIC_DEFINE) - set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) - endif() -- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) -- string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) -- endif() -+ string(MAKE_C_IDENTIFIER ${STATIC_DEFINE} STATIC_DEFINE) - - if(_GEH_DEFINE_NO_DEPRECATED) -- set(DEFINE_NO_DEPRECATED TRUE) -+ set(DEFINE_NO_DEPRECATED 1) -+ else() -+ set(DEFINE_NO_DEPRECATED 0) - endif() - - if(_GEH_NO_DEPRECATED_MACRO_NAME) - set(NO_DEPRECATED_MACRO_NAME - ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) - endif() -- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) -- string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) -- endif() -+ string(MAKE_C_IDENTIFIER ${NO_DEPRECATED_MACRO_NAME} NO_DEPRECATED_MACRO_NAME) - -- set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") -+ if(_GEH_INCLUDE_GUARD_NAME) -+ set(INCLUDE_GUARD_NAME ${_GEH_INCLUDE_GUARD_NAME}) -+ else() -+ set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") -+ endif() - - get_target_property(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY} DEFINE_SYMBOL) - - if(NOT EXPORT_IMPORT_CONDITION) - set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) - endif() -- if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) -- string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) -+ string(MAKE_C_IDENTIFIER ${EXPORT_IMPORT_CONDITION} EXPORT_IMPORT_CONDITION) -+ -+ if(_GEH_CUSTOM_CONTENT_FROM_VARIABLE) -+ if(DEFINED "${_GEH_CUSTOM_CONTENT_FROM_VARIABLE}") -+ set(CUSTOM_CONTENT "${${_GEH_CUSTOM_CONTENT_FROM_VARIABLE}}") -+ else() -+ set(CUSTOM_CONTENT "") -+ endif() - endif() - - configure_file("${_VXL_GENERATE_EXPORT_HEADER_MODULE_DIR}/vxlexportheader.cmake.in" -@@ -418,6 +401,9 @@ function(vxl_add_compiler_export_flags) - _vxl_test_compiler_hidden_visibility() - _vxl_test_compiler_has_deprecated() - -+ option(USE_COMPILER_HIDDEN_VISIBILITY -+ "Use HIDDEN visibility support if available." ON) -+ mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) - if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) - # Just return if there are no flags to add. - return() -@@ -434,6 +420,7 @@ function(vxl_add_compiler_export_flags) - if(ARGC GREATER 0) - set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) - else() -- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}" PARENT_SCOPE) -+ string(APPEND CMAKE_CXX_FLAGS " ${EXTRA_FLAGS}") -+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE) - endif() - endfunction() -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake -index a921edcf51..1d1ebc6e72 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/VXLIntrospectionConfig.cmake -@@ -752,11 +752,10 @@ if(NOT VCL_CXX_HAS_HEADER_LIMITS) - message(FATAL_ERROR "Compiler is required to have limits.h") - else() - PERFORM_CMAKE_TEST_RUN(${VXL_PLFM_TEST_FILE} VCL_NUMERIC_LIMITS_HAS_INFINITY) -- # ITK does not require has_infinity -- #if(NOT VCL_NUMERIC_LIMITS_HAS_INFINITY) -- #message(FATAL_ERROR "Compiler is required to have has_infinity.") -- #endif() -- #unset(VCL_NUMERIC_LIMITS_HAS_INFINITY) -+ if(NOT VCL_NUMERIC_LIMITS_HAS_INFINITY) -+ message(FATAL_ERROR "Compiler is required to have has_infinity.") -+ endif() -+ unset(VCL_NUMERIC_LIMITS_HAS_INFINITY) - endif() - unset(VCL_CXX_HAS_HEADER_LIMITS) - -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt -index 7b6e95b121..f2133fdffd 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt -@@ -1,12 +1,32 @@ - # vxl/config/cmake/config/vxl_shared_link_test/CMakeLists.txt - # --cmake_minimum_required(VERSION 2.8.9 FATAL_ERROR) --if(POLICY CMP0025) -- cmake_policy(SET CMP0025 NEW) --endif() --if(POLICY CMP0042) -- cmake_policy(SET CMP0042 NEW) --endif() -+cmake_minimum_required(VERSION 3.3.0 FATAL_ERROR) -+# Set policies consistent with newer versions of cmake -+# to ease integration with projects that require newer -+# cmake versions. -+ -+foreach(p -+ ## Only policies introduced after the cmake_minimum_required -+ ## version need to explicitly be set to NEW. -+ -+ ##----- Policies Introduced by CMake 3.10¶ -+ CMP0071 #: Let AUTOMOC and AUTOUIC process GENERATED files. -+ CMP0070 #: Define file(GENERATE) behavior for relative paths. -+ ##----- Policies Introduced by CMake 3.9 -+ CMP0069 #: INTERPROCEDURAL_OPTIMIZATION is enforced when enabled. -+ CMP0068 #: RPATH settings on macOS do not affect install_name. -+ ##----- Policies Introduced by CMake 3.8 -+ CMP0067 #: Honor language standard in try_compile() source-file signature. -+ ##----- Policies Introduced by CMake 3.7 -+ CMP0066 #: Honor per-config flags in try_compile() source-file signature. -+ ##----- Policies Introduced by CMake 3.4 -+ CMP0065 #: Do not add flags to export symbols from executables without the ENABLE_EXPORTS target property. -+ CMP0064 #: Support new TEST if() operator. -+ ) -+ if(POLICY ${p}) -+ cmake_policy(SET ${p} NEW) -+ endif() -+endforeach() - project(vxl_pic_compatible) - - add_library(cmTryCompileStaticLib STATIC static_src.cxx) -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake -index 3ae1f1c166..6222df72fe 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/config/vxl_utils.cmake -@@ -112,27 +112,21 @@ macro( vxl_add_library ) - if("${VXL_INSTALL_INCLUDE_DIR}" STREQUAL "include/vxl") - ## Identify the relative path for installing the header files and txx files - string(REPLACE ${VXL_ROOT_SOURCE_DIR} "${VXL_INSTALL_INCLUDE_DIR}" relative_install_path ${CMAKE_CURRENT_SOURCE_DIR}) -- ## Added in 2.8.11 http://stackoverflow.com/questions/19460707/how-to-set-include-directories-from-a-cmakelists-txt-file -- if(${CMAKE_VERSION} VERSION_GREATER 2.8.11.2) -- target_include_directories(${lib_name} -- PUBLIC -- $ -- $ -- ) -- endif() -+ target_include_directories(${lib_name} -+ PUBLIC -+ $ -+ $ -+ ) - else() - set(relative_install_path "${VXL_INSTALL_INCLUDE_DIR}") - if(DEFINED header_install_dir) - set(relative_install_path "${relative_install_path}/${header_install_dir}") - endif() -- ## Added in 2.8.11 http://stackoverflow.com/questions/19460707/how-to-set-include-directories-from-a-cmakelists-txt-file -- if(${CMAKE_VERSION} VERSION_GREATER 2.8.11.2) -- target_include_directories(${lib_name} -- PUBLIC -- $ -- $ -- ) -- endif() -+ target_include_directories(${lib_name} -+ PUBLIC -+ $ -+ $ -+ ) - endif() - INSTALL_NOBASE_HEADER_FILES(${relative_install_path} ${lib_srcs}) - endif() -@@ -181,23 +175,14 @@ macro(SET_VXL_LIBRARY_PROPERTIES) - message(FATAL_ERROR "INSTALL_DIR REQUIRED when using USE_HIDDEN_VISIBILITY") - endif() - -- if (BUILD_SHARED_LIBS OR (APPLE AND NOT BUILD_SHARED_LIBS)) -+ if (BUILD_SHARED_LIBS OR (APPLE AND NOT BUILD_SHARED_LIBS) ) #APPLE Respects hidden visibility for static builds - # export flags are only added when building shared libs, they cause - # mismatched visibility warnings when building statically. -- if(CMAKE_VERSION VERSION_LESS 2.8.12) -- # future DEPRECATION notice from cmake: -- # "The add_compiler_export_flags function is obsolete. -- # Use the CXX_VISIBILITY_PRESET and VISIBILITY_INLINES_HIDDEN -- # target properties instead." -- add_compiler_export_flags(my_abi_flags) -- set_property(TARGET ${LSLHVP_TARGET_NAME} APPEND PROPERTY COMPILE_FLAGS "${my_abi_flags}") -- else() -- if (USE_COMPILER_HIDDEN_VISIBILITY) -- # Prefer to use target properties supported by newer cmake -- set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) -- set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES C_VISIBILITY_PRESET hidden) -- set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES VISIBILITY_INLINES_HIDDEN 1) -- endif() -+ if (USE_COMPILER_HIDDEN_VISIBILITY) -+ # Prefer to use target properties supported by newer cmake -+ set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES CXX_VISIBILITY_PRESET hidden) -+ set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES C_VISIBILITY_PRESET hidden) -+ set_target_properties(${LSLHVP_TARGET_NAME} PROPERTIES VISIBILITY_INLINES_HIDDEN 1) - endif() - endif() - endif() -diff --git a/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake b/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake -index b2e8c964a9..e0142c79ca 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake -+++ b/Modules/ThirdParty/VNL/src/vxl/config/cmake/export/VXLCreateProject.cmake -@@ -22,11 +22,7 @@ set(VXL_CMAKE_DOXYGEN_DIR ${VXL_ROOT_SOURCE_DIR}/config/cmake/doxygen) - get_property(VXLTargets_MODULES GLOBAL PROPERTY VXLTargets_MODULES) - - set(VXL_CONFIG_CMAKE_DIR "share/vxl/cmake") --if(${CMAKE_VERSION} VERSION_LESS 2.8.12) -- set(INTERFACE_LINK_OPTION "") --else() -- set(INTERFACE_LINK_OPTION "EXPORT_LINK_INTERFACE_LIBRARIES") --endif() -+set(INTERFACE_LINK_OPTION "EXPORT_LINK_INTERFACE_LIBRARIES") - - if(VXLTargets_MODULES) - export(TARGETS -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt -index 78a984911b..b6af7c2591 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/core/CMakeLists.txt -@@ -9,12 +9,6 @@ doxygen_add_package(core-L2 "Level-2 Vision Libraries") - doxygen_add_package(core-L2E "Level-2 Vision Libraries (Experimental)") - doxygen_add_package(core-test "Test Framework") - --# --# Do platform-specific configuration. --# configure files --# --vxl_configure_file(${CMAKE_CURRENT_LIST_DIR}/vxl_config.h.in ${PROJECT_BINARY_DIR}/vxl_config.h ${VXL_INSTALL_INCLUDE_DIR}) --include_directories(${PROJECT_BINARY_DIR}) - - set(global_sources - vxl_copyright.h -@@ -28,6 +22,13 @@ else() - endif() - INSTALL_NOBASE_HEADER_FILES(${prefix} ${global_sources}) - -+# -+# Do platform-specific configuration. -+# configure files -+# -+vxl_configure_file(${CMAKE_CURRENT_LIST_DIR}/vxl_config.h.in ${PROJECT_BINARY_DIR}/vxl_config.h ${prefix}) -+include_directories(${PROJECT_BINARY_DIR}) -+ - if(BUILD_CORE_UTILITIES) - # POSIX layer - add_subdirectory(vpl) -@@ -122,7 +123,7 @@ endif() - - - # video --CMAKE_DEPENDENT_OPTION (BUILD_CORE_VIDEO "Build VXL's core video libraries" ON -+CMAKE_DEPENDENT_OPTION (BUILD_CORE_VIDEO "Build VXL's core video libraries" OFF - "BUILD_CORE_UTILITIES;BUILD_CORE_IMAGING" OFF) - if (BUILD_CORE_VIDEO) - add_subdirectory(vidl) -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt -index a48b5640bf..59231aa70f 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/CMakeLists.txt -@@ -24,6 +24,10 @@ option(VNL_CONFIG_THREAD_SAFE - option(VNL_CONFIG_ENABLE_SSE2 - "Enable Streaming SIMD Extensions 2 optimisations (hardware dependant). Currently broken. For use by VNL developers only." OFF) - #endif() -+if(VNL_CONFIG_ENABLE_SSE2) -+ # Tested on ubuntu and Mac. ctest becomes unstable and failures change between runs. -+ message(FATAL_ERROR "VNL_CONFIG_ENABLE_SSE2 option currently fails testing on all platforms, this is not suitable for use at the momemnt.") -+endif() - - option(VNL_CONFIG_ENABLE_SSE2_ROUNDING - "Enable Streaming SIMD Extensions 2 implementation of rounding (hardware dependant)." -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx -index 71e6e80d0a..1f14291ed6 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/tests/test_convolve.cxx -@@ -63,7 +63,6 @@ void test_convolve() - - TEST_NEAR("vnl_convolve() with_fft(16384)", (r9-r10).two_norm(), 0.0, 1e-6); - std::cout << "Done FFT-2-based 10000x2000 convolution in " << ms2/double(ntimes) << " milliseconds\n"; -- TEST("vnl_convolve() timing: should be at least 2.5x faster", 5*ms2 < 2*ms1, true); - - vnl_vector r11; - const std::clock_t timer_05 = std::clock(); -@@ -73,7 +72,6 @@ void test_convolve() - const int ms3 = ( timer_06 - timer_05)/ (CLOCKS_PER_SEC/1000); - TEST_NEAR("vnl_convolve() with_fft(12800)", (r9-r11).two_norm(), 0.0, 1e-6); - std::cout << "Done FFT-2,5-based 10000x2000 convolution in " << ms3/double(ntimes) << " milliseconds\n"; -- TEST("vnl_convolve() timing: should even be faster", 2*ms3 < 3*ms2, true); - - vnl_vector r12; - const std::clock_t timer_07 = std::clock(); -@@ -83,7 +81,6 @@ void test_convolve() - const int ms4 = ( timer_08 - timer_07)/ (CLOCKS_PER_SEC/1000); - TEST_NEAR("vnl_convolve() with_fft(27648)", (r9-r12).two_norm(), 0.0, 1e-6); - std::cout << "Done FFT-2,3-based 10000x2000 convolution in " << ms4/double(ntimes) << " milliseconds\n"; -- TEST("vnl_convolve() timing: should be slower", 5*ms4 > 3*ms2, true); - - double c1_data[] = { -1, 0, 1, 2, 3, 4 }; - vnl_vector c1(6, 6, c1_data); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx -index 89eb069622..c1c99263ae 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_brent.cxx -@@ -23,7 +23,7 @@ double vnl_brent::minimize_given_bounds(double ax, double bx, double cx, - double tol, - double *xmin) - { -- assert( xmin != NULL ); -+ assert( xmin != VXL_NULLPTR ); - this->set_x_tolerance( tol ); - *xmin = vnl_brent_minimizer::minimize_given_bounds( ax, bx, cx ); - return vnl_brent_minimizer::f_at_last_minimum(); -@@ -33,7 +33,7 @@ double vnl_brent::minimize_given_bounds_and_1st_f(double ax, double bx, - double fb, double cx, - double tol, double *xmin) - { -- assert( xmin != NULL ); -+ assert( xmin != VXL_NULLPTR ); - this->set_x_tolerance( tol ); - *xmin = vnl_brent_minimizer::minimize_given_bounds_and_one_f( ax, bx, cx, fb ); - return vnl_brent_minimizer::f_at_last_minimum(); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx -index 24f9607238..214d4957a5 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_complex_generalized_schur.cxx -@@ -30,10 +30,10 @@ bool vnl_generalized_schur(vnl_matrix > *A, - assert(B->rows() == B->cols()); - - long n = A->rows(); -- assert(alpha!=0); alpha->set_size(n); alpha->fill(0); -- assert(beta!=0); beta ->set_size(n); beta ->fill(0); -- assert(L!=0); L ->set_size(n, n); L ->fill(0); -- assert(R!=0); R ->set_size(n, n); R ->fill(0); -+ assert(alpha!=VXL_NULLPTR); alpha->set_size(n); alpha->fill(0); -+ assert(beta!=VXL_NULLPTR); beta ->set_size(n); beta ->fill(0); -+ assert(L!=VXL_NULLPTR); L ->set_size(n, n); L ->fill(0); -+ assert(R!=VXL_NULLPTR); R ->set_size(n, n); R ->fill(0); - - long sdim = 0; - long lwork = 1000 + (8*n + 16); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx -index 3c5f3f0895..a92377cf5c 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_convolve.hxx -@@ -47,7 +47,7 @@ vnl_vector vnl_convolve_cyclic(vnl_vector const& v1, vnl_vector const - if (n == 1) return vnl_vector(1, U(v1[0]*v2[0])); - - if (use_fft) -- return vnl_convolve_cyclic_using_fft(v1, v2, (U*)0); -+ return vnl_convolve_cyclic_using_fft(v1, v2, (U*)VXL_NULLPTR); - - vnl_vector ret(n, (U)0); // all elements already initialized to zero - for (unsigned int k=0; k vnl_convolve_using_fft(vnl_vector const& v1, vnl_vector co - vnl_vector w1(n, U(0)); for (unsigned i=0; i w2(n, U(0)); for (unsigned i=0; i(v1.size()+v2.size()-1, v1.size()+v2.size()-1, w1.data_block()); - } -@@ -98,7 +98,7 @@ vnl_vector vnl_convolve(vnl_vector const& v1, vnl_vector const& v2, int - if (v2.size() == 1) return v1*v2[0]; - - if (use_fft != 0) -- return vnl_convolve_using_fft(v1, v2, (T*)0, use_fft); -+ return vnl_convolve_using_fft(v1, v2, (T*)VXL_NULLPTR, use_fft); - - unsigned int n = v1.size() + v2.size() - 1; - vnl_vector ret(n, (T)0); // all elements already initialized to zero -@@ -120,7 +120,7 @@ vnl_vector vnl_convolve(vnl_vector const& v1, vnl_vector const& v2, U - return vnl_vector(0); - - if (use_fft != 0) -- return vnl_convolve_using_fft(v1, v2, (U*)0, use_fft); -+ return vnl_convolve_using_fft(v1, v2, (U*)VXL_NULLPTR, use_fft); - - unsigned int n = v1.size() + v2.size() - 1; - vnl_vector ret(n, (U)0); // all elements already initialized to zero -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx -index 32f784ba87..a11870bf6f 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_fft_prime_factors.hxx -@@ -9,7 +9,7 @@ - - template - vnl_fft_prime_factors::vnl_fft_prime_factors() -- : trigs_(0) -+ : trigs_(VXL_NULLPTR) - , number_(0) - { - } -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx -index 497da54958..d7d7b1960c 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_generalized_schur.cxx -@@ -30,11 +30,11 @@ bool vnl_generalized_schur(vnl_matrix *A, - assert(A->cols() == B->cols()); - - long n = A->rows(); -- assert(alphar!=0); alphar->set_size(n); alphar->fill(0); -- assert(alphai!=0); alphai->set_size(n); alphai->fill(0); -- assert(beta!=0); beta ->set_size(n); beta ->fill(0); -- assert(L!=0); L ->set_size(n, n); L ->fill(0); -- assert(R!=0); R ->set_size(n, n); R ->fill(0); -+ assert(alphar!=VXL_NULLPTR); alphar->set_size(n); alphar->fill(0); -+ assert(alphai!=VXL_NULLPTR); alphai->set_size(n); alphai->fill(0); -+ assert(beta!=VXL_NULLPTR); beta ->set_size(n); beta ->fill(0); -+ assert(L!=VXL_NULLPTR); L ->set_size(n, n); L ->fill(0); -+ assert(R!=VXL_NULLPTR); R ->set_size(n, n); R ->fill(0); - - long sdim = 0; - long lwork = 1000 + (8*n + 16); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx -index 9d125ea561..d1d84918bc 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lbfgs.cxx -@@ -77,7 +77,7 @@ bool vnl_lbfgs::minimize(vnl_vector& x) - std::cerr << "vnl_lbfgs: "; - - double best_f = 0; -- vnl_vector best_x = x; -+ vnl_vector best_x; - - bool ok; - this->num_evaluations_ = 0; -@@ -105,8 +105,8 @@ bool vnl_lbfgs::minimize(vnl_vector& x) - best_f = f; - } - --#define print_(i,a,b,c,d) std::cerr<ls_ = NULL; -+ this->ls_ = VXL_NULLPTR; - } - - virtual ~lsqrVNL() -@@ -88,7 +88,7 @@ vnl_lsqr::~vnl_lsqr() - } - - // Requires number_of_residuals() of workspace in rw. --int vnl_lsqr::aprod_(long* mode, long* m, long* n, double* x, double* y, long* /*leniw*/, long* /*lenrw*/, long* /*iw*/, double* rw, void* userdata) -+int vnl_lsqr::aprod_(const long* mode, const long* m, const long* n, double* x, double* y, long* /*leniw*/, long* /*lenrw*/, long* /*iw*/, double* rw, void* userdata) - { - // - // THIS CODE IS DEPRECATED -@@ -123,7 +123,7 @@ int vnl_lsqr::minimize(vnl_vector& result) - long n = ls_->get_number_of_unknowns(); - double damp = 0; - long leniw = 1; -- long* iw = 0; -+ long* iw = VXL_NULLPTR; - long lenrw = m; - #ifdef __GNUC__ - double rw[m]; -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h -index 6ab8d07f69..8ca0959993 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_lsqr.h -@@ -74,7 +74,7 @@ class VNL_ALGO_EXPORT vnl_lsqr - double result_norm_; - long return_code_; - -- static int aprod_(long* mode, long* m, long* n, double* x, double* y, -+ static int aprod_(const long* mode, const long* m, const long* n, double* x, double* y, - long* leniw, long* lenrw, long* iw, double* rw, - void* userdata); - }; -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h -index 56e54c1fb4..12d93958e0 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_matrix_inverse.h -@@ -35,7 +35,7 @@ template - struct vnl_matrix_inverse : public vnl_svd - { - vnl_matrix_inverse(vnl_matrix const & M): vnl_svd(M) { } -- ~vnl_matrix_inverse() {} -+ ~vnl_matrix_inverse() VXL_OVERRIDE {} - - operator vnl_matrix () const { return this->inverse(); } - }; -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx -index fb19f73d27..e48bbed9f7 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_qr.hxx -@@ -199,10 +199,10 @@ vnl_vector vnl_qr::solve(const vnl_vector& b) const - vnl_linpack_qrsl(qrdc_out_.data_block(), - &n, &n, &p, - qraux_.data_block(), -- b_data, (T*)0, Qt_B.data_block(), -+ b_data, (T*)VXL_NULLPTR, Qt_B.data_block(), - x.data_block(), -- (T*)0/*residual*/, -- (T*)0/*Ax*/, -+ (T*)VXL_NULLPTR/*residual*/, -+ (T*)VXL_NULLPTR/*Ax*/, - &JOB, - &info); - -@@ -230,11 +230,11 @@ vnl_vector vnl_qr::QtB(const vnl_vector& b) const - &n, &n, &p, - qraux_.data_block(), - b_data, -- (T*)0, // A: Qb -+ (T*)VXL_NULLPTR, // A: Qb - Qt_B.data_block(), // B: Q'b -- (T*)0, // C: x -- (T*)0, // D: residual -- (T*)0, // E: Ax -+ (T*)VXL_NULLPTR, // C: x -+ (T*)VXL_NULLPTR, // D: residual -+ (T*)VXL_NULLPTR, // E: Ax - &JOB, - &info); - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx -index 025e0f07cc..dd4d49bc91 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_sparse_symmetric_eigensystem.cxx -@@ -29,7 +29,7 @@ void sse_op_callback(const long* n, - const double* p, - double* q) - { -- assert(current_system != 0); -+ assert(current_system != VXL_NULLPTR); - - current_system->CalculateProduct(*n,*m,p,q); - } -@@ -46,7 +46,7 @@ void sse_iovect_callback(const long* n, - const long* j, - const long* k) - { -- assert(current_system != 0); -+ assert(current_system != VXL_NULLPTR); - - if (*k==0) - current_system->SaveVectors(*n,*m,q,*j-*m); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx -index bb20b6b7e8..a2e7c825b4 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/algo/vnl_svd_economy.hxx -@@ -45,7 +45,7 @@ vnl_svd_economy::vnl_svd_economy( vnl_matrix const& M ) : - vnl_linpack_svdc_economy((real_t*)X, &m_, &m_, &n_, - wspace.data_block(), - espace.data_block(), -- 0, &ldu, -+ VXL_NULLPTR, &ldu, - vspace.data_block(), &n_, - work.data_block(), - &job, &info); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx -index 625b9b51b8..592a05a8af 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/basic_operation_timings.cxx -@@ -17,7 +17,7 @@ - const unsigned nstests = 10; - - --void fill_with_rng(double * begin, double * end, double a, double b, vnl_random &rng) -+void fill_with_rng(double * begin, const double * end, double a, double b, vnl_random &rng) - { - while (begin != end) - { -@@ -26,7 +26,7 @@ void fill_with_rng(double * begin, double * end, double a, double b, vnl_random - } - } - --void fill_with_rng(float * begin, float * end, float a, float b, vnl_random &rng) -+void fill_with_rng(float * begin, const float * end, float a, float b, vnl_random &rng) - { - while (begin != end) - { -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx -index b269ba6ba6..db889e64fc 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_arithmetic.cxx -@@ -15,10 +15,10 @@ - // --- dynamic ------------------------------ - - #define NewMat(mat, r,c,data) \ -- assert( sizeof(data) >= r*c*sizeof(double) ); \ -+ assert( sizeof(data) >= (r)*(c)*sizeof(double) ); \ - vnl_matrix mat( data, r, c ) - #define NewVec(vec, n,data) \ -- assert( sizeof(data) >= n*sizeof(double) ); \ -+ assert( sizeof(data) >= (n)*sizeof(double) ); \ - vnl_vector vec( data, n ) - - static -@@ -35,10 +35,10 @@ test_arithmetic_dynamic() - // --- ref ---------------------------------- - - #define NewMat(mat, r,c,data) \ -- assert( sizeof(data) >= r*c*sizeof(double) ); \ -+ assert( sizeof(data) >= (r)*(c)*sizeof(double) ); \ - vnl_matrix_ref mat( r, c, data ) - #define NewVec(vec, n,data) \ -- assert( sizeof(data) >= n*sizeof(double) ); \ -+ assert( sizeof(data) >= (n)*sizeof(double) ); \ - vnl_vector_ref vec( n, data ) - - static -@@ -55,10 +55,10 @@ test_arithmetic_ref() - #undef NewVec - - #define NewMat(mat, r,c,data) \ -- assert( sizeof(data) >= r*c*sizeof(double) ); \ -+ assert( sizeof(data) >= (r)*(c)*sizeof(double) ); \ - vnl_matrix_fixed mat( data ) - #define NewVec(vec, n,data) \ -- assert( sizeof(data) >= n*sizeof(double) ); \ -+ assert( sizeof(data) >= (n)*sizeof(double) ); \ - vnl_vector_fixed vec( data ) - - void -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx -index 4b60e8a01d..a6502a2243 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matlab.cxx -@@ -32,7 +32,7 @@ - // get a byte-swapped file, short of reading in a native file and swapping it - // and writing it back out, and that isn't any easier. - void matlab_write_swapped(std::ostream &f, -- float *array, -+ const float *array, - unsigned size, - char const *name) - { -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx -index 8919c4a4fc..2fdac67c58 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_matrix.cxx -@@ -62,7 +62,7 @@ void test_int() - try { m0.get(0,25); } // Raise out of bounds exception. - catch(...) { exceptionThrownAndCaught = true; } - TEST("Out of bounds get(0,25)", exceptionThrownAndCaught, true); -- -+ - exceptionThrownAndCaught = false; - try { m0.get(25,0); } // Raise out of bounds exception. - catch(...) { exceptionThrownAndCaught = true; } -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx -index 7f371724e6..aed9edafb4 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_na.cxx -@@ -9,9 +9,9 @@ - - - #define print_hex(p) \ -- std::hex<(&p)[sizeof(p)-1]; \ -+ std::hex<(&(p))[sizeof(p)-1]; \ - for (unsigned int i=2; i<=sizeof(p); ++i) \ -- std::cout<(&p))[sizeof(p)-i]; \ -+ std::cout<(&(p)))[sizeof(p)-i]; \ - std::cout<(&p)[sizeof(p)-1]; \ -+ std::hex<(&(p))[sizeof(p)-1]; \ - for (unsigned int i=2; i<=sizeof(p); ++i) \ -- std::cout<(&p))[sizeof(p)-i]; \ -+ std::cout<(&(p)))[sizeof(p)-i]; \ - std::cout<(0)); -+ TEST("==", z_int==0L, true); -+ vnl_rational z_uint(static_cast(0) ); -+ TEST("==", z_uint==0L, true); -+ -+ vnl_rational z_short(static_cast(0)); -+ TEST("==", z_short==0L, true); -+ vnl_rational z_ushort(static_cast(0) ); -+ TEST("==", z_ushort==0L, true); -+ -+ vnl_rational z_long(static_cast(0)); -+ TEST("==", z_long==0L, true); -+ vnl_rational z_ulong(static_cast(0)); -+ TEST("==", z_ulong==0L, true); -+#if 0 -+ vnl_rational z_mixed(static_cast(0), static_cast(1) ); -+ TEST("==", z_mixed==0L, true); -+#endif -+ - TEST("==", a==-5L, true); - TEST("==", 5L==-a, true); - TEST("==", b==-7, true); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx -index b49115fe54..a77f7b4518 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/tests/test_sym_matrix.cxx -@@ -83,7 +83,7 @@ void test_int() - try { sm1.get(0,25); } // Raise out of bounds exception. - catch(...) { exceptionThrownAndCaught = true; } - TEST("Out of bounds get(0,25)", exceptionThrownAndCaught, true); -- -+ - exceptionThrownAndCaught = false; - try { sm1.get(25,0); } // Raise out of bounds exception. - catch(...) { exceptionThrownAndCaught = true; } -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx -index e5ec177ee1..2d6af99d6e 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_na_vector.hxx -@@ -153,8 +153,8 @@ template VNL_EXPORT void vnl_c_na_vector_inf_norm(T const *, unsigned, S *) - #undef VNL_C_NA_VECTOR_INSTANTIATE_ordered - #define VNL_C_NA_VECTOR_INSTANTIATE_ordered(T) \ - VNL_C_NA_VECTOR_INSTANTIATE_norm(T, vnl_c_na_vector::abs_t); \ --template class VNL_EXPORT vnl_c_na_vector; \ --template VNL_EXPORT std::ostream& print_na_vector(std::ostream &,T const *,unsigned) -+template class vnl_c_na_vector; \ -+template std::ostream& print_na_vector(std::ostream &,T const *,unsigned) - - - #undef VNL_C_NA_VECTOR_INSTANTIATE_unordered -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx -index eb558a937a..37e1221e85 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_c_vector.hxx -@@ -441,7 +441,7 @@ template VNL_EXPORT void vnl_c_vector_inf_norm(T const *, unsigned, S *) - #undef VNL_C_VECTOR_INSTANTIATE_ordered - #define VNL_C_VECTOR_INSTANTIATE_ordered(T) \ - VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector::abs_t); \ --template class VNL_EXPORT vnl_c_vector; \ -+template class vnl_c_vector; \ - template VNL_EXPORT std::ostream& print_vector(std::ostream &,T const *,unsigned) - - #undef VNL_C_VECTOR_INSTANTIATE_unordered -@@ -450,7 +450,7 @@ VCL_DO_NOT_INSTANTIATE(T vnl_c_vector::max_value(T const *, unsigned), T(0)) - VCL_DO_NOT_INSTANTIATE(T vnl_c_vector::min_value(T const *, unsigned), T(0)); \ - VCL_DO_NOT_INSTANTIATE(unsigned vnl_c_vector::arg_max(T const *, unsigned), 0U); \ - VCL_DO_NOT_INSTANTIATE(unsigned vnl_c_vector::arg_min(T const *, unsigned), 0U); \ --template class VNL_EXPORT vnl_c_vector; \ -+template class vnl_c_vector; \ - VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector::abs_t); - - #ifndef DOXYGEN_SHOULD_SKIP_THIS -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h -index e831cfb116..7ee40fb0e2 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_matrix.h -@@ -30,7 +30,7 @@ class VNL_TEMPLATE_EXPORT vnl_file_matrix : public vnl_matrix - vnl_file_matrix(char const* filename); - - operator safe_bool () const -- { return (ok_)? VCL_SAFE_BOOL_TRUE : 0; } -+ { return (ok_)? VCL_SAFE_BOOL_TRUE : VXL_NULLPTR; } - bool operator!() const - { return !ok_; } - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h -index 99cd366e85..8d5c9a78bf 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_file_vector.h -@@ -31,7 +31,7 @@ class VNL_TEMPLATE_EXPORT vnl_file_vector : public vnl_vector - vnl_file_vector(char const* filename); - - operator safe_bool () const -- { return (ok_)? VCL_SAFE_BOOL_TRUE : 0; } -+ { return (ok_)? VCL_SAFE_BOOL_TRUE : VXL_NULLPTR; } - bool operator!() const - { return !ok_; } - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx -index 1f6bd5f718..8d3f9a8cfc 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.cxx -@@ -26,7 +26,7 @@ - #endif - - #elif VXL_HAS_STD_ISFINITE || VXL_HAS_STD_ISNAN || VXL_HAS_STD_ISNORMAL --# include -+# include - # if VXL_HAS_STD_ISFINITE - # define finite std::isfinite - # define finitef std::isfinite -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h -index 4a7e4a7669..c66e3df9ab 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_math.h -@@ -153,41 +153,28 @@ namespace vnl_math - namespace vnl_math - { - #if VXL_FULLCXX11SUPPORT -- // Prefer to use perfect forwarding to the std library if C++11 features are available. -- //http://stackoverflow.com/questions/9864125/c11-how-to-alias-a-function -- template -- auto isnan(Args&&... args) -> decltype(std::isnan(std::forward(args)...)) { -- return std::isnan(std::forward(args)...); -+ using std::isnan; -+ // Ensure proper conversion to bool type. -+ // Return a signed integer type has been seen with the following -+ // compilers/libstdc++: -+ // g++ (GCC) 7.2.1 20170829 (Red Hat 7.2.1-1) -+ // g++ (GCC) 6.3.1 20170216 (Red Hat 6.3.1-3) -+ template -+ bool isinf(TArg&& arg) -+ { -+ return bool(std::isinf(std::forward(arg))); - } -- template -- auto isinf(Args&&... args) -> decltype(std::isinf(std::forward(args)...)) { -- return std::isinf(std::forward(args)...); -- } -- template -- auto isfinite(Args&&... args) -> decltype(std::isfinite(std::forward(args)...)) { -- return std::isfinite(std::forward(args)...); -- } -- template -- auto isnormal(Args&&... args) -> decltype(std::isnormal(std::forward(args)...)) { -- return std::isnormal(std::forward(args)...); -- } -- template -- auto max(Args&&... args) -> decltype(std::max(std::forward(args)...)) { -- return std::max(std::forward(args)...); -- } -- template -- auto min(Args&&... args) -> decltype(std::min(std::forward(args)...)) { -- return std::min(std::forward(args)...); -- } -- //cbrt is defined in C++11 -- template -- auto cuberoot(Args&&... args) -> decltype(std::cbrt(std::forward(args)...)) { -- return std::cbrt(std::forward(args)...); -- } -- template -- auto hypot(Args&&... args) -> decltype(std::hypot(std::forward(args)...)) { -- return std::hypot(std::forward(args)...); -+ using std::isfinite; -+ using std::isnormal; -+ using std::max; -+ using std::min; -+ using std::cbrt; -+ template -+ TArg cuberoot(TArg&& arg) -+ { -+ return std::cbrt(std::forward(arg)); - } -+ using std::hypot; - #else - // isnan - inline bool isnan(char) { return false; } -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h -index d818e12015..c001352b08 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print.h -@@ -46,7 +46,7 @@ std::ostream &vnl_matlab_print(std::ostream &, - template VNL_TEMPLATE_EXPORT - std::ostream &vnl_matlab_print(std::ostream &, - vnl_diag_matrix const&, -- char const *variable_name =0, -+ char const *variable_name =VXL_NULLPTR, - vnl_matlab_print_format =vnl_matlab_print_format_default); - - //: print a vnl_matrix. -@@ -54,7 +54,7 @@ std::ostream &vnl_matlab_print(std::ostream &, - template VNL_TEMPLATE_EXPORT - std::ostream &vnl_matlab_print(std::ostream &, - vnl_matrix const&, -- char const *variable_name =0, -+ char const *variable_name =VXL_NULLPTR, - vnl_matlab_print_format =vnl_matlab_print_format_default); - - //: print a vnl_matrix_fixed. -@@ -62,7 +62,7 @@ std::ostream &vnl_matlab_print(std::ostream &, - template VNL_TEMPLATE_EXPORT - std::ostream &vnl_matlab_print(std::ostream &, - vnl_matrix_fixed const&, -- char const *variable_name =0, -+ char const *variable_name =VXL_NULLPTR, - vnl_matlab_print_format =vnl_matlab_print_format_default); - - //: print a vnl_matrix_ref. -@@ -70,7 +70,7 @@ std::ostream &vnl_matlab_print(std::ostream &, - template VNL_TEMPLATE_EXPORT - std::ostream &vnl_matlab_print(std::ostream &, - vnl_matrix_ref const &, -- char const *variable_name =0, -+ char const *variable_name =VXL_NULLPTR, - vnl_matlab_print_format =vnl_matlab_print_format_default); - - //: print a vnl_vector. -@@ -78,7 +78,7 @@ std::ostream &vnl_matlab_print(std::ostream &, - template VNL_TEMPLATE_EXPORT - std::ostream &vnl_matlab_print(std::ostream &, - vnl_vector const &, -- char const *variable_name =0, -+ char const *variable_name =VXL_NULLPTR, - vnl_matlab_print_format =vnl_matlab_print_format_default); - - //: print a vnl_vector_fixed. -@@ -86,7 +86,7 @@ std::ostream &vnl_matlab_print(std::ostream &, - template VNL_TEMPLATE_EXPORT - std::ostream &vnl_matlab_print(std::ostream &, - vnl_vector_fixed const &, -- char const *variable_name =0, -+ char const *variable_name =VXL_NULLPTR, - vnl_matlab_print_format =vnl_matlab_print_format_default); - - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h -index bdac336023..061e7b0e11 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_print2.h -@@ -61,7 +61,7 @@ template - inline - vnl_matlab_print_proxy - vnl_matlab_print(T const &obj, -- char const *name = 0, -+ char const *name = VXL_NULLPTR, - vnl_matlab_print_format format = vnl_matlab_print_format_default) - { - return vnl_matlab_print_proxy(obj, name, format); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h -index 788c583ab8..5e56ac93d4 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_read.h -@@ -33,8 +33,8 @@ template class vnl_matrix; - // If the data in the file cannot reasonably be read into the destination, abort(). - // - // The vector/matrix will be resized if necessary. --template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_vector &, char const *name =0); --template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_matrix &, char const *name =0); -+template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_vector &, char const *name =VXL_NULLPTR); -+template VNL_TEMPLATE_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_matrix &, char const *name =VXL_NULLPTR); - - // ------------------------------ less easy ------------------------------ - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx -index a48b31f269..5f276ef576 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matrix_fixed_ref.hxx -@@ -536,7 +536,7 @@ vnl_matrix_fixed_ref::read_ascii(std::istream& s) const - - template - vnl_matrix_fixed_ref & --vnl_matrix_fixed_ref::flipud() -+vnl_matrix_fixed_ref::flipud() - { - for (unsigned int r1 = 0; 2*r1+1 < nrows; ++r1) - { -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx -index 72046e8162..0fc9533336 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_numeric_traits.cxx -@@ -57,7 +57,7 @@ VXL_CONSTEXPR_VAR unsigned long long vnl_numeric_traits::one - #endif - - VXL_CONSTEXPR_VAR bool vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(true); --VXL_CONSTEXPR_VAR char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(char(255)<0?127:255); -+VXL_CONSTEXPR_VAR char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(char(255)<0?127:char(255)); - // It is 127 when "char" is signed and 255 when "char" is unsigned. - VXL_CONSTEXPR_VAR unsigned char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(255); - VXL_CONSTEXPR_VAR signed char vnl_numeric_traits::maxval VCL_STATIC_CONST_INIT_INT_DEFN(127); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx -index cd3e202c38..8cdb8f8582 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.cxx -@@ -89,7 +89,7 @@ void vnl_random::reseed(unsigned long seed) - for (int j=0;j<1000;j++) lrand32(); - } - --void vnl_random::reseed(unsigned long seed[vnl_random_array_size]) -+void vnl_random::reseed(const unsigned long seed[vnl_random_array_size]) - { - mz_array_position = 0UL; - mz_borrow = 0L; -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h -index faaa00a187..de5391ac8a 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_random.h -@@ -81,7 +81,7 @@ class VNL_EXPORT vnl_random - void reseed(unsigned long); - - //: Starts a new deterministic sequence from an already declared generator using the provided seed. -- void reseed(unsigned long[vnl_random_array_size]); -+ void reseed(const unsigned long[vnl_random_array_size]); - - //: This restarts the sequence of random numbers. - // Restarts so that it repeats -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx -index a43759f0ab..293fd07b87 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.cxx -@@ -6,9 +6,8 @@ - #include // for vnl_numeric_traits::maxval - #include - --//: Creates a rational from a double. --// This is done by computing the continued fraction approximation for d. --vnl_rational::vnl_rational(double d) -+template -+inline void makeNumDen( FloatingType d, long &num_, long &den_) - { - bool sign = d<0; - if (sign) d = -d; -@@ -29,6 +28,20 @@ vnl_rational::vnl_rational(double d) - // no need to normalize() since prev_num and prev_den have guaranteed a gcd=1 - } - -+//: Creates a rational from a double. -+// This is done by computing the continued fraction approximation for d. -+vnl_rational::vnl_rational(double d) -+{ -+ makeNumDen(d,num_,den_); -+} -+ -+//: Creates a rational from a double. -+// This is done by computing the continued fraction approximation for d. -+vnl_rational::vnl_rational(float f) -+{ -+ makeNumDen(f,num_,den_); -+} -+ - //: Multiply/assign: replace lhs by lhs * rhs - // Note that 0 * Inf and Inf * 0 are undefined. - // Also note that there could be integer overflow during this calculation! -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h -index f36caab39a..9afa439ee5 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_rational.h -@@ -80,21 +80,45 @@ class VNL_EXPORT vnl_rational - // Also serves as automatic cast from long to vnl_rational. - // The only input which is not allowed is (0,0); - // the denominator is allowed to be 0, to represent +Inf or -Inf. -- inline vnl_rational(long num = 0L, long den = 1L) -+ -+ inline vnl_rational() -+ : num_(0L), den_(1L) { normalize(); } -+ -+ inline vnl_rational(long num) -+ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } -+ inline vnl_rational(long num, long den) - : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } -- //: Creates a rational with given numerator and denominator. -- // Note these are not automatic type conversions because of a bug -- // in the Borland compiler. Since these just convert their -- // arguments to long anyway, there is no harm in letting -- // the long overload be used for automatic conversions. -- explicit inline vnl_rational(int num, int den = 1) -+ -+ inline vnl_rational(unsigned long num) -+ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } -+ inline vnl_rational(unsigned long num, unsigned long den) -+ : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } -+ -+ inline vnl_rational(int num) -+ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } -+ inline vnl_rational(int num, int den) - : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } -- explicit inline vnl_rational(unsigned int num, unsigned int den = 1) -+ -+ inline vnl_rational(unsigned int num) -+ : num_((long)num), den_(1L) { assert(num!=0||den_!=0); normalize(); } -+ inline vnl_rational(unsigned int num, unsigned int den) - : num_((long)num), den_((long)den) { assert(num!=0||den!=0); normalize(); } -+ -+ inline vnl_rational(short num) -+ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } -+ inline vnl_rational(short num, short den) -+ : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } -+ -+ inline vnl_rational(unsigned short num) -+ : num_(num), den_(1L) { assert(num!=0||den_!=0); normalize(); } -+ inline vnl_rational(unsigned short num, unsigned short den) -+ : num_(num), den_(den) { assert(num!=0||den!=0); normalize(); } -+ - //: Creates a rational from a double. - // This is done by computing the continued fraction approximation for d. - // Note that this is explicitly \e not an automatic type conversion. -- explicit vnl_rational(double d); -+ vnl_rational(double d); -+ vnl_rational(float d); - // Copy constructor - inline vnl_rational(vnl_rational const& from) - : num_(from.numerator()), den_(from.denominator()) {} -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx -index e699962126..9d5d745436 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sample.cxx -@@ -11,7 +11,7 @@ - #include - #include - --#include // dont_vxl_filter -+#include // dont_vxl_filter - - #if !VXL_STDLIB_HAS_DRAND48 - // rand() is not always a good random number generator, -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h -index a3429de673..d012cf7b73 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix.h -@@ -94,7 +94,7 @@ class VNL_TEMPLATE_EXPORT vnl_sparse_matrix_pair - return *this; - } - -- struct less : public std::binary_function -+ struct less - { - bool operator() (vnl_sparse_matrix_pair const& p1, vnl_sparse_matrix_pair const& p2) { - return p1.first < p2.first; -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx -index 7584d8da9e..608b488339 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.cxx -@@ -77,6 +77,6 @@ void vnl_sparse_matrix_linear_system::apply_preconditioner(vnl_vector - px = dot_product(x,jacobi_precond_); - } - --template class VNL_EXPORT vnl_sparse_matrix_linear_system; --template class VNL_EXPORT vnl_sparse_matrix_linear_system; -+template class vnl_sparse_matrix_linear_system; -+template class vnl_sparse_matrix_linear_system; - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h -index 8fbe755e74..091425bd8f 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sparse_matrix_linear_system.h -@@ -35,8 +35,6 @@ class VNL_TEMPLATE_EXPORT vnl_sparse_matrix_linear_system : public vnl_linear_sy - vnl_sparse_matrix_linear_system(vnl_sparse_matrix const& A, vnl_vector const& b) : - vnl_linear_system(A.columns(), A.rows()), A_(A), b_(b), jacobi_precond_() {} - -- virtual ~vnl_sparse_matrix_linear_system() {} -- - //: Implementations of the vnl_linear_system virtuals. - void multiply(vnl_vector const& x, vnl_vector & b) const; - //: Implementations of the vnl_linear_system virtuals. -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h -index e06ef30d33..bfc4a3a733 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sse.h -@@ -77,8 +77,8 @@ - # define VNL_SSE_HEAP_STORE(pf) _mm_storeu_##pf - # define VNL_SSE_HEAP_LOAD(pf) _mm_loadu_##pf - # if VNL_CONFIG_THREAD_SAFE --# define VNL_SSE_ALLOC(n,s,a) new char[n*s] --# define VNL_SSE_FREE(v,n,s) delete [] static_cast(v) -+# define VNL_SSE_ALLOC(n,s,a) new char[(n)*(s)] -+# define VNL_SSE_FREE(v,n,s) (delete [] static_cast(v)) - # else - # define VNL_SSE_ALLOC(n,s,a) vnl_alloc::allocate((n == 0) ? 8 : (n * s)); - # define VNL_SSE_FREE(v,n,s) if (v) vnl_alloc::deallocate(v, (n == 0) ? 8 : (n * s)); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h -index d1adbb1d8a..3922fca8eb 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_sym_matrix.h -@@ -29,7 +29,7 @@ class VNL_TEMPLATE_EXPORT vnl_sym_matrix - { - public: - //: Construct an empty symmetric matrix. -- vnl_sym_matrix(): data_(0), index_(0), nn_(0) {} -+ vnl_sym_matrix(): data_(VXL_NULLPTR), index_(VXL_NULLPTR), nn_(0) {} - - //: Construct a symmetric matrix of size nn by nn. - explicit vnl_sym_matrix(unsigned nn): -@@ -222,7 +222,7 @@ inline vnl_sym_matrix::vnl_sym_matrix(vnl_matrix const& that): - - template - inline vnl_sym_matrix::vnl_sym_matrix(vnl_sym_matrix const& that): -- data_(0), index_(0), nn_(0) -+ data_(VXL_NULLPTR), index_(VXL_NULLPTR), nn_(0) - { - set_size(that.rows()); - update(that); -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h -index 3fb0a9207f..5053a4e172 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.h -@@ -134,7 +134,7 @@ class VNL_TEMPLATE_EXPORT vnl_vector - vnl_vector(vnl_vector const &, vnl_matrix const &, vnl_tag_mul); // v * M - vnl_vector(vnl_vector &that, vnl_tag_grab) - : num_elmts(that.num_elmts), data(that.data) -- { that.num_elmts=0; that.data=0; } // "*this" now uses "that"'s data. -+ { that.num_elmts=0; that.data=VXL_NULLPTR; } // "*this" now uses "that"'s data. - // - #endif - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx -index 0e995a8ce3..1af97626ca 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector.hxx -@@ -65,7 +65,7 @@ - #define vnl_vector_alloc_blah(size) \ - do { \ - this->num_elmts = (size); \ -- this->data = size ? vnl_c_vector::allocate_T(size) : 0; \ -+ this->data = (size) ? vnl_c_vector::allocate_T(size) : 0; \ - } while (false) - - // This macro deallocates the dynamic storage used by a vnl_vector. -@@ -288,7 +288,7 @@ void vnl_vector::clear() - if (data) { - destroy(); - num_elmts = 0; -- data = 0; -+ data = VXL_NULLPTR; - } - } - -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx -index 7317b90c72..13879ea79a 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_vector_fixed_ref.hxx -@@ -123,7 +123,7 @@ vnl_vector_fixed_ref_const::print( std::ostream& s ) const - // instantiation macros for vnl_vector_fixed_ref : - - #define VNL_VECTOR_FIXED_REF_INSTANTIATE(T,n) \ --template class VNL_EXPORT vnl_vector_fixed_ref; \ --template class VNL_EXPORT vnl_vector_fixed_ref_const -+template class vnl_vector_fixed_ref; \ -+template class vnl_vector_fixed_ref_const - - #endif // vnl_vector_fixed_ref_hxx_ -diff --git a/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h b/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h -index 152aeab849..a37ecc38b7 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h -+++ b/Modules/ThirdParty/VNL/src/vxl/core/vxl_version.h -@@ -26,9 +26,9 @@ - - //: Version date. This is updated every day. - // Formats are year=CCYY, month=MM, day=DD --#define VXL_VERSION_DATE_YEAR 2017 --#define VXL_VERSION_DATE_MONTH 12 --#define VXL_VERSION_DATE_DAY 08 -+#define VXL_VERSION_DATE_YEAR 2018 -+#define VXL_VERSION_DATE_MONTH 05 -+#define VXL_VERSION_DATE_DAY 16 - - //: Helper macros to create strings with the preprocessor. - #define VXL_VERSION_TO_STRING(s) VXL_VERSION_TO_STRING0(s) -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt -index 431bbae68a..f9f4816083 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/CMakeLists.txt -@@ -445,7 +445,6 @@ if(BUILD_TESTING) - add_subdirectory(tests) - endif() - --# Disabled in ITK to avoid find_package(X11) --if(BUILD_EXAMPLES AND 0) -+if(BUILD_EXAMPLES) - add_subdirectory(examples) - endif() -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat -index 2ae4565113..0dc84531c9 100755 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/comptry.bat -@@ -1,5 +1,5 @@ --%1 %2 %3 %4 %5 %6 %7 %8 %9 --if errorlevel 1 goto nolonglong --exit 0 --:nolonglong --%1 -DNO_LONG_LONG %2 %3 %4 %5 %6 %7 %8 %9 -+%1 %2 %3 %4 %5 %6 %7 %8 %9 -+if errorlevel 1 goto nolonglong -+exit 0 -+:nolonglong -+%1 -DNO_LONG_LONG %2 %3 %4 %5 %6 %7 %8 %9 -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat -index 69be841b91..2c11a97e45 100755 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/libf2c/scomptry.bat -@@ -1,5 +1,5 @@ --%1 -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 --if errorlevel 1 goto nolonglong --exit 0 --:nolonglong --%1 -DNO_LONG_LONG -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 -+%1 -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 -+if errorlevel 1 goto nolonglong -+exit 0 -+:nolonglong -+%1 -DNO_LONG_LONG -DWRITE_ARITH_H -DNO_FPINIT %2 %3 %4 %5 %6 %7 %8 %9 -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx -index 6053b93203..067b1abebb 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrBase.cxx -@@ -16,6 +16,7 @@ - * - *=========================================================================*/ - #include "lsmrBase.h" -+#include "vcl_compiler_detection.h" - - #include - #include -@@ -40,7 +41,7 @@ lsmrBase::lsmrBase() - this->btol = 1e-6; - this->conlim = 1.0 / ( 10 * sqrt( this->eps ) ); - this->itnlim = 10; -- this->nout = NULL; -+ this->nout = VXL_NULLPTR; - this->istop = 0; - this->itn = 0; - this->normA = 0.0; -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx -index 799bc0538b..b0ccf84890 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsmrDense.cxx -@@ -16,10 +16,11 @@ - * - *=========================================================================*/ - #include "lsmrDense.h" -+#include "vcl_compiler_detection.h" - - lsmrDense::lsmrDense() - { -- this->A = 0; -+ this->A = VXL_NULLPTR; - } - - -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx -index c62c3953a8..8d55fc088a 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/linalg/lsqrDense.cxx -@@ -17,10 +17,11 @@ - *=========================================================================*/ - - #include "lsqrDense.h" -+#include "vcl_compiler_detection.h" - - lsqrDense::lsqrDense() - { -- this->A = 0; -+ this->A = VXL_NULLPTR; - } - - -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h -index 38300975a4..c30ff15ac8 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/sparse/spMatrix.h -@@ -175,15 +175,15 @@ - * Macro function that adds data to a imaginary element in the matrix by - * a pointer. - */ --#define spADD_IMAG_ELEMENT(element,imag) *(element+1) += imag -+#define spADD_IMAG_ELEMENT(element,imag) *((element)+1) += imag - - /*! - * Macro function that adds data to a complex element in the matrix by - * a pointer. - */ - #define spADD_COMPLEX_ELEMENT(element,real,imag) \ --{ *(element) += real; \ -- *(element+1) += imag; \ -+{ *(element) += (real); \ -+ *((element)+1) += (imag); \ - } - - /*! -@@ -191,10 +191,10 @@ - * specified by the given template. - */ - #define spADD_REAL_QUAD(template,real) \ --{ *((template).Element1) += real; \ -- *((template).Element2) += real; \ -- *((template).Element3Negated) -= real; \ -- *((template).Element4Negated) -= real; \ -+{ *((template).Element1) += (real); \ -+ *((template).Element2) += (real); \ -+ *((template).Element3Negated) -= (real); \ -+ *((template).Element4Negated) -= (real); \ - } - - /*! -@@ -202,10 +202,10 @@ - * elements specified by the given template. - */ - #define spADD_IMAG_QUAD(template,imag) \ --{ *((template).Element1+1) += imag; \ -- *((template).Element2+1) += imag; \ -- *((template).Element3Negated+1) -= imag; \ -- *((template).Element4Negated+1) -= imag; \ -+{ *((template).Element1+1) += (imag); \ -+ *((template).Element2+1) += (imag); \ -+ *((template).Element3Negated+1) -= (imag); \ -+ *((template).Element4Negated+1) -= (imag); \ - } - - /*! -@@ -213,14 +213,14 @@ - * elements specified by the given template. - */ - #define spADD_COMPLEX_QUAD(template,real,imag) \ --{ *((template).Element1) += real; \ -- *((template).Element2) += real; \ -- *((template).Element3Negated) -= real; \ -- *((template).Element4Negated) -= real; \ -- *((template).Element1+1) += imag; \ -- *((template).Element2+1) += imag; \ -- *((template).Element3Negated+1) -= imag; \ -- *((template).Element4Negated+1) -= imag; \ -+{ *((template).Element1) += (real); \ -+ *((template).Element2) += (real); \ -+ *((template).Element3Negated) -= (real); \ -+ *((template).Element4Negated) -= (real); \ -+ *((template).Element1+1) += (imag); \ -+ *((template).Element2+1) += (imag); \ -+ *((template).Element3Negated+1) -= (imag); \ -+ *((template).Element4Negated+1) -= (imag); \ - } - - /* -diff --git a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c -index e9b55d33d5..b11058fd9d 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c -+++ b/Modules/ThirdParty/VNL/src/vxl/v3p/netlib/triangle.c -@@ -9232,6 +9232,8 @@ int arraysize; - } - /* Choose a random pivot to split the array. */ - pivot = (int) randomnation((unsigned int) arraysize); -+ if (pivot == arraysize)//JLM without this test, pivot can equal arraysize and segfault -+ pivot--; - pivotx = sortarray[pivot][0]; - pivoty = sortarray[pivot][1]; - /* Split the array. */ -@@ -9308,6 +9310,8 @@ int axis; - } - /* Choose a random pivot to split the array. */ - pivot = (int) randomnation((unsigned int) arraysize); -+ if (pivot == arraysize)//JLM/SES without this test, pivot can equal arraysize and segfault -+ pivot--; - pivot1 = sortarray[pivot][axis]; - pivot2 = sortarray[pivot][1 - axis]; - /* Split the array. */ -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt b/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt -index 89e2b99f71..fed3b8e268 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/CMakeLists.txt -@@ -73,7 +73,7 @@ if( VXL_MANUAL_GENERATE_NEW_COMPILER_DETECTION_HEADERS ) - cxx_long_long_type # long long type, as defined in N1811. - cxx_noexcept # Exception specifications, as defined in N3050. - cxx_nonstatic_member_init # Non-static data member initialization, as defined in N2756. -- cxx_nullptr # Null pointer, as defined in N2431. -+ cxx_VXL_NULLPTR # Null pointer, as defined in N2431. - cxx_override # Override control override keyword, as defined in N2928, N3206 and N3272. - cxx_range_for # Range-based for, as defined in N2930. - cxx_raw_string_literals # Raw string literals, as defined in N2442. -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h -index 196ab2d503..7ff70236c4 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_AppleClang_CXX.h -@@ -226,7 +226,7 @@ - # define VXL_COMPILER_CXX_NONSTATIC_MEMBER_INIT 0 - # endif - --# if ((__clang_major__ * 100) + __clang_minor__) >= 400 && __has_feature(cxx_nullptr) -+# if ((__clang_major__ * 100) + __clang_minor__) >= 400 && __has_feature(cxx_VXL_NULLPTR) - # define VXL_COMPILER_CXX_NULLPTR 1 - # else - # define VXL_COMPILER_CXX_NULLPTR 0 -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h -index 752ad86223..cae90561d2 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/compilers/VXL_COMPILER_INFO_Clang_CXX.h -@@ -225,7 +225,7 @@ - # define VXL_COMPILER_CXX_NONSTATIC_MEMBER_INIT 0 - # endif - --# if ((__clang_major__ * 100) + __clang_minor__) >= 301 && __has_feature(cxx_nullptr) -+# if ((__clang_major__ * 100) + __clang_minor__) >= 301 && __has_feature(cxx_VXL_NULLPTR) - # define VXL_COMPILER_CXX_NULLPTR 1 - # else - # define VXL_COMPILER_CXX_NULLPTR 0 -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx -index 43ba3e5feb..605e73114a 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_atomic_count.cxx -@@ -1,7 +1,7 @@ - #include - #include - --#define TEST(str,x,y) vcl_printf(str ": "); if (x!=y) { vcl_printf("FAILED\n"); status = 1; } else { vcl_printf("PASSED\n"); } -+#define TEST(str,x,y) vcl_printf(str ": "); if ((x)!=(y)) { vcl_printf("FAILED\n"); status = 1; } else { vcl_printf("PASSED\n"); } - - int test_atomic_count_main(int /*argc*/,char* /*argv*/[]) - { -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx -index 5ca2b758e6..ebc552b521 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_cmath.cxx -@@ -24,7 +24,7 @@ int test_cmath_main(int /*argc*/,char* /*argv*/[]) - - #define macro(var, type) \ - do { \ -- if (vcl_abs(var) == var && vcl_abs(- var) == var) \ -+ if (vcl_abs(var) == (var) && vcl_abs(- (var)) == (var)) \ - vcl_cout << "vcl_abs(" #type ") PASSED" << vcl_endl; \ - else \ - vcl_cerr << "vcl_abs(" #type ") *** FAILED *** " << vcl_endl; \ -@@ -58,7 +58,7 @@ do { \ - do { \ - T x = 2; \ - T y = vcl_sqrt(x); \ -- if (vcl_abs(x - y*y) < eps) \ -+ if (vcl_abs(x - y*y) < (eps)) \ - vcl_cout << "vcl_sqrt(" #T ") PASSED" << vcl_endl; \ - else \ - vcl_cout << "vcl_sqrt(" #T ") *** FAILED *** " << vcl_endl; \ -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx -index 4d4fb1aa24..40ed03dd02 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_limits.cxx -@@ -49,8 +49,8 @@ void test_static_const_definition() - #undef TEST_TYPE - } - --#define TEST(m,x,y) if ((x)!=(y)) { vcl_cout<< "FAIL: " << m << '\n'; fail=true; } \ -- else { vcl_cout<< "PASS: " << m << '\n'; } -+#define TEST(m,x,y) if ((x)!=(y)) { vcl_cout<< "FAIL: " << (m) << '\n'; fail=true; } \ -+ else { vcl_cout<< "PASS: " << (m) << '\n'; } - - int test_limits_main(int /*argc*/, char* /*argv*/[]) - { -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx -index a76e92d467..b87977af9f 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_memory.cxx -@@ -14,14 +14,14 @@ struct A - - struct B: public A {}; - --static int function_call(vcl_auto_ptr a) -+static int function_call(vcl_unique_ptr a) - { - return a.get()? 1:0; - } - - static A* get_A(A& a) { return &a; } - --static vcl_auto_ptr generate_auto_ptr () { return vcl_auto_ptr(new A); } -+static vcl_unique_ptr generate_auto_ptr () { return vcl_unique_ptr(new A); } - - int test_memory_main(int /*argc*/,char* /*argv*/[]) - { -@@ -29,11 +29,11 @@ int test_memory_main(int /*argc*/,char* /*argv*/[]) - - // Keep everything in a subscope so we can detect leaks. - { -- vcl_auto_ptr pa0; -- vcl_auto_ptr pa1(new A()); -- vcl_auto_ptr pb1(new B()); -- vcl_auto_ptr pa2(new B()); -- vcl_auto_ptr pa3(pb1); -+ vcl_unique_ptr pa0; -+ vcl_unique_ptr pa1(new A()); -+ vcl_unique_ptr pb1(new B()); -+ vcl_unique_ptr pa2(new B()); -+ vcl_unique_ptr pa3(vcl_move(pb1)); - - A* ptr = get_A(*pa1); - ASSERT(ptr == pa1.get(), -@@ -55,12 +55,12 @@ int test_memory_main(int /*argc*/,char* /*argv*/[]) - delete pa0.release(); - ASSERT(!pa0.get(), "auto_ptr holds an object after release()"); - -- pa1 = pa3; -+ pa1 = vcl_move(pa3); - ASSERT(!pa3.get(), "auto_ptr holds an object after assignment to another"); - ASSERT(pa1.get(), - "auto_ptr does not hold an object after assignment from another"); - -- int copied = function_call(pa2); -+ int copied = function_call(vcl_move(pa2)); - ASSERT(copied, "auto_ptr did not receive ownership in called function"); - ASSERT(!pa2.get(), "auto_ptr did not release ownership to called function"); - -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx -index 32e454954d..9bbbe02526 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/tests/test_sstream.cxx -@@ -2,7 +2,7 @@ - #include - #include - --#define AssertEq(x,y) {status+=((x)==(y))?0:1;vcl_cout<<"TEST ["< 2 ) -+# define VCL_GCC_83 -+# elif (__GNUC_MINOR__ > 1 ) -+# define VCL_GCC_82 -+# elif (__GNUC_MINOR__ > 0 ) -+# define VCL_GCC_81 -+# else -+# define VCL_GCC_80 -+# endif - # else - # error "Dunno about this gcc" - # endif -@@ -897,7 +908,7 @@ __inline int vcl_snprintf(char *outBuf, size_t size, const char *format, ...) - #define vcl_uninitialized_copy std::uninitialized_copy - #define vcl_uninitialized_fill std::uninitialized_fill - #define vcl_uninitialized_fill_n std::uninitialized_fill_n --#define vcl_auto_ptr std::auto_ptr -+#define vcl_auto_ptr vcl_auto_ptr - #define vcl_bad_alloc std::bad_alloc - #define vcl_set_new_handler std::set_new_handler - #define vcl_accumulate std::accumulate -diff --git a/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h b/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h -index b15a5f4368..da038dd721 100644 ---- a/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h -+++ b/Modules/ThirdParty/VNL/src/vxl/vcl/vcl_memory.h -@@ -2,6 +2,19 @@ - #define vcl_memory_h_ - - #include -+#include - #include "vcl_compiler.h" - -+// Needed to provide backwards compatibility between C++11 and older compilers -+// https://softwareengineering.stackexchange.com/questions/291141/how-to-handle-design-changes-for-auto-ptr-deprecation-in-c11 -+#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER > 540) -+ template -+ using vcl_unique_ptr = std::unique_ptr; -+ #define vcl_move( value ) std::move(value) -+#else -+// NOTE: THIS DOES NOT MEET THE STANDARDS FOR A UNIQUE POINTER! -+# define vcl_unique_ptr std::auto_ptr -+# define vcl_move( value ) value -+#endif -+ - #endif // vcl_memory_h_ diff --git a/CMakeExternals/ITK.cmake b/CMakeExternals/ITK.cmake index 0109ff72a3..62654da969 100644 --- a/CMakeExternals/ITK.cmake +++ b/CMakeExternals/ITK.cmake @@ -1,77 +1,75 @@ #----------------------------------------------------------------------------- # ITK #----------------------------------------------------------------------------- # Sanity checks if(DEFINED ITK_DIR AND NOT EXISTS ${ITK_DIR}) message(FATAL_ERROR "ITK_DIR variable is defined but corresponds to non-existing directory") endif() set(proj ITK) set(proj_DEPENDENCIES GDCM) if(MITK_USE_OpenCV) list(APPEND proj_DEPENDENCIES OpenCV) endif() if(MITK_USE_HDF5) list(APPEND proj_DEPENDENCIES HDF5) endif() set(ITK_DEPENDS ${proj}) if(NOT DEFINED ITK_DIR) set(additional_cmake_args -DUSE_WRAP_ITK:BOOL=OFF) if(MITK_USE_OpenCV) list(APPEND additional_cmake_args -DModule_ITKVideoBridgeOpenCV:BOOL=ON -DOpenCV_DIR:PATH=${OpenCV_DIR} ) endif() # Keep the behaviour of ITK 4.3 which by default turned on ITK Review # see MITK bug #17338 list(APPEND additional_cmake_args -DModule_ITKReview:BOOL=ON # for 4.7, the OpenJPEG is needed by review but the variable must be set -DModule_ITKOpenJPEG:BOOL=ON ) if(CTEST_USE_LAUNCHERS) list(APPEND additional_cmake_args "-DCMAKE_PROJECT_${proj}_INCLUDE:FILEPATH=${CMAKE_ROOT}/Modules/CTestUseLaunchers.cmake" ) endif() ExternalProject_Add(${proj} LIST_SEPARATOR ${sep} - URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.13.0.tar.xz - URL_MD5 3badf70cfb0093054453f66c5974c5a4 - # work with external GDCM - PATCH_COMMAND ${PATCH_COMMAND} -N -p1 -i ${CMAKE_CURRENT_LIST_DIR}/ITK-VNL-2018-05-16.patch + URL ${MITK_THIRDPARTY_DOWNLOAD_PREFIX_URL}/InsightToolkit-4.13.1.tar.xz + URL_MD5 bc7296e7faccdcb5656a7669d4d875d2 CMAKE_GENERATOR ${gen} CMAKE_ARGS ${ep_common_args} ${additional_cmake_args} -DBUILD_EXAMPLES:BOOL=OFF -DITK_USE_SYSTEM_GDCM:BOOL=ON -DGDCM_DIR:PATH=${GDCM_DIR} -DITK_USE_SYSTEM_HDF5:BOOL=ON -DHDF5_DIR:PATH=${HDF5_DIR} CMAKE_CACHE_ARGS ${ep_common_cache_args} CMAKE_CACHE_DEFAULT_ARGS ${ep_common_cache_default_args} DEPENDS ${proj_DEPENDENCIES} ) set(ITK_DIR ${ep_prefix}) mitkFunctionInstallExternalCMakeProject(${proj}) else() mitkMacroEmptyExternalProject(${proj} "${proj_DEPENDENCIES}") endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 58ef8a6fea..1ba3dabb29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,1347 +1,1384 @@ set(MITK_CMAKE_MINIMUM_REQUIRED_VERSION 3.10) cmake_minimum_required(VERSION ${MITK_CMAKE_MINIMUM_REQUIRED_VERSION}) #----------------------------------------------------------------------------- # See https://cmake.org/cmake/help/v3.10/manual/cmake-policies.7.html for details #----------------------------------------------------------------------------- set(project_policies ) foreach(policy ${project_policies}) if(POLICY ${policy}) cmake_policy(SET ${policy} NEW) endif() endforeach() #----------------------------------------------------------------------------- # MITK Extension Feature #----------------------------------------------------------------------------- set(MITK_EXTENSION_DIRS "" CACHE STRING "") mark_as_advanced(MITK_EXTENSION_DIRS) #----------------------------------------------------------------------------- # Superbuild Option - Enabled by default #----------------------------------------------------------------------------- option(MITK_USE_SUPERBUILD "Build MITK and the projects it depends on via SuperBuild.cmake." ON) if(MITK_USE_SUPERBUILD) project(MITK-superbuild) set(MITK_SOURCE_DIR ${PROJECT_SOURCE_DIR}) set(MITK_BINARY_DIR ${PROJECT_BINARY_DIR}) else() project(MITK VERSION 2016.11.99) include_directories(SYSTEM ${MITK_SUPERBUILD_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Update CMake module path #----------------------------------------------------------------------------- set(MITK_CMAKE_DIR ${MITK_SOURCE_DIR}/CMake) set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR}) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_CMAKE_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake) get_filename_component(MITK_CMAKE_EXTENSION_DIR ${MITK_CMAKE_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_CMAKE_EXTENSION_DIR}) list(APPEND CMAKE_MODULE_PATH ${MITK_CMAKE_EXTENSION_DIR}) endif() endforeach() #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- # Standard CMake macros include(FeatureSummary) include(CTestUseLaunchers) include(CMakeParseArguments) include(FindPackageHandleStandardArgs) # MITK macros include(mitkFunctionGetGccVersion) include(mitkFunctionCheckCompilerFlags) include(mitkFunctionSuppressWarnings) # includes several functions include(mitkMacroEmptyExternalProject) include(mitkFunctionGenerateProjectXml) include(mitkFunctionEnableBuildConfiguration) include(mitkFunctionWhitelists) include(mitkFunctionAddExternalProject) SUPPRESS_VC_DEPRECATED_WARNINGS() #----------------------------------------------------------------------------- # Set a default build type if none was specified #----------------------------------------------------------------------------- if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to 'Debug' as none was specified.") set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) # Set the possible values of build type for cmake-gui set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") endif() #----------------------------------------------------------------------------- -# Check miminum Mac OS X version +# Check miminum macOS version #----------------------------------------------------------------------------- -# The minimum supported Mac OS X version is 10.9. If you use a version less than 10.9, there is no guarantee that the build still works. +# The minimum supported macOS version is 10.13. If you use a version less than 10.13, there is no guarantee that the build still works. if(APPLE) - exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE osx_version) - if (osx_version VERSION_LESS "10.9") - message(WARNING "Detected OS X version \"${osx_version}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") + exec_program(sw_vers ARGS -productVersion OUTPUT_VARIABLE macos_version) + if (macos_version VERSION_LESS "10.13") + message(WARNING "Detected macOS version \"${macos_version}\" is not supported anymore. Minimum required macOS version is at least 10.13.") endif() - if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.9) - message(WARNING "Detected OS X deployment target \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" is not supported anymore. Minimum required OS X version is 10.9 or greater.") + if (CMAKE_OSX_DEPLOYMENT_TARGET AND CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS 10.13) + message(WARNING "Detected macOS deployment target \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" is not supported anymore. Minimum required macOS version is at least 10.13.") endif() endif() #----------------------------------------------------------------------------- # Check miminum compiler versions #----------------------------------------------------------------------------- if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # require at least gcc 4.9 as provided by ppa:ubuntu-toolchain-r/test for Ubuntu 14.04 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9) message(FATAL_ERROR "GCC version must be at least 4.9 If you are using Ubuntu 14.04, you can easily install gcc and g++ 4.9 (or any later version available) in addition to your version ${CMAKE_CXX_COMPILER_VERSION}: sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-4.9 g++-4.9 Make sure to explicitly specify these compilers when configuring MITK: CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc-4.9 CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/g++-4.9 For more information on the proposed PPA see the Toolchain Updates section of https://wiki.ubuntu.com/ToolChain.") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # require at least clang 3.4 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.4) message(FATAL_ERROR "Clang version must be at least 3.4") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") # require at least clang 5.0 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0) message(FATAL_ERROR "Apple Clang version must be at least 5.0") endif() elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # require at least Visual Studio 2015 if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) message(FATAL_ERROR "Microsoft Visual Studio 2017 or newer required") endif() else() message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang (Linux or Apple), GCC and MSVC.") endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionGetGccVersion(${CMAKE_CXX_COMPILER} GCC_VERSION) else() set(GCC_VERSION 0) endif() set(MITK_CXX_STANDARD 14) set(CMAKE_CXX_EXTENSIONS 0) set(CMAKE_CXX_STANDARD ${MITK_CXX_STANDARD}) set(CMAKE_CXX_STANDARD_REQUIRED 1) # This is necessary to avoid problems with compile feature checks. # CMAKE_CXX_STANDARD seems to only set the -std=c++14 flag for targets. # However, compile flag checks also need to be done with -std=c++14. # The MITK_CXX14_FLAG variable is also used for external projects # build during the MITK super-build. mitkFunctionCheckCompilerFlags("-std=c++14" MITK_CXX14_FLAG) #----------------------------------------------------------------------------- # Warn if source or build path is too long #----------------------------------------------------------------------------- if(WIN32) set(_src_dir_length_max 50) set(_bin_dir_length_max 50) if(MITK_USE_SUPERBUILD) set(_src_dir_length_max 34) # _src_dir_length_max - strlen(ep/src/ITK-build) set(_bin_dir_length_max 40) # _bin_dir_length_max - strlen(MITK-build) endif() string(LENGTH "${MITK_SOURCE_DIR}" _src_n) string(LENGTH "${MITK_BINARY_DIR}" _bin_n) # The warnings should be converted to errors if(_src_n GREATER _src_dir_length_max) message(WARNING "MITK source code directory path length is too long (${_src_n} > ${_src_dir_length_max})." "Please move the MITK source code directory to a directory with a shorter path." ) endif() if(_bin_n GREATER _bin_dir_length_max) message(WARNING "MITK build directory path length is too long (${_bin_n} > ${_bin_dir_length_max})." "Please move the MITK build directory to a directory with a shorter path." ) endif() endif() #----------------------------------------------------------------------------- # Additional MITK Options (also shown during superbuild) #----------------------------------------------------------------------------- macro(env_option name doc value) set(_value $ENV{${name}}) if("${_value}" STREQUAL "") set(_value ${value}) endif() option(${name} "${doc}" ${_value}) endmacro() # ----------------------------------------- # General build options option(BUILD_SHARED_LIBS "Build MITK with shared libraries" ON) option(WITH_COVERAGE "Enable/Disable coverage" OFF) option(BUILD_TESTING "Test the project" ON) env_option(MITK_BUILD_ALL_APPS "Build all MITK applications" OFF) env_option(MITK_BUILD_EXAMPLES "Build the MITK Examples" OFF) option(MITK_ENABLE_PIC_READER "Enable support for reading the DKFZ pic file format." ON) mark_as_advanced(MITK_BUILD_ALL_APPS MITK_ENABLE_PIC_READER ) # ----------------------------------------- # Qt version related variables env_option(MITK_USE_Qt5 "Use Qt 5 library" ON) if(MITK_USE_Qt5) set(MITK_QT5_MINIMUM_VERSION 5.11.1) set(MITK_QT5_COMPONENTS Concurrent OpenGL PrintSupport Script Sql Svg Widgets Xml XmlPatterns WebEngineWidgets UiTools Help LinguistTools) if(APPLE) - set(MITK_QT5_COMPONENTS ${MITK_QT5_COMPONENTS} DBus) + list(APPEND MITK_QT5_COMPONENTS DBus) endif() - find_package(Qt5 ${MITK_QT5_MINIMUM_VERSION} COMPONENTS ${MITK_QT5_COMPONENTS} REQUIRED) + + # Hint at default install locations of Qt + if(NOT Qt5_DIR) + if(MSVC) + set(_dir_candidates "C:/Qt") + + if(CMAKE_GENERATOR MATCHES "^Visual Studio [0-9]+ ([0-9]+)") + set(_compiler "msvc${CMAKE_MATCH_1}") + endif() + else() + set(_dir_candidates ~/Qt) + + if(APPLE) + set(_compiler clang) + else() + list(APPEND _dir_candidates /opt/Qt) + set(_compiler gcc) + endif() + endif() + + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(_compiler "${_compiler}_64") + endif() + + foreach(_dir_candidate ${_dir_candidates}) + get_filename_component(_dir_candidate ${_dir_candidate} REALPATH) + set(_glob_expression "${_dir_candidate}/5.*/${_compiler}") + file(GLOB _hints ${_glob_expression}) + list(SORT _hints) + list(APPEND MITK_QT5_HINTS ${_hints}) + endforeach() + endif() + + find_package(Qt5 ${MITK_QT5_MINIMUM_VERSION} COMPONENTS ${MITK_QT5_COMPONENTS} REQUIRED HINTS ${MITK_QT5_HINTS}) endif() set_property(GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS "") include(CMakeExternals/ExternalProjectList.cmake) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMakeExternals) get_filename_component(MITK_CMAKE_EXTERNALS_EXTENSION_DIR ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/ExternalProjectList.cmake) include(${MITK_CMAKE_EXTERNALS_EXTENSION_DIR}/ExternalProjectList.cmake) endif() endforeach() # ----------------------------------------- # Other MITK_USE_* options not related to # external projects build via the # MITK superbuild env_option(MITK_USE_BLUEBERRY "Build the BlueBerry platform" ON) env_option(MITK_USE_OpenCL "Use OpenCL GPU-Computing library" OFF) #----------------------------------------------------------------------------- # Build configurations #----------------------------------------------------------------------------- set(_buildConfigs "Custom") file(GLOB _buildConfigFiles CMake/BuildConfigurations/*.cmake) foreach(_buildConfigFile ${_buildConfigFiles}) get_filename_component(_buildConfigFile ${_buildConfigFile} NAME_WE) list(APPEND _buildConfigs ${_buildConfigFile}) endforeach() set(MITK_BUILD_CONFIGURATION "Custom" CACHE STRING "Use pre-defined MITK configurations") set_property(CACHE MITK_BUILD_CONFIGURATION PROPERTY STRINGS ${_buildConfigs}) mitkFunctionEnableBuildConfiguration() mitkFunctionCreateWhitelistPaths(MITK) mitkFunctionFindWhitelists(MITK) # ----------------------------------------- # Custom dependency logic option(MITK_USE_SYSTEM_Boost "Use the system Boost" OFF) set(MITK_USE_Boost_LIBRARIES "" CACHE STRING "A semi-colon separated list of required Boost libraries") # only windows can't build python in debug mode if(MITK_USE_Python AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" AND WIN32) message(WARNING "Disabling Python support. Building MITK Python in debug mode on Windowsis not supported!") set(MITK_USE_Python OFF CACHE BOOL "Use python wrapping in MITK" FORCE) set(MITK_USE_Numpy OFF CACHE BOOL "Use Numpy" FORCE) set(MITK_USE_SimpleITK OFF CACHE BOOL "Use SimpleITK" FORCE) elseif(MITK_USE_Python) set(MITK_USE_ZLIB ON) if(NOT MITK_USE_Numpy) message("> Forcing MITK_USE_Numpy to ON because of MITK_USE_Python") set(MITK_USE_Numpy ON CACHE BOOL "Use Numpy" FORCE) endif() if(NOT MITK_USE_SimpleITK) message("> Forcing MITK_USE_SimpleITK to ON because of MITK_USE_Python") set(MITK_USE_SimpleITK ON CACHE BOOL "Use SimpleITK" FORCE) endif() find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) elseif(MITK_USE_Python AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" AND WIN32) message(WARNING "Disabling Python support. Building MITK Python in debug mode on Windowsis not supported!") set(MITK_USE_Python OFF CACHE BOOL "Use python wrapping in MITK" FORCE) endif() if(BUILD_TESTING AND NOT MITK_USE_CppUnit) message("> Forcing MITK_USE_CppUnit to ON because BUILD_TESTING=ON") set(MITK_USE_CppUnit ON CACHE BOOL "Use CppUnit for unit tests" FORCE) endif() if(MITK_USE_BLUEBERRY) option(MITK_BUILD_ALL_PLUGINS "Build all MITK plugins" OFF) mark_as_advanced(MITK_BUILD_ALL_PLUGINS) if(NOT MITK_USE_CTK) message("> Forcing MITK_USE_CTK to ON because of MITK_USE_BLUEBERRY") set(MITK_USE_CTK ON CACHE BOOL "Use CTK in MITK" FORCE) endif() endif() #----------------------------------------------------------------------------- # Pixel type multiplexing #----------------------------------------------------------------------------- # Customize the default pixel types for multiplex macros set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros") set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") mark_as_advanced(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES MITK_ACCESSBYITK_DIMENSIONS ) # consistency checks if(NOT MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES) set(MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES "int, unsigned int, short, unsigned short, char, unsigned char" CACHE STRING "List of integral pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES) set(MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES "double, float" CACHE STRING "List of floating pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES) set(MITK_ACCESSBYITK_COMPOSITE_PIXEL_TYPES "itk::RGBPixel, itk::RGBAPixel" CACHE STRING "List of composite pixel types used in AccessByItk and InstantiateAccessFunction macros" FORCE) endif() if(NOT MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) string(REPLACE "," ";" _integral_types ${MITK_ACCESSBYITK_INTEGRAL_PIXEL_TYPES}) string(REPLACE "," ";" _floating_types ${MITK_ACCESSBYITK_FLOATING_PIXEL_TYPES}) foreach(_scalar_type ${_integral_types} ${_floating_types}) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}itk::VariableLengthVector<${_scalar_type}>,") endforeach() string(LENGTH "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" _length) math(EXPR _length "${_length} - 1") string(SUBSTRING "${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES}" 0 ${_length} MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES) set(MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES ${MITK_ACCESSBYITK_VECTOR_PIXEL_TYPES} CACHE STRING "List of vector pixel types used in AccessByItk and InstantiateAccessFunction macros for itk::VectorImage types" FORCE) endif() if(NOT MITK_ACCESSBYITK_DIMENSIONS) set(MITK_ACCESSBYITK_DIMENSIONS "2,3" CACHE STRING "List of dimensions used in AccessByItk and InstantiateAccessFunction macros") endif() #----------------------------------------------------------------------------- # Project.xml #----------------------------------------------------------------------------- # A list of topologically ordered targets set(CTEST_PROJECT_SUBPROJECTS) list(APPEND CTEST_PROJECT_SUBPROJECTS MITK-Core MITK-CoreUI MITK-IGT MITK-ToF MITK-DTI MITK-Modules # all modules not contained in a specific subproject MITK-Plugins # all plugins not contained in a specific subproject MITK-Examples Unlabeled # special "subproject" catching all unlabeled targets and tests ) # Configure CTestConfigSubProject.cmake that could be used by CTest scripts configure_file(${MITK_SOURCE_DIR}/CTestConfigSubProject.cmake.in ${MITK_BINARY_DIR}/CTestConfigSubProject.cmake) if(CTEST_PROJECT_ADDITIONAL_TARGETS) # those targets will be executed at the end of the ctest driver script # and they also get their own subproject label set(subproject_list "${CTEST_PROJECT_SUBPROJECTS};${CTEST_PROJECT_ADDITIONAL_TARGETS}") else() set(subproject_list "${CTEST_PROJECT_SUBPROJECTS}") endif() # Generate Project.xml file expected by the CTest driver script mitkFunctionGenerateProjectXml(${MITK_BINARY_DIR} MITK "${subproject_list}" ${MITK_USE_SUPERBUILD}) #----------------------------------------------------------------------------- # Superbuild script #----------------------------------------------------------------------------- if(MITK_USE_SUPERBUILD) include("${CMAKE_CURRENT_SOURCE_DIR}/SuperBuild.cmake") # Print configuration summary message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL) return() endif() #***************************************************************************** #**************************** END OF SUPERBUILD **************************** #***************************************************************************** #----------------------------------------------------------------------------- # CMake function(s) and macro(s) #----------------------------------------------------------------------------- include(WriteBasicConfigVersionFile) include(CheckCXXSourceCompiles) include(GenerateExportHeader) include(mitkFunctionAddCustomModuleTest) include(mitkFunctionCheckModuleDependencies) include(mitkFunctionCompileSnippets) include(mitkFunctionConfigureVisualStudioUserProjectFile) include(mitkFunctionConvertXPSchema) include(mitkFunctionCreateBlueBerryApplication) include(mitkFunctionCreateCommandLineApp) include(mitkFunctionCreateModule) include(mitkFunctionCreatePlugin) include(mitkFunctionCreateProvisioningFile) include(mitkFunctionGetLibrarySearchPaths) include(mitkFunctionGetVersion) include(mitkFunctionGetVersionDescription) include(mitkFunctionInstallAutoLoadModules) include(mitkFunctionInstallCTKPlugin) include(mitkFunctionInstallProvisioningFiles) include(mitkFunctionInstallThirdPartyCTKPlugins) include(mitkFunctionOrganizeSources) include(mitkFunctionTestPlugin) include(mitkFunctionUseModules) if( ${MITK_USE_MatchPoint} ) include(mitkFunctionCreateMatchPointDeployedAlgorithm) endif() include(mitkMacroConfigureItkPixelTypes) include(mitkMacroCreateExecutable) include(mitkMacroCreateModuleTests) include(mitkMacroGenerateToolsLibrary) include(mitkMacroGetLinuxDistribution) include(mitkMacroGetPMDPlatformString) include(mitkMacroInstall) include(mitkMacroInstallHelperApp) include(mitkMacroInstallTargets) include(mitkMacroMultiplexPicType) # Deprecated include(mitkMacroCreateCTKPlugin) #----------------------------------------------------------------------------- # Global CMake variables #----------------------------------------------------------------------------- # Required and enabled C++14 features for all MITK code. # These are added as PUBLIC compile features to all MITK modules. set(MITK_CXX_FEATURES cxx_auto_type cxx_decltype cxx_enum_forward_declarations cxx_extended_friend_declarations cxx_extern_templates cxx_final cxx_lambdas cxx_local_type_template_args cxx_long_long_type cxx_nullptr cxx_override cxx_range_for cxx_right_angle_brackets cxx_rvalue_references cxx_static_assert cxx_strong_enums cxx_template_template_parameters cxx_trailing_return_types cxx_variadic_macros ) if(NOT DEFINED CMAKE_DEBUG_POSTFIX) # We can't do this yet because the CTK Plugin Framework # cannot cope with a postfix yet. #set(CMAKE_DEBUG_POSTFIX d) endif() #----------------------------------------------------------------------------- # Output directories. #----------------------------------------------------------------------------- set(_default_LIBRARY_output_dir lib) set(_default_RUNTIME_output_dir bin) set(_default_ARCHIVE_output_dir lib) foreach(type LIBRARY RUNTIME ARCHIVE) # Make sure the directory exists if(MITK_CMAKE_${type}_OUTPUT_DIRECTORY AND NOT EXISTS ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) message("Creating directory MITK_CMAKE_${type}_OUTPUT_DIRECTORY: ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") file(MAKE_DIRECTORY "${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}") endif() if(MITK_CMAKE_${type}_OUTPUT_DIRECTORY) set(CMAKE_${type}_OUTPUT_DIRECTORY ${MITK_CMAKE_${type}_OUTPUT_DIRECTORY}) else() set(CMAKE_${type}_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${_default_${type}_output_dir}) set(MITK_CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY}) endif() set(CMAKE_${type}_OUTPUT_DIRECTORY ${CMAKE_${type}_OUTPUT_DIRECTORY} CACHE INTERNAL "Output directory for ${type} files.") mark_as_advanced(CMAKE_${type}_OUTPUT_DIRECTORY) endforeach() #----------------------------------------------------------------------------- # Set MITK specific options and variables (NOT available during superbuild) #----------------------------------------------------------------------------- # Look for optional Doxygen package find_package(Doxygen) option(BLUEBERRY_DEBUG_SMARTPOINTER "Enable code for debugging smart pointers" OFF) mark_as_advanced(BLUEBERRY_DEBUG_SMARTPOINTER) # ASK THE USER TO SHOW THE CONSOLE WINDOW FOR CoreApp and mitkWorkbench option(MITK_SHOW_CONSOLE_WINDOW "Use this to enable or disable the console window when starting MITK GUI Applications" ON) mark_as_advanced(MITK_SHOW_CONSOLE_WINDOW) # TODO: check if necessary option(USE_ITKZLIB "Use the ITK zlib for pic compression." ON) mark_as_advanced(USE_ITKZLIB) if(NOT MITK_FAST_TESTING) if(DEFINED MITK_CTEST_SCRIPT_MODE AND (MITK_CTEST_SCRIPT_MODE STREQUAL "continuous" OR MITK_CTEST_SCRIPT_MODE STREQUAL "experimental") ) set(MITK_FAST_TESTING 1) endif() endif() if(NOT UNIX) set(MITK_WIN32_FORCE_STATIC "STATIC" CACHE INTERNAL "Use this variable to always build static libraries on non-unix platforms") endif() if(MITK_BUILD_ALL_PLUGINS) set(MITK_BUILD_ALL_PLUGINS_OPTION "FORCE_BUILD_ALL") endif() # Configure pixel types used for ITK image access multiplexing mitkMacroConfigureItkPixelTypes() # Configure module naming conventions set(MITK_MODULE_NAME_REGEX_MATCH "^[A-Z].*$") set(MITK_MODULE_NAME_REGEX_NOT_MATCH "^[Mm][Ii][Tt][Kk].*$") set(MITK_DEFAULT_MODULE_NAME_PREFIX "Mitk") set(MITK_MODULE_NAME_PREFIX ${MITK_DEFAULT_MODULE_NAME_PREFIX}) set(MITK_MODULE_NAME_DEFAULTS_TO_DIRECTORY_NAME 1) #----------------------------------------------------------------------------- # Get MITK version info #----------------------------------------------------------------------------- mitkFunctionGetVersion(${MITK_SOURCE_DIR} MITK) mitkFunctionGetVersionDescription(${MITK_SOURCE_DIR} MITK) # MITK_VERSION set(MITK_VERSION_STRING "${MITK_VERSION_MAJOR}.${MITK_VERSION_MINOR}.${MITK_VERSION_PATCH}") if(MITK_VERSION_PATCH STREQUAL "99") set(MITK_VERSION_STRING "${MITK_VERSION_STRING}-${MITK_REVISION_SHORTID}") endif() #----------------------------------------------------------------------------- # Installation preparation # # These should be set before any MITK install macros are used #----------------------------------------------------------------------------- -# on Mac OSX all BlueBerry plugins get copied into every +# on macOS all BlueBerry plugins get copied into every # application bundle (.app directory) specified here if(MITK_USE_BLUEBERRY AND APPLE) include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) list(GET target_info_list 0 app_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) set(MACOSX_BUNDLE_NAMES ${MACOSX_BUNDLE_NAMES} Mitk${app_name}) endif() endforeach() endif() #----------------------------------------------------------------------------- # Set coverage Flags #----------------------------------------------------------------------------- if(WITH_COVERAGE) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(coverage_flags "-g -fprofile-arcs -ftest-coverage -O0 -DNDEBUG") set(COVERAGE_CXX_FLAGS ${coverage_flags}) set(COVERAGE_C_FLAGS ${coverage_flags}) endif() endif() #----------------------------------------------------------------------------- # MITK C/CXX Flags #----------------------------------------------------------------------------- set(MITK_C_FLAGS "${COVERAGE_C_FLAGS}") set(MITK_C_FLAGS_DEBUG ) set(MITK_C_FLAGS_RELEASE ) set(MITK_CXX_FLAGS "${COVERAGE_CXX_FLAGS} ${MITK_CXX14_FLAG}") set(MITK_CXX_FLAGS_DEBUG ) set(MITK_CXX_FLAGS_RELEASE ) set(MITK_EXE_LINKER_FLAGS ) set(MITK_SHARED_LINKER_FLAGS ) find_package(OpenMP) if (OPENMP_FOUND) set(MITK_C_FLAGS "${MITK_C_FLAGS} ${OpenMP_C_FLAGS}") set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") endif() if(WIN32) set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -D_WIN32_WINNT=0x0501 -DPOCO_NO_UNWINDOWS -DWIN32_LEAN_AND_MEAN -DNOMINMAX") mitkFunctionCheckCompilerFlags("/wd4005" MITK_CXX_FLAGS) # warning C4005: macro redefinition mitkFunctionCheckCompilerFlags("/wd4231" MITK_CXX_FLAGS) # warning C4231: nonstandard extension used : 'extern' before template explicit instantiation # the following line should be removed after fixing bug 17637 mitkFunctionCheckCompilerFlags("/wd4316" MITK_CXX_FLAGS) # warning C4316: object alignment on heap mitkFunctionCheckCompilerFlags("/wd4180" MITK_CXX_FLAGS) # warning C4180: qualifier applied to function type has no meaning endif() +if(APPLE) + set(MITK_CXX_FLAGS "${MITK_CXX_FLAGS} -DGL_SILENCE_DEPRECATION") # Apple deprecated OpenGL in macOS 10.14 +endif() + if(NOT MSVC_VERSION) foreach(_flag -Wall -Wextra -Wpointer-arith -Winvalid-pch -Wcast-align -Wwrite-strings -Wno-error=gnu -Wno-error=unknown-pragmas # The strict-overflow warning is generated by ITK template code -Wno-error=strict-overflow -Woverloaded-virtual -Wstrict-null-sentinel #-Wold-style-cast #-Wsign-promo -Wno-array-bounds -fdiagnostics-show-option ) mitkFunctionCheckCAndCXXCompilerFlags(${_flag} MITK_C_FLAGS MITK_CXX_FLAGS) endforeach() endif() if(CMAKE_COMPILER_IS_GNUCXX AND NOT APPLE) mitkFunctionCheckCompilerFlags("-Wl,--no-undefined" MITK_SHARED_LINKER_FLAGS) mitkFunctionCheckCompilerFlags("-Wl,--as-needed" MITK_SHARED_LINKER_FLAGS) endif() if(CMAKE_COMPILER_IS_GNUCXX) mitkFunctionCheckCAndCXXCompilerFlags("-fstack-protector-all" MITK_C_FLAGS MITK_CXX_FLAGS) set(MITK_CXX_FLAGS_RELEASE "-U_FORTIFY_SOURCES -D_FORTIFY_SOURCE=2 ${MITK_CXX_FLAGS_RELEASE}") endif() set(MITK_MODULE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) set(MITK_EXE_LINKER_FLAGS ${MITK_SHARED_LINKER_FLAGS}) #----------------------------------------------------------------------------- # MITK Packages #----------------------------------------------------------------------------- set(MITK_MODULES_PACKAGE_DEPENDS_DIR ${MITK_SOURCE_DIR}/CMake/PackageDepends) set(MODULES_PACKAGE_DEPENDS_DIRS ${MITK_MODULES_PACKAGE_DEPENDS_DIR}) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_PACKAGE_DEPENDS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/CMake/PackageDepends) get_filename_component(MITK_PACKAGE_DEPENDS_EXTENSION_DIR ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR}) list(APPEND MODULES_PACKAGE_DEPENDS_DIRS ${MITK_PACKAGE_DEPENDS_EXTENSION_DIR}) endif() endforeach() if(NOT MITK_USE_SYSTEM_Boost) set(Boost_NO_SYSTEM_PATHS 1) endif() set(Boost_USE_MULTITHREADED 1) set(Boost_USE_STATIC_LIBS 0) set(Boost_USE_STATIC_RUNTIME 0) -set(Boost_ADDITIONAL_VERSIONS "1.65" "1.65.1") +set(Boost_ADDITIONAL_VERSIONS "1.65" "1.65.1" "1.66" "1.67" "1.68" "1.68.0") # We need this later for a DCMTK workaround set(_dcmtk_dir_orig ${DCMTK_DIR}) # This property is populated at the top half of this file get_property(MITK_EXTERNAL_PROJECTS GLOBAL PROPERTY MITK_EXTERNAL_PROJECTS) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(MITK_USE_${ep} AND _package) if(_components) find_package(${_package} COMPONENTS ${_components} REQUIRED CONFIG) else() # Prefer config mode first because it finds external # Config.cmake files pointed at by _DIR variables. # Otherwise, existing Find.cmake files could fail. if(DEFINED ${_package}_DIR) #we store the information because it will be overwritten by find_package #and would get lost for all EPs that use on Find.cmake instead of config #files. set(_temp_EP_${_package}_dir ${${_package}_DIR}) endif(DEFINED ${_package}_DIR) find_package(${_package} QUIET CONFIG) string(TOUPPER "${_package}" _package_uc) if(NOT (${_package}_FOUND OR ${_package_uc}_FOUND)) if(DEFINED _temp_EP_${_package}_dir) set(${_package}_DIR ${_temp_EP_${_package}_dir} CACHE PATH "externaly set dir of the package ${_package}" FORCE) endif(DEFINED _temp_EP_${_package}_dir) find_package(${_package} REQUIRED) endif() endif() endif() endforeach() # Ensure that the MITK CMake module path comes first set(CMAKE_MODULE_PATH ${MITK_CMAKE_DIR} ${CMAKE_MODULE_PATH} ) if(MITK_USE_DCMTK) # Due to the preferred CONFIG mode in find_package calls above, # the DCMTKConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMTK. if(${_dcmtk_dir_orig} MATCHES "${MITK_EXTERNAL_PROJECT_PREFIX}.*") # Help our FindDCMTK.cmake script find our super-build DCMTK set(DCMTK_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) else() # Use the original value set(DCMTK_DIR ${_dcmtk_dir_orig}) endif() find_package(DCMTK REQUIRED MODULE) endif() if(MITK_USE_DCMQI) # Due to the preferred CONFIG mode in find_package calls above, # the DCMQIConfig.cmake file is read, which does not provide useful # package information. We explictly need MODULE mode to find DCMQI. # Help our FindDCMQI.cmake script find our super-build DCMQI set(DCMQI_DIR ${MITK_EXTERNAL_PROJECT_PREFIX}) find_package(DCMQI REQUIRED) endif() if(MITK_USE_Python) find_package(PythonLibs REQUIRED) find_package(PythonInterp REQUIRED) if(MITK_USE_Numpy) find_package(Numpy REQUIRED) endif() endif() link_directories(${Boost_LIBRARY_DIRS}) if(MITK_USE_OpenIGTLink) link_directories(${OpenIGTLink_LIBRARY_DIRS}) endif() if(MITK_USE_SimpleITK) link_directories(${SimpleITK_LIBRARY_DIRS}) endif() if(MITK_USE_OpenCL) find_package(OpenCL REQUIRED) endif() # Qt support if(MITK_USE_Qt5) find_package(Qt5Core ${MITK_QT5_MINIMUM_VERSION} REQUIRED) # at least Core required get_target_property(_qmake_exec Qt5::qmake LOCATION) execute_process(COMMAND ${_qmake_exec} -query QT_INSTALL_BINS RESULT_VARIABLE _result OUTPUT_VARIABLE QT_BINARY_DIR ERROR_VARIABLE _error ) string(STRIP "${QT_BINARY_DIR}" QT_BINARY_DIR) if(_result OR NOT EXISTS "${QT_BINARY_DIR}") message(FATAL_ERROR "Could not determine Qt binary directory: ${_result} ${QT_BINARY_DIR} ${_error}") endif() find_program(QT_HELPGENERATOR_EXECUTABLE NAMES qhelpgenerator qhelpgenerator-qt5 qhelpgenerator5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_COLLECTIONGENERATOR_EXECUTABLE NAMES qcollectiongenerator qcollectiongenerator-qt5 qcollectiongenerator5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_ASSISTANT_EXECUTABLE NAMES assistant assistant-qt5 assistant5 PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) find_program(QT_XMLPATTERNS_EXECUTABLE NAMES xmlpatterns PATHS ${QT_BINARY_DIR} NO_DEFAULT_PATH ) mark_as_advanced(QT_HELPGENERATOR_EXECUTABLE QT_COLLECTIONGENERATOR_EXECUTABLE QT_ASSISTANT_EXECUTABLE QT_XMLPATTERNS_EXECUTABLE ) if(MITK_USE_BLUEBERRY) option(BLUEBERRY_USE_QT_HELP "Enable support for integrating plugin documentation into Qt Help" ${DOXYGEN_FOUND}) mark_as_advanced(BLUEBERRY_USE_QT_HELP) # Sanity checks for in-application BlueBerry plug-in help generation if(BLUEBERRY_USE_QT_HELP) set(_force_blueberry_use_qt_help_to_off 0) if(NOT DOXYGEN_FOUND) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen was not found.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(DOXYGEN_FOUND AND DOXYGEN_VERSION VERSION_LESS 1.8.7) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because Doxygen version 1.8.7 or newer not found.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT QT_HELPGENERATOR_EXECUTABLE) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because QT_HELPGENERATOR_EXECUTABLE is empty.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT MITK_USE_Qt5) message("> Forcing BLUEBERRY_USE_QT_HELP to OFF because MITK_USE_Qt5 is OFF.") set(_force_blueberry_use_qt_help_to_off 1) endif() if(NOT QT_XMLPATTERNS_EXECUTABLE) message("You have enabled Qt Help support, but QT_XMLPATTERNS_EXECUTABLE is empty") set(_force_blueberry_use_qt_help_to_off 1) endif() if(_force_blueberry_use_qt_help_to_off) set(BLUEBERRY_USE_QT_HELP OFF CACHE BOOL "Enable support for integrating plugin documentation into Qt Help" FORCE) endif() endif() if(BLUEBERRY_QT_HELP_REQUIRED AND NOT BLUEBERRY_USE_QT_HELP) message(FATAL_ERROR "BLUEBERRY_USE_QT_HELP is required to be set to ON") endif() endif() endif() #----------------------------------------------------------------------------- # Testing #----------------------------------------------------------------------------- if(BUILD_TESTING) enable_testing() include(CTest) mark_as_advanced(TCL_TCLSH DART_ROOT) option(MITK_ENABLE_RENDERING_TESTING OFF "Enable the MITK rendering tests. Requires x-server in Linux.") #Rendering testing does not work for Linux nightlies, thus it is disabled per default #and activated for Mac and Windows. if(WIN32 OR APPLE) set(MITK_ENABLE_RENDERING_TESTING ON) endif() mark_as_advanced( MITK_ENABLE_RENDERING_TESTING ) # Setup file for setting custom ctest vars configure_file( CMake/CTestCustom.cmake.in ${MITK_BINARY_DIR}/CTestCustom.cmake @ONLY ) # Initial cache for ProjectTemplate and PluginGenerator tests configure_file( CMake/mitkTestInitialCache.txt.in ${MITK_BINARY_DIR}/mitkTestInitialCache.txt @ONLY ) # Configuration for the CMake-generated test driver set(CMAKE_TESTDRIVER_EXTRA_INCLUDES "#include ") set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN " try {") set(CMAKE_TESTDRIVER_AFTER_TESTMAIN " } catch( std::exception & excp ) { fprintf(stderr,\"%s\\n\",excp.what()); return EXIT_FAILURE; } catch( ... ) { printf(\"Exception caught in the test driver\\n\"); return EXIT_FAILURE; } ") set(MITK_TEST_OUTPUT_DIR "${MITK_BINARY_DIR}/test_output") if(NOT EXISTS ${MITK_TEST_OUTPUT_DIR}) file(MAKE_DIRECTORY ${MITK_TEST_OUTPUT_DIR}) endif() # Test the external project template if(MITK_USE_BLUEBERRY) include(mitkTestProjectTemplate) endif() # Test the package target include(mitkPackageTest) endif() configure_file(mitkTestingConfig.h.in ${MITK_BINARY_DIR}/mitkTestingConfig.h) #----------------------------------------------------------------------------- # MITK_SUPERBUILD_BINARY_DIR #----------------------------------------------------------------------------- # If MITK_SUPERBUILD_BINARY_DIR isn't defined, it means MITK is *NOT* build using Superbuild. # In that specific case, MITK_SUPERBUILD_BINARY_DIR should default to MITK_BINARY_DIR if(NOT DEFINED MITK_SUPERBUILD_BINARY_DIR) set(MITK_SUPERBUILD_BINARY_DIR ${MITK_BINARY_DIR}) endif() #----------------------------------------------------------------------------- # Set C/CXX and linker flags for MITK code #----------------------------------------------------------------------------- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MITK_CXX_FLAGS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MITK_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${MITK_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MITK_C_FLAGS}") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MITK_C_FLAGS_DEBUG}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${MITK_C_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MITK_EXE_LINKER_FLAGS}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${MITK_SHARED_LINKER_FLAGS}") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${MITK_MODULE_LINKER_FLAGS}") #----------------------------------------------------------------------------- # Add custom targets representing CDash subprojects #----------------------------------------------------------------------------- foreach(subproject ${CTEST_PROJECT_SUBPROJECTS}) if(NOT TARGET ${subproject} AND NOT subproject MATCHES "Unlabeled") add_custom_target(${subproject}) endif() endforeach() #----------------------------------------------------------------------------- # Add subdirectories #----------------------------------------------------------------------------- add_subdirectory(Utilities) add_subdirectory(Modules) include("${CMAKE_CURRENT_SOURCE_DIR}/Modules/ModuleList.cmake") mitkFunctionWhitelistModules(MITK MITK_MODULES) foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_MODULES_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Modules) get_filename_component(MITK_MODULES_EXTENSION_DIR ${MITK_MODULES_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_MODULES_EXTENSION_DIR}/ModuleList.cmake) set(MITK_MODULES "") include(${MITK_MODULES_EXTENSION_DIR}/ModuleList.cmake) foreach(mitk_module ${MITK_MODULES}) add_subdirectory(${MITK_MODULES_EXTENSION_DIR}/${mitk_module} Modules/${mitk_module}) endforeach() endif() set(MITK_MODULE_NAME_PREFIX ${MITK_DEFAULT_MODULE_NAME_PREFIX}) endforeach() add_subdirectory(Wrapping) if(MITK_USE_BLUEBERRY) set(BLUEBERRY_XPDOC_OUTPUT_DIR ${MITK_DOXYGEN_OUTPUT_DIR}/html/extension-points/html/) # Plug-in testing (needs some work to be enabled again) if(BUILD_TESTING) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp") if(TARGET CoreApp) get_target_property(_is_macosx_bundle CoreApp MACOSX_BUNDLE) if(APPLE AND _is_macosx_bundle) set(BLUEBERRY_UI_TEST_APP "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/CoreApp.app/Contents/MacOS/CoreApp") endif() endif() set(BLUEBERRY_TEST_APP_ID "org.mitk.qt.coreapplication") endif() include("${CMAKE_CURRENT_SOURCE_DIR}/Plugins/PluginList.cmake") mitkFunctionWhitelistPlugins(MITK MITK_PLUGINS) set(mitk_plugins_fullpath "") foreach(mitk_plugin ${MITK_PLUGINS}) list(APPEND mitk_plugins_fullpath Plugins/${mitk_plugin}) endforeach() set(MITK_PLUGIN_REGEX_LIST "") foreach(MITK_EXTENSION_DIR ${MITK_EXTENSION_DIRS}) set(MITK_PLUGINS_EXTENSION_DIR ${MITK_EXTENSION_DIR}/Plugins) get_filename_component(MITK_PLUGINS_EXTENSION_DIR ${MITK_PLUGINS_EXTENSION_DIR} ABSOLUTE) if(EXISTS ${MITK_PLUGINS_EXTENSION_DIR}/PluginList.cmake) set(MITK_PLUGINS "") include(${MITK_PLUGINS_EXTENSION_DIR}/PluginList.cmake) foreach(mitk_plugin ${MITK_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PLUGINS_EXTENSION_DIR}/${mitk_plugin}) endforeach() endif() endforeach() if(EXISTS ${MITK_PRIVATE_MODULES}/PluginList.cmake) include(${MITK_PRIVATE_MODULES}/PluginList.cmake) foreach(mitk_plugin ${MITK_PRIVATE_PLUGINS}) list(APPEND mitk_plugins_fullpath ${MITK_PRIVATE_MODULES}/${mitk_plugin}) endforeach() endif() if(MITK_BUILD_EXAMPLES) include("${CMAKE_CURRENT_SOURCE_DIR}/Examples/Plugins/PluginList.cmake") set(mitk_example_plugins_fullpath ) foreach(mitk_example_plugin ${MITK_EXAMPLE_PLUGINS}) list(APPEND mitk_example_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) list(APPEND mitk_plugins_fullpath Examples/Plugins/${mitk_example_plugin}) endforeach() endif() # Specify which plug-ins belong to this project macro(GetMyTargetLibraries all_target_libraries varname) set(re_ctkplugin_mitk "^org_mitk_[a-zA-Z0-9_]+$") set(re_ctkplugin_bb "^org_blueberry_[a-zA-Z0-9_]+$") set(_tmp_list) list(APPEND _tmp_list ${all_target_libraries}) ctkMacroListFilter(_tmp_list re_ctkplugin_mitk re_ctkplugin_bb MITK_PLUGIN_REGEX_LIST OUTPUT_VARIABLE ${varname}) endmacro() # Get infos about application directories and build options include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/AppList.cmake") set(mitk_apps_fullpath ) foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 directory_name) list(GET target_info_list 1 option_name) if(${option_name}) list(APPEND mitk_apps_fullpath "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${directory_name}^^${option_name}") endif() endforeach() if (mitk_plugins_fullpath) ctkMacroSetupPlugins(${mitk_plugins_fullpath} BUILD_OPTION_PREFIX MITK_BUILD_ APPS ${mitk_apps_fullpath} BUILD_ALL ${MITK_BUILD_ALL_PLUGINS} COMPACT_OPTIONS) endif() set(MITK_PLUGIN_USE_FILE "${MITK_BINARY_DIR}/MitkPluginUseFile.cmake") if(${PROJECT_NAME}_PLUGIN_LIBRARIES) ctkFunctionGeneratePluginUseFile(${MITK_PLUGIN_USE_FILE}) else() file(REMOVE ${MITK_PLUGIN_USE_FILE}) set(MITK_PLUGIN_USE_FILE ) endif() endif() #----------------------------------------------------------------------------- # Documentation #----------------------------------------------------------------------------- if(DOXYGEN_FOUND) add_subdirectory(Documentation) endif() #----------------------------------------------------------------------------- # Installation #----------------------------------------------------------------------------- # set MITK cpack variables # These are the default variables, which can be overwritten ( see below ) include(mitkSetupCPack) set(use_default_config ON) # MITK_APPS is set in Applications/AppList.cmake (included somewhere above # if MITK_USE_BLUEBERRY is set to ON). if(MITK_APPS) set(activated_apps_no 0) list(LENGTH MITK_APPS app_count) # Check how many apps have been enabled # If more than one app has been activated, the we use the # default CPack configuration. Otherwise that apps configuration # will be used, if present. foreach(mitk_app ${MITK_APPS}) # extract option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 1 option_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) MATH(EXPR activated_apps_no "${activated_apps_no} + 1") endif() endforeach() if(app_count EQUAL 1 AND (activated_apps_no EQUAL 1 OR MITK_BUILD_ALL_APPS)) # Corner case if there is only one app in total set(use_project_cpack ON) elseif(activated_apps_no EQUAL 1 AND NOT MITK_BUILD_ALL_APPS) # Only one app is enabled (no "build all" flag set) set(use_project_cpack ON) else() # Less or more then one app is enabled set(use_project_cpack OFF) endif() foreach(mitk_app ${MITK_APPS}) # extract target_dir and option_name string(REPLACE "^^" "\\;" target_info ${mitk_app}) set(target_info_list ${target_info}) list(GET target_info_list 0 target_dir) list(GET target_info_list 1 option_name) list(GET target_info_list 2 executable_name) # check if the application is enabled if(${option_name} OR MITK_BUILD_ALL_APPS) # check whether application specific configuration files will be used if(use_project_cpack) # use files if they exist if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/Applications/${target_dir}/CPackOptions.cmake") endif() if(EXISTS "${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in") set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_BINARY_DIR}/Applications/${target_dir}/CPackConfig.cmake") configure_file(${PROJECT_SOURCE_DIR}/Applications/${target_dir}/CPackConfig.cmake.in ${CPACK_PROJECT_CONFIG_FILE} @ONLY) set(use_default_config OFF) endif() endif() # add link to the list list(APPEND CPACK_CREATE_DESKTOP_LINKS "${executable_name}") endif() endforeach() endif() # if no application specific configuration file was used, use default if(use_default_config) configure_file(${MITK_SOURCE_DIR}/MITKCPackOptions.cmake.in ${MITK_BINARY_DIR}/MITKCPackOptions.cmake @ONLY) set(CPACK_PROJECT_CONFIG_FILE "${MITK_BINARY_DIR}/MITKCPackOptions.cmake") endif() # include CPack model once all variables are set include(CPack) # Additional installation rules include(mitkInstallRules) #----------------------------------------------------------------------------- # Last configuration steps #----------------------------------------------------------------------------- # ---------------- Export targets ----------------- set(MITK_EXPORTS_FILE "${MITK_BINARY_DIR}/MitkExports.cmake") file(REMOVE ${MITK_EXPORTS_FILE}) set(targets_to_export) get_property(module_targets GLOBAL PROPERTY MITK_MODULE_TARGETS) if(module_targets) list(APPEND targets_to_export ${module_targets}) endif() if(MITK_USE_BLUEBERRY) if(MITK_PLUGIN_LIBRARIES) list(APPEND targets_to_export ${MITK_PLUGIN_LIBRARIES}) endif() endif() export(TARGETS ${targets_to_export} APPEND FILE ${MITK_EXPORTS_FILE}) set(MITK_EXPORTED_TARGET_PROPERTIES ) foreach(target_to_export ${targets_to_export}) get_target_property(autoload_targets ${target_to_export} MITK_AUTOLOAD_TARGETS) if(autoload_targets) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_TARGETS \"${autoload_targets}\")") endif() get_target_property(autoload_dir ${target_to_export} MITK_AUTOLOAD_DIRECTORY) if(autoload_dir) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_AUTOLOAD_DIRECTORY \"${autoload_dir}\")") endif() get_target_property(deprecated_module ${target_to_export} MITK_MODULE_DEPRECATED_SINCE) if(deprecated_module) set(MITK_EXPORTED_TARGET_PROPERTIES "${MITK_EXPORTED_TARGET_PROPERTIES} set_target_properties(${target_to_export} PROPERTIES MITK_MODULE_DEPRECATED_SINCE \"${deprecated_module}\")") endif() endforeach() # ---------------- External projects ----------------- get_property(MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS_CONFIG GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) set(MITK_CONFIG_EXTERNAL_PROJECTS ) #string(REPLACE "^^" ";" _mitk_external_projects ${MITK_EXTERNAL_PROJECTS}) foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} set(MITK_USE_${ep} ${MITK_USE_${ep}}) set(MITK_${ep}_DIR \"${${ep}_DIR}\") set(MITK_${ep}_COMPONENTS ${_components}) ") endforeach() foreach(ep ${MITK_EXTERNAL_PROJECTS}) get_property(_package GLOBAL PROPERTY MITK_${ep}_PACKAGE) get_property(_components GLOBAL PROPERTY MITK_${ep}_COMPONENTS) if(_components) set(_components_arg COMPONENTS \${_components}) else() set(_components_arg) endif() if(_package) set(MITK_CONFIG_EXTERNAL_PROJECTS "${MITK_CONFIG_EXTERNAL_PROJECTS} if(MITK_USE_${ep}) set(${ep}_DIR \${MITK_${ep}_DIR}) if(MITK_${ep}_COMPONENTS) mitkMacroFindDependency(${_package} COMPONENTS \${MITK_${ep}_COMPONENTS}) else() mitkMacroFindDependency(${_package}) endif() endif()") endif() endforeach() # ---------------- Tools ----------------- configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactory.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolExtensionITKFactoryLoader.cpp.in ${MITK_BINARY_DIR}/ToolExtensionITKFactoryLoader.cpp.in COPYONLY) configure_file(${MITK_SOURCE_DIR}/CMake/ToolGUIExtensionITKFactory.cpp.in ${MITK_BINARY_DIR}/ToolGUIExtensionITKFactory.cpp.in COPYONLY) # ---------------- Configure files ----------------- configure_file(mitkVersion.h.in ${MITK_BINARY_DIR}/mitkVersion.h) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) set(IPFUNC_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities/ipFunc) set(UTILITIES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Utilities) configure_file(mitkConfig.h.in ${MITK_BINARY_DIR}/mitkConfig.h) configure_file(MITKConfig.cmake.in ${MITK_BINARY_DIR}/MITKConfig.cmake @ONLY) write_basic_config_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake VERSION ${MITK_VERSION_STRING} COMPATIBILITY AnyNewerVersion) #----------------------------------------------------------------------------- # MITK Applications #----------------------------------------------------------------------------- # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Applications) if(MSVC AND TARGET MitkWorkbench) set_directory_properties(PROPERTIES VS_STARTUP_PROJECT MitkWorkbench) endif() #----------------------------------------------------------------------------- # MITK Examples #----------------------------------------------------------------------------- if(MITK_BUILD_EXAMPLES) # This must come after MITKConfig.h was generated, since applications # might do a find_package(MITK REQUIRED). add_subdirectory(Examples) endif() #----------------------------------------------------------------------------- # Print configuration summary #----------------------------------------------------------------------------- message("\n\n") feature_summary( DESCRIPTION "------- FEATURE SUMMARY FOR ${PROJECT_NAME} -------" WHAT ALL ) diff --git a/Documentation/Doxygen/3-DeveloperManual/Application/Deployment.dox b/Documentation/Doxygen/3-DeveloperManual/Application/Deployment.dox index e9d31cfa59..08686e7347 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Application/Deployment.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Application/Deployment.dox @@ -1,49 +1,49 @@ /** \page DeploymentPage Deploying MITK \section DeploymentPageIntroduction Introduction
  • easily create portable or installable versions of your MITK-based applications.
  • created packages include all MITK and 3rd party libraries necessary for running the application on other systems
  • distribute your binary application to other people without giving them your source code or putting them in the need for setting up a development environment themselves, eg for evaluation of your tool.
\note This does not install the MITK headers (like an SDK). If you want to develop applications based on MITK you still have to compile MITK yourself. \section DeploymentPagePlatform Platform specific notes \subsection DeploymentPagePlatformLinux Linux You can create a tarball (.tar.gz) of your MITK application which includes all necessary non-system libraries by following these steps:
  • Set the %CMake Variable CMAKE_BUILD_TYPE to either "Debug" or "Release". Any other type (or leaving the variable empty) will not work.
  • If you are using third-pary libraries not shipped with MITK, you might need to add the paths to the third-party libs to your LD_LIBRARY_PATH environment variable (not necessary if you use RPATH in your shared libraries).
  • Type "make package" in your build-tree. This will create a tarball in your build-tree directory.
\note Libraries in system locations (/lib/, /lib32/, /lib64/, /usr/lib/, /usr/lib32/,/usr/lib64/, and /usr/X11R6/) will not be included in the tarball. If you want to distribute Qt (for example), you have to do a custom Qt installation outside of these directories. \subsection DeploymentPagePlatformWindows Windows You can create a Zip file (.zip) or an NSIS 2 installer (needs an installation of
NSIS) for Windows platforms. Only "Release" builds are supported during packaging, the results of trying to package "Debug" builds are undefined.
  • In Visual Studio, build the "PACKAGE" project, this will create a .zip file and a .exe NSIS installer (if NSIS is installed).
On some systems, it might still be necessary to install the Microsoft Visual C++ Redistributable Package to start the installed application successfully. \note It is possible to include the Microsoft Visual C++ Redistributable Package in the application installer.\n A CMake variable "CMAKE_(Your Visual Studio Version)_REDISTRIBUTABLE" will be created. It has to be set to the appropriate executable (vcredist_x86.exe or vcredist_x64.exe), which will then be part of both the NSIS installer and the ZIP Archive.\n In the case of the NSIS installer it will be automatically run if no appropriate redistributable is present on the target system.\n Please note that it is not possible to automatically check the provided redistributable matches the Visual Studio version used to build the installer. -\subsection DeploymentPagePlatformMacOS MacOS +\subsection DeploymentPagePlatformMacOS macOS -You can create a drag'n drop disk image (.dmg) file for MacOS. The procedure is pretty much the same as for Linux. +You can create a drag'n drop disk image (.dmg) file for macOS. The procedure is pretty much the same as for Linux. -\note On MacOS, libraries in system locations as pointed out in the Linux section \b and libraries located in /System/Library will not be copied. If you want to distribute any libraries from these locations, you have to install them somewhere else prior to configuring your MITK build. +\note On macOS, libraries in system locations as pointed out in the Linux section \b and libraries located in /System/Library will not be copied. If you want to distribute any libraries from these locations, you have to install them somewhere else prior to configuring your MITK build. */ diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox index 96ad095432..d5bcff232c 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox +++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/BuildInstructions.dox @@ -1,216 +1,216 @@ /** \page BuildInstructionsPage Build Instructions \tableofcontents \section BuildInstructions_Introduction Introduction The CMake-based build system of MITK supports a "superbuild" process, meaning that it will download, configure, and build all required third-party libraries (except Qt) automatically. These instructions will show you how to use the MITK superbuild. \note This page explains explicitly how to build MITK itself. If you want to create your own project based on MITK, the process described below is completely automated. Please see \ref HowToNewProject. For more advanced users, the last sections explains how to inject custom build libraries into the superbuild process. \section BuildInstructions_Prerequisites Prerequisites You need: -# Git from http://git-scm.com (there are also numerous third-party graphical clients available). We recomment using Git, but see below for a way how to get the current source code without using it. -# CMake (version \minimumCMakeVersion or higher) - -# Qt 5.10.1 if you plan to develop Qt-based + -# Qt 5.11.1 if you plan to develop Qt-based applications - -# If you are using macOS you need an XCode installation as it - provides the neccessary compilers and SDKs + -# If you are using macOS you need an XCode installation and the + Command Line Tools as it provides the neccessary compilers and SDKs \section BuildInstructions_Qt A note about Qt As we do not provide Qt in the MITK superbuild you need to install Qt manually. The Qt Company provides online installers for all supported platforms. \section BuildInstructions_Get_Source Get a source tree Since MITK is under active development we recommend to use Git to check out the latest stable release from the homepage. If you decide to use the most current nightly release, make sure to get a stable tree: Check the MITK dashboard before checking out. If the build tree is not clean, you can specify an older revision for the checkout or get a stable tar ball from www.mitk.org. To clone MITK's current Git repository do: \code git clone https://phabricator.mitk.org/source/mitk.git MITK \endcode \section BuildInstructions_Build_With_CMake Build MITK with CMake Create a new directory for the superbuild binary tree, change to it and call CMake: In the shell (assuming your current directory is the same as the one where you issued the git clone command): \code mkdir MITK-superbuild cd MITK-superbuild ccmake ../MITK \endcode If you use Windows or prefer to use the CMake GUI, start the CMake GUI and enter the location of the source tree and binary tree, choose a suitable generator and configure the project. CMake will present you a couple of options, these are the most important ones: - - CMAKE_PREFIX_PATH The path to your Qt installation, e.g., C:/Qt/5.6/msvc2013_64 or /home/user/Qt/5.6/gcc_64 + - CMAKE_PREFIX_PATH The path to your Qt installation, e.g., C:/Qt/5.11.1/msvc2017_64 or /home/user/Qt/5.11.1/gcc_64 - MITK_USE_ACVD Build MITK code which depends on ACVD (this will download and build ACVD) - MITK_USE_BLUEBERRY Build the BlueBerry application framework - MITK_USE_Boost_LIBRARIES If you need binary Boost libraries, specify them here. - MITK_USE_OpenCV Build MITK code which depends on OpenCV (this will download and build OpenCV 2.4) - MITK_USE_Python Enables Python wrapping in MITK. This will also configure ITK, VTK, and OpenCV (if enabled) to build Python wrappers. - MITK_USE_Qt5 Build MITK code which depends on Qt 5 If you are satisfied with the configuration of your MITK superbuild, generate the project files with CMake by pressing "Generate". -Linux and Mac OS X users usually just enter "make" (optionally +Linux and macOS users usually just enter "make" (optionally supplying the number threads to be used for a parallel build): \code make -j6 \endcode Windows users using Visual Studio can open the generated MITK-superbuild.sln solution file in the MITK-superbuild directory and start the build by building the BUILD_ALL project. \section BuildInstructions_Customize Customize your MITK superbuild The MITK superbuild configures MITK as well as all external libraries. The build directories of these libraries, and of MITK itself are located inside the MITK-superbuild directory. For example, the directory layout may look like: \code MITK-superbuild |- ep "external projects" |-bin |-lib |-include |-src |- MITK-build \endcode To change the configuration of the MITK build itself, choose the MITK-build directory as the binary directory in the CMake GUI (not the MITK-superbuild directory). After generating the project files, build the MITK project by either issuing "make" -in the MITK-build directory (Linux, Mac OS X), or by opening MITK-build/MITK.sln (Windows). +in the MITK-build directory (Linux, macOS), or by opening MITK-build/MITK.sln (Windows). You may also change the configuration of any project configured via the superbuild process. Make sure to also build the changed project and also the projects which depend on it. \section BuildInstructions_Running Running Applications On Linux, just execute the application you want to run. MITK executables are located in MITK-superbuild/MITK-build/bin On Windows, the PATH environment variable must contain the directories containing the third-party libraries. This is automatically done from Visual Studio. For running the applications directly use the generated batch files in the MITK-superbuild/MITK-build/bin. \section BuildInstructions_Documentation Documentation If you have the Doxygen documentation tool installed, you get a new project (Visual Studio) or "make" target named "doc". You can build this to generate the HTML documentation of MITK in the Documentation/Doxygen directory of your MITK-build binary tree or in the MITK_DOXYGEN_OUTPUT_DIR CMake variable (if specified). \section BuildInstructions_Extending Extend MITK on your own (using the application framework BlueBerry) Please see \ref NewPluginPage \section BuildInstructions_As_Toolkit Use MITK in your own project (as a toolkit) To use MITK in your external project, add the CMake command find_package(MITK REQUIRED) to your CMakeLists.txt and make use of the CMake macros mitk_create_module() and mitk_create_executable() provided by MITK. Here is a very basic example CMakeLists.txt including MITK as a project: \code cmake_minimum_required(VERSION 3.10 FATAL_ERROR) project(MyProject) find_package(MITK 2016.11 REQUIRED) add_executable(MyApp main.cpp) target_link_libraries(MyApp MitkCore) \endcode with the main.ccp being \code #include #include int main() { MITK_INFO << "Hello world!"; return 0; } \endcode \section BuildInstructions_Advanced_Customization Superbuild customization You can inject pre-build third-party libraries into the MITK superbuild by setting certain CMake variables before the first configure step. MITK will then use these third-party libraries instead of downloading and building them by itself. Note that you must take care of configuring those libraries with all options MITK requires. The variables listed below are provided for injecting third-party libraries. Their occurrence in the CMake GUI or in ccmake may depend on specific MITK_USE_* options set to ON. You may also use the variable names below without the EXTERNAL_ prefix, for example when providing their values on a command line call to CMake. - EXTERNAL_BOOST_ROOT Set this variable to your custom Boost installation - EXTERNAL_CTK_DIR Set this variable to your CTK binary tree (the directory containing the CTKConfig.cmake file) - EXTERNAL_CableSwig_DIR Set this variable to your CableSwig binary tree for Python wrapping (the directory containing the CableSwigConfig.cmake file) - EXTERNAL_DCMTK_DIR Set this variable to your DCMTK binary tree (the directory containing the DCMTKConfig.cmake file) - EXTERNAL_GDCM_DIR Set this variable to your GDCM binary tree (the directory containing the GDCMConfig.cmake file) - EXTERNAL_ITK_DIR Set this variable to your ITK binary tree (the directory containing the ITKConfig.cmake file) - EXTERNAL_OpenCV_DIR Set this variable to your OpenCV binary tree (the directory containing the OpenCVConfig.cmake file) - EXTERNAL_VTK_DIR Set this variable to your VTK binary tree (the directory containing the VTKConfig.cmake file) To set CMake options before the first configure step is invoked, supply them on the command line, i.e. \code ccmake -DITK_DIR:PATH=/opt/ITK-release ../MITK \endcode */ diff --git a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/SupportedPlatforms.md b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/SupportedPlatforms.md index 8faf8b3f7e..c3af74ee21 100644 --- a/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/SupportedPlatforms.md +++ b/Documentation/Doxygen/3-DeveloperManual/Starting/SettingUpMITK/SupportedPlatforms.md @@ -1,49 +1,48 @@ Supported Platforms {#SupportedPlatformsPage} =================== MITK is a cross-platform framework that is available for the following platforms: - Windows -- Linux/X11 -- Mac OS X +- Linux +- macOS Supported Platforms Details --------------------------- The MITK team provides support for the most frequently used platforms and continuously runs testing procedures to ensure compatibility. Due to the large amount of possible combinations of operating systems and compiler versions, we divide platform support into two test categories: Tier 1 and Tier 2. Although MITK may be built on a broader range of platform-compiler combinations, only a subset of these are actively supported by the MITK development team. Tier 1 Platforms ---------------- All Tier 1 platforms are continuously tested by our unit test suite and other internal testing procedures. Errors or bugs discovered in these platforms are prioritized and corrected as soon as possible. | Platform | Compilers | ----------------------------------- | -------------------------------------------------- -| Ubuntu Linux 14.04 (x64) | GNU 4.9 as provided by ppa:ubuntu-toolchain-r/test -| Ubuntu Linux 16.04 (x64) | GNU 4.9 -| Microsoft Windows 7 (x64) | MSVC 2015 (latest update) +| Microsoft Windows 10 (x64) | Visual Studio 2017 (latest update) +| Linux Ubuntu 18.04 (x64) | GCC 7.3 +| Linux Ubuntu 16.04 (x64) | GCC 5.4 Tier 2 Platforms ---------------- Tier 2 platforms may or may not be tested on a regular basis. Some Tier 2 platforms are used by individual members of the MITK development team on a daily basis and some only receive occasional testing. While we strive to support these platforms, MITK users should note that errors may be present in released versions as well as in the current master branch. -| Platform | Compilers -| ---------------------------------- | -------------------------------------------------- -| Microsoft Windows 10 (x64) | MSVC 2015 (latest update) -| Microsoft Windows 10 (x64) | MSVC 2017 (latest update) -| Apple OS X 10.10 "Yosemite" | Clang 6.0 -| Apple OS X 10.9 "Mavericks" | Clang 5.0 +| Platform | Compilers +| ----------------------------------- | -------------------------------------------------- +| Microsoft Windows 7 (x64) | Visual Studio 2017 (latest update) +| Apple macOS 10.14 "Mojave" | Apple LLVM 10.0 +| Apple macOS 10.13 "High Sierra" | Apple LLVM 10.0 All platforms not listed above are not officially supported by the MITK team. However, we will happily accept contributions to improve support for other platforms. diff --git a/Modules/AppUtil/src/mitkBaseApplication.cpp b/Modules/AppUtil/src/mitkBaseApplication.cpp index 31a0604c51..d17d780edf 100644 --- a/Modules/AppUtil/src/mitkBaseApplication.cpp +++ b/Modules/AppUtil/src/mitkBaseApplication.cpp @@ -1,899 +1,899 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseApplication.h" #include "mitkLogMacros.h" #include "mitkExceptionMacro.h" #include "QmitkSafeApplication.h" #include "QmitkSingleApplication.h" #include "mitkProvisioningInfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance"; QString BaseApplication::ARG_CLEAN = "BlueBerry.clean"; QString BaseApplication::ARG_APPLICATION = "BlueBerry.application"; QString BaseApplication::ARG_PRODUCT = "BlueBerry.product"; QString BaseApplication::ARG_HOME = "BlueBerry.home"; QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir"; QString BaseApplication::ARG_PLUGIN_CACHE = "BlueBerry.plugin_cache_dir"; QString BaseApplication::ARG_PLUGIN_DIRS = "BlueBerry.plugin_dirs"; QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins"; QString BaseApplication::ARG_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary"; QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning"; QString BaseApplication::ARG_DEBUG = "BlueBerry.debug"; QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog"; QString BaseApplication::ARG_TESTPLUGIN = "BlueBerry.testplugin"; QString BaseApplication::ARG_TESTAPPLICATION = "BlueBerry.testapplication"; QString BaseApplication::ARG_SPLASH_IMAGE = "BlueBerry.splashscreen"; QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache"; QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading"; QString BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE = "BlueBerry.registryMultiLanguage"; QString BaseApplication::ARG_XARGS = "xargs"; QString BaseApplication::PROP_NEWINSTANCE = BaseApplication::ARG_NEWINSTANCE; QString BaseApplication::PROP_FORCE_PLUGIN_INSTALL = BaseApplication::ARG_FORCE_PLUGIN_INSTALL; QString BaseApplication::PROP_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE; QString BaseApplication::PROP_NO_LAZY_REGISTRY_CACHE_LOADING = BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING; QString BaseApplication::PROP_REGISTRY_MULTI_LANGUAGE = BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE; QString BaseApplication::PROP_PRODUCT = "blueberry.product"; QString BaseApplication::PROP_APPLICATION = "blueberry.application"; QString BaseApplication::PROP_TESTPLUGIN = "BlueBerry.testplugin"; QString BaseApplication::PROP_TESTAPPLICATION = "BlueBerry.testapplication"; static void outputQtMessage(QtMsgType type, const QMessageLogContext &, const QString &msg) { auto message = msg.toStdString(); switch (type) { case QtDebugMsg: MITK_DEBUG << message; break; case QtInfoMsg: MITK_INFO << message; break; case QtWarningMsg: MITK_WARN << message; break; case QtCriticalMsg: MITK_ERROR << message; break; case QtFatalMsg: MITK_ERROR << message; abort(); default: MITK_INFO << message; break; } } class SplashCloserCallback : public QRunnable { public: SplashCloserCallback(QSplashScreen* splashscreen) { this->m_Splashscreen = splashscreen; } void run() override { this->m_Splashscreen->close(); } private: QSplashScreen* m_Splashscreen; }; struct BaseApplication::Impl { ctkProperties m_FWProps; QScopedPointer m_QApp; int m_Argc; char **m_Argv; QString m_AppName; QString m_OrgaName; QString m_OrgaDomain; bool m_SingleMode; bool m_SafeMode; QSplashScreen* m_Splashscreen; SplashCloserCallback* m_SplashscreenClosingCallback; QStringList m_PreloadLibs; QString m_ProvFile; Impl(int argc, char **argv) : m_Argc(argc), m_Argv(argv), m_SingleMode(false), m_SafeMode(true), m_Splashscreen(nullptr), m_SplashscreenClosingCallback(nullptr) { #ifdef Q_OS_MAC /* * This is a workaround for bug 19080: - * On Mac OS X the prosess serial number is passed as an commandline argument (-psn_) + * On macOS the prosess serial number is passed as an commandline argument (-psn_) * if the application is started via the.app bundle. * This option is unknown, which causes a Poco exception. * Since this is done by the system we have to manually remove the argument here. */ int newArgc = m_Argc - 1; char **newArgs = new char *[newArgc]; bool argFound(false); for (int i = 0; i < m_Argc; ++i) { if (QString::fromLatin1(m_Argv[i]).contains("-psn")) { argFound = true; } else { newArgs[i] = m_Argv[i]; } } if (argFound) { m_Argc = newArgc; m_Argv = newArgs; } #endif } QVariant getProperty(const QString &property) const { auto iter = m_FWProps.find(property); return iter == m_FWProps.end() ? QVariant() : iter.value(); } void handleBooleanOption(const std::string &name, const std::string & /*value*/) { QString fwKey = QString::fromStdString(name); // translate some keys to proper framework properties if (fwKey == ARG_CONSOLELOG) { fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG; } // For all other options we use the command line option name as the // framework property key. m_FWProps[fwKey] = true; } void handlePreloadLibraryOption(const std::string & /*name*/, const std::string &value) { m_PreloadLibs.push_back(QString::fromStdString(value)); } void handleClean(const std::string & /*name*/, const std::string & /*value*/) { m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT; } void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration &configuration) { // add all configuration key / value pairs as framework properties Poco::Util::LayeredConfiguration::Keys keys; Poco::Util::LayeredConfiguration::Keys keyStack; configuration.keys(keyStack); std::vector keyChain; while (!keyStack.empty()) { std::string currSubKey = keyStack.back(); if (!keyChain.empty() && keyChain.back() == currSubKey) { keyChain.pop_back(); keyStack.pop_back(); continue; } Poco::Util::LayeredConfiguration::Keys subKeys; configuration.keys(currSubKey, subKeys); if (subKeys.empty()) { keyStack.pop_back(); std::string finalKey; for (auto k = keyChain.begin(); k != keyChain.end(); ++k) { finalKey += *k + "."; } finalKey += currSubKey; keys.push_back(finalKey); } else { keyChain.push_back(currSubKey); for (auto s : subKeys) { keyStack.push_back(s); } } } for (auto key : keys) { QString qKey = QString::fromStdString(key); if (configuration.hasProperty(key)) { // ini and command line options overwrite already inserted keys m_FWProps[qKey] = QString::fromStdString(configuration.getString(key)); } } } void parseProvisioningFile(const QString &filePath) { // Skip parsing if the file path is empty if (filePath.isEmpty()) return; bool consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool(); // read initial plugins from a provisioning file QStringList pluginsToStart; QFileInfo provFile(filePath); if (provFile.exists()) { MITK_INFO(consoleLog) << "Using provisioning file: " << qPrintable(provFile.absoluteFilePath()); ProvisioningInfo provInfo(provFile.absoluteFilePath()); // it can still happen, that the encoding is not compatible with the fromUtf8 function ( i.e. when manipulating // the LANG variable // in such case, the QStringList in provInfo is empty which we can easily check for if (provInfo.getPluginDirs().empty()) { MITK_ERROR << "Cannot search for provisioning file, the retrieved directory list is empty.\n" << "This can occur if there are some special (non-ascii) characters in the install path."; } else { foreach (QString pluginPath, provInfo.getPluginDirs()) { ctkPluginFrameworkLauncher::addSearchPath(pluginPath); } // bool forcePluginOverwrite = this->getProperty(ARG_FORCE_PLUGIN_INSTALL).toBool(); QList pluginUrlsToStart = provInfo.getPluginsToStart(); for (auto url : pluginUrlsToStart) { pluginsToStart.push_back(url.toString()); } // foreach(QUrl pluginUrl, provInfo.getPluginsToInstall()) //{ // TODO for "uninstall", we need a proper configuration agent, e.g. a dedicated // plug-in for provisioning of the platform /* if (forcePluginOverwrite) { uninstallPugin(pluginUrl, context); } */ // try //{ // MITK_INFO(consoleLog) << "Installing CTK plug-in from: " << pluginUrl.toString().toStdString(); /* QSharedPointer plugin = context->installPlugin(pluginUrl); if (pluginsToStart.contains(pluginUrl)) { m_CTKPluginsToStart << plugin->getPluginId(); } */ /* } catch (const ctkPluginException& e) { QString errorMsg; QDebug dbg(&errorMsg); dbg << e.printStackTrace(); BERRY_ERROR << qPrintable(errorMsg); } */ //} } } else { MITK_INFO(consoleLog) << "No provisioning file set."; } if (!pluginsToStart.isEmpty()) { m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS] = pluginsToStart; // Use transient start with declared activation policy (this helps when // the provisioning file changes and some plug-ins should not be installed // in the application any more). ctkPlugin::StartOptions startOptions(ctkPlugin::START_TRANSIENT | ctkPlugin::START_ACTIVATION_POLICY); m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS_START_OPTIONS] = static_cast(startOptions); } } }; BaseApplication::BaseApplication(int argc, char **argv) : Application(), d(new Impl(argc, argv)) { } BaseApplication::~BaseApplication() { if (d->m_Splashscreen != nullptr) { delete(d->m_Splashscreen); } if (d->m_SplashscreenClosingCallback != nullptr) { delete(d->m_SplashscreenClosingCallback); } } void BaseApplication::printHelp(const std::string & /*name*/, const std::string & /*value*/) { Poco::Util::HelpFormatter help(this->options()); help.setAutoIndent(); help.setCommand(this->commandName()); help.format(std::cout); exit(EXIT_OK); } void BaseApplication::setApplicationName(const QString &name) { if (qApp) { qApp->setApplicationName(name); } d->m_AppName = name; } QString BaseApplication::getApplicationName() const { if (qApp) { return qApp->applicationName(); } return d->m_AppName; } void BaseApplication::setOrganizationName(const QString &name) { if (qApp) { qApp->setOrganizationName(name); } d->m_OrgaName = name; } QString BaseApplication::getOrganizationName() const { if (qApp) return qApp->organizationName(); return d->m_OrgaName; } void BaseApplication::setOrganizationDomain(const QString &domain) { if (qApp) { qApp->setOrganizationDomain(domain); } d->m_OrgaDomain = domain; } QString BaseApplication::getOrganizationDomain() const { if (qApp) return qApp->organizationDomain(); return d->m_OrgaDomain; } void BaseApplication::setSingleMode(bool singleMode) { if (qApp) return; d->m_SingleMode = singleMode; } bool BaseApplication::getSingleMode() const { return d->m_SingleMode; } void BaseApplication::setSafeMode(bool safeMode) { if (qApp && !d->m_QApp) return; d->m_SafeMode = safeMode; if (d->m_QApp) { if (getSingleMode()) { static_cast(d->m_QApp.data())->setSafeMode(safeMode); } else { static_cast(d->m_QApp.data())->setSafeMode(safeMode); } } } bool BaseApplication::getSafeMode() const { return d->m_SafeMode; } void BaseApplication::setPreloadLibraries(const QStringList &libraryBaseNames) { d->m_PreloadLibs = libraryBaseNames; } QStringList BaseApplication::getPreloadLibraries() const { return d->m_PreloadLibs; } void BaseApplication::setProvisioningFilePath(const QString &filePath) { d->m_ProvFile = filePath; } QString BaseApplication::getProvisioningFilePath() const { QString provFilePath = d->m_ProvFile; // A null QString means look up a default provisioning file if (provFilePath.isNull() && qApp) { QFileInfo appFilePath(QCoreApplication::applicationFilePath()); QDir basePath(QCoreApplication::applicationDirPath()); QString provFileName = appFilePath.baseName() + ".provisioning"; QFileInfo provFile(basePath.absoluteFilePath(provFileName)); #ifdef Q_OS_MAC /* * On Mac, if started from the build directory the .provisioning file is located at: * * but the executable path is: * * In this case we have to cdUp threetimes. * * During packaging however the MitkWorkbench.provisioning file is placed at the same * level like the executable, hence nothing has to be done. */ if (!provFile.exists()) { basePath.cdUp(); basePath.cdUp(); basePath.cdUp(); provFile = basePath.absoluteFilePath(provFileName); } #endif if (provFile.exists()) { provFilePath = provFile.absoluteFilePath(); } #ifdef CMAKE_INTDIR else { basePath.cdUp(); provFile.setFile(basePath.absoluteFilePath(provFileName)); if (provFile.exists()) { provFilePath = provFile.absoluteFilePath(); } } #endif } return provFilePath; } void BaseApplication::initializeQt() { if (qApp) return; // If previously parameters have been set we have to store them // to hand them through to the application QString appName = this->getApplicationName(); QString orgName = this->getOrganizationName(); QString orgDomain = this->getOrganizationDomain(); // Create a QCoreApplication instance this->getQApplication(); // provide parameters to QCoreApplication this->setApplicationName(appName); this->setOrganizationName(orgName); this->setOrganizationDomain(orgDomain); qInstallMessageHandler(outputQtMessage); } void BaseApplication::initialize(Poco::Util::Application &self) { // 1. Call the super-class method Poco::Util::Application::initialize(self); // 2. Initialize the Qt framework (by creating a QCoreApplication) this->initializeQt(); // 3. Seed the random number generator, once at startup. QTime time = QTime::currentTime(); qsrand((uint)time.msec()); // 4. Load the "default" configuration, which involves parsing // an optional .ini file and parsing any // command line arguments this->loadConfiguration(); // 5. Add configuration data from the command line and the // optional .ini file as CTK plugin // framework properties. d->initializeCTKPluginFrameworkProperties(this->config()); // 6. Initialize splash screen if an image path is provided // in the .ini file this->initializeSplashScreen(qApp); // 7. Set the custom CTK Plugin Framework storage directory QString storageDir = this->getCTKFrameworkStorageDir(); if (!storageDir.isEmpty()) { d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir; } // 8. Set the library search paths and the pre-load library property this->initializeLibraryPaths(); QStringList preloadLibs = this->getPreloadLibraries(); if (!preloadLibs.isEmpty()) { d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs; } // 9. Initialize the CppMicroServices library. // The initializeCppMicroServices() method reuses the // FRAMEWORK_STORAGE property, so we call it after the // getCTKFrameworkStorageDir method. this->initializeCppMicroServices(); // 10. Parse the (optional) provisioning file and set the // correct framework properties. d->parseProvisioningFile(this->getProvisioningFilePath()); // Finally, set the CTK Plugin Framework properties ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps); } void BaseApplication::uninitialize() { QSharedPointer pfw = this->getFramework(); if (pfw) { pfw->stop(); // wait 10 seconds for the CTK plugin framework to stop pfw->waitForStop(10000); } Poco::Util::Application::uninitialize(); } int BaseApplication::getArgc() const { return d->m_Argc; } char **BaseApplication::getArgv() const { return d->m_Argv; } QString BaseApplication::getCTKFrameworkStorageDir() const { QString storageDir; if (this->getSingleMode()) { // This function checks if an instance is already running // and either sends a message to it (containing the command // line arguments) or checks if a new instance was forced by // providing the BlueBerry.newInstance command line argument. // In the latter case, a path to a temporary directory for // the new application's storage directory is returned. storageDir = handleNewAppInstance( static_cast(d->m_QApp.data()), d->m_Argc, d->m_Argv, ARG_NEWINSTANCE); } if (storageDir.isEmpty()) { // This is a new instance and no other instance is already running. We specify // the storage directory here (this is the same code as in berryInternalPlatform.cpp // so that we can re-use the location for the persistent data location of the // the CppMicroServices library. // Append a hash value of the absolute path of the executable to the data location. // This allows to start the same application from different build or install trees. storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/" + this->getOrganizationName() + "/" + this->getApplicationName() + '_'; storageDir += QString::number(qHash(QCoreApplication::applicationDirPath())) + "/"; } return storageDir; } void BaseApplication::initializeCppMicroServices() { QString storageDir = this->getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString(); if (!storageDir.isEmpty()) { us::ModuleSettings::SetStoragePath((storageDir + QString("us") + QDir::separator()).toStdString()); } } QCoreApplication *BaseApplication::getQApplication() const { QCoreApplication *qCoreApp = qApp; if (nullptr == qCoreApp) { vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(0); auto defaultFormat = QVTKOpenGLWidget::defaultFormat(); defaultFormat.setSamples(0); QSurfaceFormat::setDefaultFormat(defaultFormat); #ifdef Q_OS_OSX QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); #endif QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); if (this->getSingleMode()) { qCoreApp = new QmitkSingleApplication(d->m_Argc, d->m_Argv, getSafeMode()); } else { auto safeApp = new QmitkSafeApplication(d->m_Argc, d->m_Argv); safeApp->setSafeMode(d->m_SafeMode); qCoreApp = safeApp; } d->m_QApp.reset(qCoreApp); } return qCoreApp; } void BaseApplication::initializeLibraryPaths() { QStringList suffixes; suffixes << "plugins"; #ifdef Q_OS_WINDOWS suffixes << "bin/plugins"; #ifdef CMAKE_INTDIR suffixes << "bin/" CMAKE_INTDIR "/plugins"; #endif #else suffixes << "lib/plugins"; #ifdef CMAKE_INTDIR suffixes << "lib/" CMAKE_INTDIR "/plugins"; #endif #endif #ifdef Q_OS_MAC suffixes << "../../plugins"; #endif // we add a couple of standard library search paths for plug-ins QDir appDir(QCoreApplication::applicationDirPath()); // walk one directory up and add bin and lib sub-dirs; this // might be redundant appDir.cdUp(); foreach (QString suffix, suffixes) { ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix)); } } int BaseApplication::main(const std::vector &args) { // Start the plugin framework and all installed plug-ins according with // their auto-start setting. QStringList arguments; for (auto const &arg : args) { arguments.push_back(QString::fromStdString(arg)); } if (d->m_Splashscreen != nullptr) { // a splash screen is displayed, // creating the closing callback d->m_SplashscreenClosingCallback = new SplashCloserCallback(d->m_Splashscreen); } return ctkPluginFrameworkLauncher::run(d->m_SplashscreenClosingCallback, QVariant::fromValue(arguments)).toInt(); } void BaseApplication::defineOptions(Poco::Util::OptionSet &options) { Poco::Util::Option helpOption("help", "h", "print this help text"); helpOption.callback(Poco::Util::OptionCallback(this, &BaseApplication::printHelp)); options.addOption(helpOption); Poco::Util::Option newInstanceOption( ARG_NEWINSTANCE.toStdString(), "", "forces a new instance of this application"); newInstanceOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(newInstanceOption); Poco::Util::Option cleanOption(ARG_CLEAN.toStdString(), "", "cleans the plugin cache"); cleanOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleClean)); options.addOption(cleanOption); Poco::Util::Option productOption(ARG_PRODUCT.toStdString(), "", "the id of the product to be launched"); productOption.argument("").binding(PROP_PRODUCT.toStdString()); options.addOption(productOption); Poco::Util::Option appOption( ARG_APPLICATION.toStdString(), "", "the id of the application extension to be executed"); appOption.argument("").binding(PROP_APPLICATION.toStdString()); options.addOption(appOption); Poco::Util::Option provOption(ARG_PROVISIONING.toStdString(), "", "the location of a provisioning file"); provOption.argument("").binding(ARG_PROVISIONING.toStdString()); options.addOption(provOption); Poco::Util::Option storageDirOption( ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data"); storageDirOption.argument("").binding(ctkPluginConstants::FRAMEWORK_STORAGE.toStdString()); options.addOption(storageDirOption); Poco::Util::Option consoleLogOption(ARG_CONSOLELOG.toStdString(), "", "log messages to the console"); consoleLogOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(consoleLogOption); Poco::Util::Option debugOption(ARG_DEBUG.toStdString(), "", "enable debug mode"); debugOption.argument("", false).binding(ctkPluginFrameworkLauncher::PROP_DEBUG.toStdString()); options.addOption(debugOption); Poco::Util::Option forcePluginOption( ARG_FORCE_PLUGIN_INSTALL.toStdString(), "", "force installing plug-ins with same symbolic name"); forcePluginOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(forcePluginOption); Poco::Util::Option preloadLibsOption(ARG_PRELOAD_LIBRARY.toStdString(), "", "preload a library"); preloadLibsOption.argument("") .repeatable(true) .callback(Poco::Util::OptionCallback(d.data(), &Impl::handlePreloadLibraryOption)); options.addOption(preloadLibsOption); Poco::Util::Option testPluginOption(ARG_TESTPLUGIN.toStdString(), "", "the plug-in to be tested"); testPluginOption.argument("").binding(PROP_TESTPLUGIN.toStdString()); options.addOption(testPluginOption); Poco::Util::Option testAppOption(ARG_TESTAPPLICATION.toStdString(), "", "the application to be tested"); testAppOption.argument("").binding(PROP_TESTAPPLICATION.toStdString()); options.addOption(testAppOption); Poco::Util::Option noRegistryCacheOption( ARG_NO_REGISTRY_CACHE.toStdString(), "", "do not use a cache for the registry"); noRegistryCacheOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(noRegistryCacheOption); Poco::Util::Option noLazyRegistryCacheLoadingOption( ARG_NO_LAZY_REGISTRY_CACHE_LOADING.toStdString(), "", "do not use lazy cache loading for the registry"); noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(noLazyRegistryCacheLoadingOption); Poco::Util::Option registryMultiLanguageOption( ARG_REGISTRY_MULTI_LANGUAGE.toStdString(), "", "enable multi-language support for the registry"); registryMultiLanguageOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(registryMultiLanguageOption); Poco::Util::Option splashScreenOption(ARG_SPLASH_IMAGE.toStdString(), "", "optional picture to use as a splash screen"); splashScreenOption.argument("").binding(ARG_SPLASH_IMAGE.toStdString()); options.addOption(splashScreenOption); Poco::Util::Option xargsOption(ARG_XARGS.toStdString(), "", "Extended argument list"); xargsOption.argument("").binding(ARG_XARGS.toStdString()); options.addOption(xargsOption); Poco::Util::Application::defineOptions(options); } QSharedPointer BaseApplication::getFramework() const { return ctkPluginFrameworkLauncher::getPluginFramework(); } ctkPluginContext *BaseApplication::getFrameworkContext() const { QSharedPointer framework = getFramework(); if (framework) return framework->getPluginContext(); return nullptr; } void BaseApplication::initializeSplashScreen(QCoreApplication * application) const { QVariant pixmapFileNameProp = d->getProperty(ARG_SPLASH_IMAGE); if (!pixmapFileNameProp.isNull()) { QString pixmapFileName = pixmapFileNameProp.toString(); QFileInfo checkFile(pixmapFileName); if (checkFile.exists() && checkFile.isFile()) { QPixmap pixmap(checkFile.absoluteFilePath()); d->m_Splashscreen = new QSplashScreen(pixmap, Qt::WindowStaysOnTopHint); d->m_Splashscreen->show(); application->processEvents(); } } } QHash BaseApplication::getFrameworkProperties() const { return d->m_FWProps; } int BaseApplication::run() { this->init(d->m_Argc, d->m_Argv); return Application::run(); } void BaseApplication::setProperty(const QString &property, const QVariant &value) { d->m_FWProps[property] = value; } QVariant BaseApplication::getProperty(const QString &property) const { return d->getProperty(property); } void BaseApplication::installTranslator(QTranslator* translator) { this->getQApplication()->installTranslator(translator); } bool BaseApplication::isRunning() { auto app = dynamic_cast(this->getQApplication()); if (nullptr != app) app->isRunning(); mitkThrow() << "Method not implemented."; } void BaseApplication::sendMessage(const QByteArray msg) { auto app = dynamic_cast(this->getQApplication()); if (nullptr != app) app->sendMessage(msg); mitkThrow() << "Method not implemented."; } } diff --git a/Modules/Core/include/mitkDataNode.h b/Modules/Core/include/mitkDataNode.h index 6cd38a74d1..170b1c9747 100644 --- a/Modules/Core/include/mitkDataNode.h +++ b/Modules/Core/include/mitkDataNode.h @@ -1,612 +1,618 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef DATATREENODE_H_HEADER_INCLUDED_C1E14338 #define DATATREENODE_H_HEADER_INCLUDED_C1E14338 #include "mitkBaseData.h" //#include "mitkMapper.h" #include "mitkDataInteractor.h" #include "mitkIdentifiable.h" #include "mitkIPropertyOwner.h" #ifdef MBI_NO_STD_NAMESPACE #define MBI_STD #include #include #else #define MBI_STD std #include #include #endif #include "mitkColorProperty.h" #include "mitkPropertyList.h" #include "mitkStringProperty.h" //#include "mitkMapper.h" #include "mitkGeometry3D.h" #include "mitkLevelWindow.h" #include #include class vtkLinearTransform; namespace mitk { class BaseRenderer; class Mapper; /** * \brief Class for nodes of the DataTree * * Contains the data (instance of BaseData), a list of mappers, which can * draw the data, a transform (vtkTransform) and a list of properties * (PropertyList). * \ingroup DataManagement * * \todo clean up all the GetProperty methods. There are too many different flavours... Can most probably be reduced * to * bool GetProperty(type&) * * \warning Change in semantics of SetProperty() since Aug 25th 2006. Check your usage of this method if you do * more with properties than just call SetProperty( "key", new SomeProperty("value") ). */ class MITKCORE_EXPORT DataNode : public itk::DataObject, public Identifiable, public IPropertyOwner { public: typedef mitk::Geometry3D::Pointer Geometry3DPointer; typedef std::vector> MapperVector; typedef std::map MapOfPropertyLists; typedef std::vector PropertyListKeyNames; typedef std::set GroupTagList; /** * \brief Definition of an itk::Event that is invoked when * a DataInteractor is set on this DataNode. */ itkEventMacro(InteractorChangedEvent, itk::AnyEvent) mitkClassMacroItkParent(DataNode, itk::DataObject) itkFactorylessNewMacro(Self) itkCloneMacro(Self) // IPropertyProvider BaseProperty::ConstPointer GetConstProperty(const std::string &propertyKey, const std::string &contextName = "", bool fallBackOnDefaultContext = true) const override; std::vector GetPropertyKeys(const std::string &contextName = "", bool includeDefaultContext = false) const override; std::vector GetPropertyContextNames() const override; // IPropertyOwner BaseProperty * GetNonConstProperty(const std::string &propertyKey, const std::string &contextName = "", bool fallBackOnDefaultContext = true) override; void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName = "", bool fallBackOnDefaultContext = false) override; void RemoveProperty(const std::string &propertyKey, const std::string &contextName = "", bool fallBackOnDefaultContext = false) override; mitk::Mapper *GetMapper(MapperSlotId id) const; /** * \brief Get the data object (instance of BaseData, e.g., an Image) * managed by this DataNode */ BaseData *GetData() const; /** * \brief Get the transformation applied prior to displaying the data as * a vtkTransform * \deprecated use GetData()->GetGeometry()->GetVtkTransform() instead */ vtkLinearTransform *GetVtkTransform(int t = 0) const; /** * \brief Set the data object (instance of BaseData, e.g., an Image) * managed by this DataNode * * Prior set properties are kept if previous data of the node already exists and has the same * type as the new data to be set. Otherwise, the default properties are used. * In case that previous data already exists, the property list of the data node is cleared * before setting new default properties. * * \warning the actor-mode of the vtkInteractor does not work any more, if the transform of the * data-tree-node is connected to the transform of the basedata via vtkTransform->SetInput. */ virtual void SetData(mitk::BaseData *baseData); /** * \brief Set the Interactor. */ virtual void SetDataInteractor(const DataInteractor::Pointer interactor); virtual DataInteractor::Pointer GetDataInteractor() const; mitk::DataNode &operator=(const DataNode &right); mitk::DataNode &operator=(BaseData *right); virtual void SetMapper(MapperSlotId id, mitk::Mapper *mapper); void UpdateOutputInformation() override; void SetRequestedRegionToLargestPossibleRegion() override; bool RequestedRegionIsOutsideOfTheBufferedRegion() override; bool VerifyRequestedRegion() override; void SetRequestedRegion(const itk::DataObject *data) override; void CopyInformation(const itk::DataObject *data) override; /** * \brief The "names" used for (renderer-specific) PropertyLists in GetPropertyList(string). * * All possible values for the "renderer" parameters of * the diverse GetProperty/List() methods. */ PropertyListKeyNames GetPropertyListNames() const; /** * \brief Set the property (instance of BaseProperty) with key \a propertyKey in the PropertyList * of the \a renderer (if nullptr, use BaseRenderer-independent PropertyList). This is set-by-value. * * \warning Change in semantics since Aug 25th 2006. Check your usage of this method if you do * more with properties than just call SetProperty( "key", new SomeProperty("value") ). * * \sa GetProperty * \sa m_PropertyList * \sa m_MapOfPropertyLists */ void SetProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Replace the property (instance of BaseProperty) with key \a propertyKey in the PropertyList * of the \a renderer (if nullptr, use BaseRenderer-independent PropertyList). This is set-by-reference. * * If \a renderer is \a nullptr the property is set in the BaseRenderer-independent * PropertyList of this DataNode. * \sa GetProperty * \sa m_PropertyList * \sa m_MapOfPropertyLists */ void ReplaceProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Add the property (instance of BaseProperty) if it does * not exist (or always if\a overwrite is\a true) * with key \a propertyKey in the PropertyList * of the \a renderer (if nullptr, use BaseRenderer-independent * PropertyList). This is set-by-value. * * For\a overwrite ==\a false the property is\em not changed * if it already exists. For\a overwrite ==\a true the method * is identical to SetProperty. * * \sa SetProperty * \sa GetProperty * \sa m_PropertyList * \sa m_MapOfPropertyLists */ void AddProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer = nullptr, bool overwrite = false); /** * \brief Get the PropertyList of the \a renderer. If \a renderer is \a * nullptr, the BaseRenderer-independent PropertyList of this DataNode * is returned. * \sa GetProperty * \sa m_PropertyList * \sa m_MapOfPropertyLists */ mitk::PropertyList *GetPropertyList(const mitk::BaseRenderer *renderer = nullptr) const; mitk::PropertyList *GetPropertyList(const std::string &rendererName) const; /** * \brief Add values from another PropertyList. * * Overwrites values in m_PropertyList only when possible (i.e. when types are compatible). * If you want to allow for object type changes (replacing a "visible":BoolProperty with "visible":IntProperty, * set the \param replace. * * \param replace true: if \param pList contains a property "visible" of type ColorProperty and our m_PropertyList * also has a "visible" property of a different type (e.g. BoolProperty), change the type, i.e. replace the objects * behind the pointer. * * \sa SetProperty * \sa ReplaceProperty * \sa m_PropertyList */ void ConcatenatePropertyList(PropertyList *pList, bool replace = false); /** * \brief Get the property (instance of BaseProperty) with key \a propertyKey from the PropertyList * of the \a renderer, if available there, otherwise use the BaseRenderer-independent PropertyList. * * If \a renderer is \a nullptr or the \a propertyKey cannot be found * in the PropertyList specific to \a renderer or is disabled there, the BaseRenderer-independent * PropertyList of this DataNode is queried. * * If \a fallBackOnDataProperties is true, the data property list is queried as a last resort. * * \sa GetPropertyList * \sa m_PropertyList * \sa m_MapOfPropertyLists */ mitk::BaseProperty *GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer = nullptr, bool fallBackOnDataProperties = true) const; /** * \brief Get the property of type T with key \a propertyKey from the PropertyList * of the \a renderer, if available there, otherwise use the BaseRenderer-independent PropertyList. * * If \a renderer is \a nullptr or the \a propertyKey cannot be found * in the PropertyList specific to \a renderer or is disabled there, the BaseRenderer-independent * PropertyList of this DataNode is queried. * \sa GetPropertyList * \sa m_PropertyList * \sa m_MapOfPropertyLists */ template bool GetProperty(itk::SmartPointer &property, const char *propertyKey, const mitk::BaseRenderer *renderer = nullptr) const { property = dynamic_cast(GetProperty(propertyKey, renderer)); return property.IsNotNull(); } /** * \brief Get the property of type T with key \a propertyKey from the PropertyList * of the \a renderer, if available there, otherwise use the BaseRenderer-independent PropertyList. * * If \a renderer is \a nullptr or the \a propertyKey cannot be found * in the PropertyList specific to \a renderer or is disabled there, the BaseRenderer-independent * PropertyList of this DataNode is queried. * \sa GetPropertyList * \sa m_PropertyList * \sa m_MapOfPropertyLists */ template bool GetProperty(T *&property, const char *propertyKey, const mitk::BaseRenderer *renderer = nullptr) const { property = dynamic_cast(GetProperty(propertyKey, renderer)); return property != nullptr; } /** * \brief Convenience access method for GenericProperty properties * (T being the type of the second parameter) * \return \a true property was found */ template bool GetPropertyValue(const char *propertyKey, T &value, const mitk::BaseRenderer *renderer = nullptr) const { GenericProperty *gp = dynamic_cast *>(GetProperty(propertyKey, renderer)); if (gp != nullptr) { value = gp->GetValue(); return true; } return false; } /// \brief Get a set of all group tags from this node's property list GroupTagList GetGroupTags() const; /** * \brief Convenience access method for bool properties (instances of * BoolProperty) * \return \a true property was found */ bool GetBoolProperty(const char *propertyKey, bool &boolValue, const mitk::BaseRenderer *renderer = nullptr) const; /** * \brief Convenience access method for int properties (instances of * IntProperty) * \return \a true property was found */ bool GetIntProperty(const char *propertyKey, int &intValue, const mitk::BaseRenderer *renderer = nullptr) const; /** * \brief Convenience access method for float properties (instances of * FloatProperty) * \return \a true property was found */ bool GetFloatProperty(const char *propertyKey, float &floatValue, const mitk::BaseRenderer *renderer = nullptr) const; /** * \brief Convenience access method for double properties (instances of * DoubleProperty) * * If there is no DoubleProperty for the given\c propertyKey argument, the method * looks for a corresponding FloatProperty instance. * * \return \a true property was found */ bool GetDoubleProperty(const char *propertyKey, double &doubleValue, const mitk::BaseRenderer *renderer = nullptr) const; /** * \brief Convenience access method for string properties (instances of * StringProperty) * \return \a true property was found */ bool GetStringProperty(const char *propertyKey, std::string &string, const mitk::BaseRenderer *renderer = nullptr) const; /** * \brief Convenience access method for color properties (instances of * ColorProperty) * \return \a true property was found */ bool GetColor(float rgb[3], const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "color") const; /** * \brief Convenience access method for level-window properties (instances of * LevelWindowProperty) * \return \a true property was found */ bool GetLevelWindow(mitk::LevelWindow &levelWindow, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "levelwindow") const; /** * \brief set the node as selected */ void SetSelected(bool selected, const mitk::BaseRenderer *renderer = nullptr); /** * \brief set the node as selected * \return \a true node is selected */ bool IsSelected(const mitk::BaseRenderer *renderer = nullptr); /** * \brief Convenience access method for accessing the name of an object (instance of * StringProperty with property-key "name") * \return \a true property was found */ bool GetName(std::string &nodeName, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "name") const { return GetStringProperty(propertyKey, nodeName, renderer); } /** * \brief Extra convenience access method for accessing the name of an object (instance of * StringProperty with property-key "name"). * * This method does not take the renderer specific * propertylists into account, because the name of an object should never be renderer specific. * \returns a std::string with the name of the object (content of "name" Property). * If there is no "name" Property, an empty string will be returned. */ virtual std::string GetName() const { mitk::StringProperty *sp = dynamic_cast(this->GetProperty("name")); if (sp == nullptr) return ""; return sp->GetValue(); } + /** Value constant that is used indicate that node names are not set so far.*/ + static std::string NO_NAME_VALUE() + { + return "No Name!"; + } + /** * \brief Extra convenience access method to set the name of an object. * * The name will be stored in the non-renderer-specific PropertyList in a StringProperty named "name". */ virtual void SetName(const char *name) { if (name == nullptr) return; this->SetProperty("name", StringProperty::New(name)); } /** * \brief Extra convenience access method to set the name of an object. * * The name will be stored in the non-renderer-specific PropertyList in a StringProperty named "name". */ virtual void SetName(const std::string name) { this->SetName(name.c_str()); } /** * \brief Convenience access method for visibility properties (instances * of BoolProperty with property-key "visible") * \return \a true property was found * \sa IsVisible */ bool GetVisibility(bool &visible, const mitk::BaseRenderer *renderer, const char *propertyKey = "visible") const { return GetBoolProperty(propertyKey, visible, renderer); } /** * \brief Convenience access method for opacity properties (instances of * FloatProperty) * \return \a true property was found */ bool GetOpacity(float &opacity, const mitk::BaseRenderer *renderer, const char *propertyKey = "opacity") const; /** * \brief Convenience access method for boolean properties (instances * of BoolProperty). Return value is the value of the property. If the property is * not found, the value of \a defaultIsOn is returned. * * Thus, the return value has a different meaning than in the * GetBoolProperty method! * \sa GetBoolProperty */ bool IsOn(const char *propertyKey, const mitk::BaseRenderer *renderer, bool defaultIsOn = true) const { if (propertyKey == nullptr) return defaultIsOn; GetBoolProperty(propertyKey, defaultIsOn, renderer); return defaultIsOn; } /** * \brief Convenience access method for visibility properties (instances * of BoolProperty). Return value is the visibility. Default is * visible==true, i.e., true is returned even if the property (\a * propertyKey) is not found. * * Thus, the return value has a different meaning than in the * GetVisibility method! * \sa GetVisibility * \sa IsOn */ bool IsVisible(const mitk::BaseRenderer *renderer, const char *propertyKey = "visible", bool defaultIsOn = true) const { return IsOn(propertyKey, renderer, defaultIsOn); } /** * \brief Convenience method for setting color properties (instances of * ColorProperty) */ void SetColor(const mitk::Color &color, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "color"); /** * \brief Convenience method for setting color properties (instances of * ColorProperty) */ void SetColor(float red, float green, float blue, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "color"); /** * \brief Convenience method for setting color properties (instances of * ColorProperty) */ void SetColor(const float rgb[3], const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "color"); /** * \brief Convenience method for setting visibility properties (instances * of BoolProperty) * \param visible If set to true, the data will be rendered. If false, the render will skip this data. * \param renderer Specify a renderer if the visibility shall be specific to a renderer * \param propertykey Can be used to specify a user defined name of the visibility propery. */ void SetVisibility(bool visible, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "visible"); /** * \brief Convenience method for setting opacity properties (instances of * FloatProperty) */ void SetOpacity(float opacity, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "opacity"); /** * \brief Convenience method for setting level-window properties * (instances of LevelWindowProperty) */ void SetLevelWindow(mitk::LevelWindow levelWindow, const mitk::BaseRenderer *renderer = nullptr, const char *propertyKey = "levelwindow"); /** * \brief Convenience method for setting int properties (instances of * IntProperty) */ void SetIntProperty(const char *propertyKey, int intValue, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Convenience method for setting boolean properties (instances of * BoolProperty) */ void SetBoolProperty(const char *propertyKey, bool boolValue, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Convenience method for setting float properties (instances of * FloatProperty) */ void SetFloatProperty(const char *propertyKey, float floatValue, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Convenience method for setting double properties (instances of * DoubleProperty) */ void SetDoubleProperty(const char *propertyKey, double doubleValue, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Convenience method for setting string properties (instances of * StringProperty) */ void SetStringProperty(const char *propertyKey, const char *string, const mitk::BaseRenderer *renderer = nullptr); /** * \brief Get the timestamp of the last change of the contents of this node or * the referenced BaseData. */ unsigned long GetMTime() const override; /** * \brief Get the timestamp of the last change of the reference to the * BaseData. */ unsigned long GetDataReferenceChangedTime() const { return m_DataReferenceChangedTime.GetMTime(); } protected: DataNode(); ~DataNode() override; /// Invoked when the property list was modified. Calls Modified() of the DataNode virtual void PropertyListModified(const itk::Object *caller, const itk::EventObject &event); /// \brief Mapper-slots mutable MapperVector m_Mappers; /** * \brief The data object (instance of BaseData, e.g., an Image) managed * by this DataNode */ BaseData::Pointer m_Data; /** * \brief BaseRenderer-independent PropertyList * * Properties herein can be overwritten specifically for each BaseRenderer * by the BaseRenderer-specific properties defined in m_MapOfPropertyLists. */ PropertyList::Pointer m_PropertyList; /// \brief Map associating each BaseRenderer with its own PropertyList mutable MapOfPropertyLists m_MapOfPropertyLists; DataInteractor::Pointer m_DataInteractor; /// \brief Timestamp of the last change of m_Data itk::TimeStamp m_DataReferenceChangedTime; unsigned long m_PropertyListModifiedObserverTag; }; #if (_MSC_VER > 1200) || !defined(_MSC_VER) MITKCORE_EXPORT MBI_STD::istream &operator>>(MBI_STD::istream &i, DataNode::Pointer &dtn); MITKCORE_EXPORT MBI_STD::ostream &operator<<(MBI_STD::ostream &o, DataNode::Pointer &dtn); #endif } // namespace mitk #if ((defined(_MSC_VER)) && (_MSC_VER <= 1200)) MITKCORE_EXPORT MBI_STD::istream &operator>>(MBI_STD::istream &i, mitk::DataNode::Pointer &dtn); MITKCORE_EXPORT MBI_STD::ostream &operator<<(MBI_STD::ostream &o, mitk::DataNode::Pointer &dtn); #endif #endif /* DATATREENODE_H_HEADER_INCLUDED_C1E14338 */ diff --git a/Modules/Core/include/mitkPropertyList.h b/Modules/Core/include/mitkPropertyList.h index cad2e3e322..7e056e9358 100644 --- a/Modules/Core/include/mitkPropertyList.h +++ b/Modules/Core/include/mitkPropertyList.h @@ -1,258 +1,254 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D #define PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D #include "mitkBaseProperty.h" #include "mitkGenericProperty.h" #include "mitkUIDGenerator.h" +#include "mitkIPropertyOwner.h" #include #include #include #include namespace mitk { class XMLWriter; /** * @brief Key-value list holding instances of BaseProperty * * This list is meant to hold an arbitrary list of "properties", * which should describe the object associated with this list. * * Usually you will use PropertyList as part of a DataNode * object - in this context the properties describe the data object * held by the DataNode (e.g. whether the object is rendered at * all, which color is used for rendering, what name should be * displayed for the object, etc.) * * The values in the list are not fixed, you may introduce any kind * of property that seems useful - all you have to do is inherit * from BaseProperty. * * The list is organized as a key-value pairs, i.e. * * \li "name" : pointer to a StringProperty * \li "visible" : pointer to a BoolProperty * \li "color" : pointer to a ColorProperty * \li "volume" : pointer to a FloatProperty * * Please see the documentation of SetProperty and ReplaceProperty for two * quite different semantics. Normally SetProperty is what you want - this * method will try to change the value of an existing property and will * not allow you to replace e.g. a ColorProperty with an IntProperty. * * @ingroup DataManagement */ - class MITKCORE_EXPORT PropertyList : public itk::Object + class MITKCORE_EXPORT PropertyList : public itk::Object, public IPropertyOwner { public: mitkClassMacroItkParent(PropertyList, itk::Object) - /** - * Method for creation through the object factory. - */ - itkFactorylessNewMacro(Self) itkCloneMacro(Self) + /** + * Method for creation through the object factory. + */ + itkFactorylessNewMacro(Self) itkCloneMacro(Self) - /** - * Map structure to hold the properties: the map key is a string, - * the value consists of the actual property object (BaseProperty). - */ - typedef std::map PropertyMap; + /** + * Map structure to hold the properties: the map key is a string, + * the value consists of the actual property object (BaseProperty). + */ + typedef std::map PropertyMap; typedef std::pair PropertyMapElementType; + // IPropertyProvider + BaseProperty::ConstPointer GetConstProperty(const std::string &propertyKey, const std::string &contextName = "", bool fallBackOnDefaultContext = true) const override; + std::vector GetPropertyKeys(const std::string &contextName = "", bool includeDefaultContext = false) const override; + std::vector GetPropertyContextNames() const override; + + // IPropertyOwner + BaseProperty * GetNonConstProperty(const std::string &propertyKey, const std::string &contextName = "", bool fallBackOnDefaultContext = true) override; + void SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName = "", bool fallBackOnDefaultContext = false) override; + void RemoveProperty(const std::string &propertyKey, const std::string &contextName = "", bool fallBackOnDefaultContext = false) override; + /** * @brief Get a property by its name. */ mitk::BaseProperty *GetProperty(const std::string &propertyKey) const; - /** - * @brief Set a property in the list/map by value. - * - * The actual OBJECT holding the value of the property is not replaced, but its value - * is modified to match that of @a property. To really replace the object holding the - * property - which would make sense if you want to change the type (bool, string) of the property - * - call ReplaceProperty. - */ - void SetProperty(const std::string &propertyKey, BaseProperty *property); - /** * @brief Set a property object in the list/map by reference. * * The actual OBJECT holding the value of the property is replaced by this function. * This is useful if you want to change the type of the property, like from BoolProperty to StringProperty. * Another use is to share one and the same property object among several ProperyList/DataNode objects, which * makes them appear synchronized. */ void ReplaceProperty(const std::string &propertyKey, BaseProperty *property); - /** - * @brief Remove a property object from the list/map by reference. - */ - void RemoveProperty(const std::string &propertyKey); - /** * @brief Set a property object in the list/map by reference. */ void ConcatenatePropertyList(PropertyList *pList, bool replace = false); //##Documentation //## @brief Convenience access method for GenericProperty properties //## (T being the type of the second parameter) //## @return @a true property was found template bool GetPropertyValue(const char *propertyKey, T &value) const { GenericProperty *gp = dynamic_cast *>(GetProperty(propertyKey)); if (gp != nullptr) { value = gp->GetValue(); return true; } return false; } /** * @brief Convenience method to access the value of a BoolProperty */ bool GetBoolProperty(const char *propertyKey, bool &boolValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, bool &boolValue) const; /** * @brief Convenience method to set the value of a BoolProperty */ void SetBoolProperty(const char *propertyKey, bool boolValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, bool boolValue); /** * @brief Convenience method to access the value of an IntProperty */ bool GetIntProperty(const char *propertyKey, int &intValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, int &intValue) const; /** * @brief Convenience method to set the value of an IntProperty */ void SetIntProperty(const char *propertyKey, int intValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, int intValue); /** * @brief Convenience method to access the value of a FloatProperty */ bool GetFloatProperty(const char *propertyKey, float &floatValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, float &floatValue) const; /** * @brief Convenience method to set the value of a FloatProperty */ void SetFloatProperty(const char *propertyKey, float floatValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, float floatValue); /** * @brief Convenience method to access the value of a DoubleProperty */ bool GetDoubleProperty(const char *propertyKey, double &doubleValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, double &doubleValue) const; /** * @brief Convenience method to set the value of a DoubleProperty */ void SetDoubleProperty(const char *propertyKey, double doubleValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, double doubleValue); /** * @brief Convenience method to access the value of a StringProperty */ bool GetStringProperty(const char *propertyKey, std::string &stringValue) const; /** * @brief ShortCut for the above method */ bool Get(const char *propertyKey, std::string &stringValue) const; /** * @brief Convenience method to set the value of a StringProperty */ void SetStringProperty(const char *propertyKey, const char *stringValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, const char *stringValue); /** * @brief ShortCut for the above method */ void Set(const char *propertyKey, const std::string &stringValue); /** * @brief Get the timestamp of the last change of the map or the last change of one of * the properties store in the list (whichever is later). */ unsigned long GetMTime() const override; /** * @brief Remove a property from the list/map. */ bool DeleteProperty(const std::string &propertyKey); const PropertyMap *GetMap() const { return &m_Properties; } bool IsEmpty() const { return m_Properties.empty(); } virtual void Clear(); protected: PropertyList(); PropertyList(const PropertyList &other); ~PropertyList() override; /** * @brief Map of properties. */ PropertyMap m_Properties; private: itk::LightObject::Pointer InternalClone() const override; }; } // namespace mitk #endif /* PROPERTYLIST_H_HEADER_INCLUDED_C1C77D8D */ diff --git a/Modules/Core/src/DataManagement/mitkBaseData.cpp b/Modules/Core/src/DataManagement/mitkBaseData.cpp index 1bb6171a7c..64add59feb 100644 --- a/Modules/Core/src/DataManagement/mitkBaseData.cpp +++ b/Modules/Core/src/DataManagement/mitkBaseData.cpp @@ -1,361 +1,353 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseData.h" #include #include #include #include #include mitk::BaseData::BaseData() : m_SourceOutputIndexDuplicate(0), m_Initialized(true), m_PropertyList(PropertyList::New()), m_TimeGeometry(ProportionalTimeGeometry::New()) { } mitk::BaseData::BaseData(const BaseData &other) : itk::DataObject(), OperationActor(), Identifiable(), m_SourceOutputIndexDuplicate(other.m_SourceOutputIndexDuplicate), m_Initialized(other.m_Initialized), m_PropertyList(other.m_PropertyList->Clone()), m_TimeGeometry(other.m_TimeGeometry->Clone()) { } mitk::BaseData::~BaseData() { } void mitk::BaseData::InitializeTimeGeometry(unsigned int timeSteps) { mitk::Geometry3D::Pointer geo3D = mitk::Geometry3D::New(); mitk::BaseGeometry::Pointer baseGeo = dynamic_cast(geo3D.GetPointer()); baseGeo->Initialize(); // The geometry is propagated automatically to the other items, // if EvenlyTimed is true... // Old timeGeometry->InitializeEvenlyTimed( g3d.GetPointer(), timeSteps ); TimeGeometry::Pointer timeGeometry = this->GetTimeGeometry(); timeGeometry->Initialize(); timeGeometry->Expand(timeSteps); for (TimeStepType step = 0; step < timeSteps; ++step) { timeGeometry->SetTimeStepGeometry(baseGeo.GetPointer(), step); } } void mitk::BaseData::UpdateOutputInformation() { if (this->GetSource()) { this->GetSource()->UpdateOutputInformation(); } if (m_TimeGeometry.IsNotNull()) { m_TimeGeometry->UpdateBoundingBox(); } } const mitk::TimeGeometry *mitk::BaseData::GetUpdatedTimeGeometry() { SetRequestedRegionToLargestPossibleRegion(); UpdateOutputInformation(); return GetTimeGeometry(); } void mitk::BaseData::Expand(unsigned int timeSteps) { if (m_TimeGeometry.IsNotNull()) { m_TimeGeometry->Expand(timeSteps); } else { this->InitializeTimeGeometry(timeSteps); } } const mitk::BaseGeometry *mitk::BaseData::GetUpdatedGeometry(int t) { SetRequestedRegionToLargestPossibleRegion(); UpdateOutputInformation(); return GetGeometry(t); } void mitk::BaseData::SetGeometry(BaseGeometry *geometry) { ProportionalTimeGeometry::Pointer timeGeometry = ProportionalTimeGeometry::New(); if (geometry != nullptr) { timeGeometry->Initialize(geometry, 1); } SetTimeGeometry(timeGeometry); return; } void mitk::BaseData::SetTimeGeometry(TimeGeometry *geometry) { m_TimeGeometry = geometry; this->Modified(); } void mitk::BaseData::SetClonedGeometry(const BaseGeometry *aGeometry3D) { SetGeometry(static_cast(aGeometry3D->Clone().GetPointer())); } void mitk::BaseData::SetClonedTimeGeometry(const TimeGeometry *geometry) { TimeGeometry::Pointer clonedGeometry = geometry->Clone(); SetTimeGeometry(clonedGeometry.GetPointer()); } void mitk::BaseData::SetClonedGeometry(const BaseGeometry *aGeometry3D, unsigned int time) { if (m_TimeGeometry) { m_TimeGeometry->SetTimeStepGeometry(static_cast(aGeometry3D->Clone().GetPointer()), time); } } bool mitk::BaseData::IsEmptyTimeStep(unsigned int) const { return IsInitialized() == false; } bool mitk::BaseData::IsEmpty() const { if (IsInitialized() == false) return true; const TimeGeometry *timeGeometry = const_cast(this)->GetUpdatedTimeGeometry(); if (timeGeometry == nullptr) return true; unsigned int timeSteps = timeGeometry->CountTimeSteps(); for (unsigned int t = 0; t < timeSteps; ++t) { if (IsEmptyTimeStep(t) == false) return false; } return true; } itk::SmartPointer mitk::BaseData::GetSource() const { return static_cast(Superclass::GetSource().GetPointer()); } mitk::PropertyList::Pointer mitk::BaseData::GetPropertyList() const { return m_PropertyList; } mitk::BaseProperty::Pointer mitk::BaseData::GetProperty(const char *propertyKey) const { return m_PropertyList->GetProperty(propertyKey); } void mitk::BaseData::SetProperty(const char *propertyKey, BaseProperty *propertyValue) { m_PropertyList->SetProperty(propertyKey, propertyValue); } void mitk::BaseData::SetPropertyList(PropertyList *pList) { m_PropertyList = pList; } void mitk::BaseData::SetOrigin(const mitk::Point3D &origin) { TimeGeometry *timeGeom = GetTimeGeometry(); assert(timeGeom != nullptr); TimeStepType steps = timeGeom->CountTimeSteps(); for (TimeStepType timestep = 0; timestep < steps; ++timestep) { auto geometry = GetGeometry(timestep); if (geometry != nullptr) { geometry->SetOrigin(origin); } } } unsigned long mitk::BaseData::GetMTime() const { unsigned long time = Superclass::GetMTime(); if (m_TimeGeometry.IsNotNull()) { if ((time < m_TimeGeometry->GetMTime())) { Modified(); return Superclass::GetMTime(); } } return time; } void mitk::BaseData::Graft(const itk::DataObject *) { itkExceptionMacro(<< "Graft not implemented for mitk::BaseData subclass " << this->GetNameOfClass()) } void mitk::BaseData::CopyInformation(const itk::DataObject *data) { const auto *bd = dynamic_cast(data); if (bd != nullptr) { m_PropertyList = bd->GetPropertyList()->Clone(); if (bd->GetTimeGeometry() != nullptr) { m_TimeGeometry = bd->GetTimeGeometry()->Clone(); } } else { // pointer could not be cast back down; this can be the case if your filters input // and output objects differ in type; then you have to write your own GenerateOutputInformation method itkExceptionMacro(<< "mitk::BaseData::CopyInformation() cannot cast " << typeid(data).name() << " to " << typeid(Self *).name()); } } bool mitk::BaseData::IsInitialized() const { return m_Initialized; } void mitk::BaseData::Clear() { this->ClearData(); this->InitializeEmpty(); } void mitk::BaseData::ClearData() { if (m_Initialized) { ReleaseData(); m_Initialized = false; } } void mitk::BaseData::ExecuteOperation(mitk::Operation * /*operation*/) { // empty by default. override if needed! } void mitk::BaseData::PrintSelf(std::ostream &os, itk::Indent indent) const { os << std::endl; os << indent << " TimeGeometry: "; if (GetTimeGeometry() == nullptr) os << "nullptr" << std::endl; else GetTimeGeometry()->Print(os, indent); // print out all properties PropertyList::Pointer propertyList = this->GetPropertyList(); if (propertyList.IsNotNull() && !propertyList->IsEmpty()) { // general headline os << "Properties of BaseData:" << std::endl; const PropertyList::PropertyMap *map = propertyList->GetMap(); for (auto iter = map->begin(); iter != map->end(); ++iter) { os << " " << (*iter).first << " " << (*iter).second->GetValueAsString() << std::endl; } } } mitk::BaseProperty::ConstPointer mitk::BaseData::GetConstProperty(const std::string &propertyKey, const std::string &contextName, bool fallBackOnDefaultContext) const { if (propertyKey.empty()) return nullptr; if (contextName.empty() || fallBackOnDefaultContext) return m_PropertyList->GetProperty(propertyKey); return nullptr; } mitk::BaseProperty * mitk::BaseData::GetNonConstProperty(const std::string &propertyKey, const std::string &contextName, bool fallBackOnDefaultContext) { if (propertyKey.empty()) return nullptr; if (contextName.empty() || fallBackOnDefaultContext) return m_PropertyList->GetProperty(propertyKey); return nullptr; } void mitk::BaseData::SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &contextName, bool fallBackOnDefaultContext) { if (propertyKey.empty()) mitkThrow() << "Property key is empty."; if (contextName.empty() || fallBackOnDefaultContext) { m_PropertyList->SetProperty(propertyKey, property); return; } mitkThrow() << "Unknown or unsupported non-default property context."; } void mitk::BaseData::RemoveProperty(const std::string &propertyKey, const std::string &contextName, bool fallBackOnDefaultContext) { if (propertyKey.empty()) mitkThrow() << "Property key is empty."; if (contextName.empty() || fallBackOnDefaultContext) { m_PropertyList->RemoveProperty(propertyKey); return; } mitkThrow() << "Unknown or unsupported non-default property context."; } -std::vector mitk::BaseData::GetPropertyKeys(const std::string &contextName, bool includeDefaultContext) const +std::vector mitk::BaseData::GetPropertyKeys(const std::string &/*contextName*/, bool /*includeDefaultContext*/) const { - std::vector propertyKeys; - - if (contextName.empty() || includeDefaultContext) - { - for (auto property : *m_PropertyList->GetMap()) - propertyKeys.push_back(property.first); - } - - return propertyKeys; + return m_PropertyList->GetPropertyKeys(); } std::vector mitk::BaseData::GetPropertyContextNames() const { return std::vector(); } diff --git a/Modules/Core/src/DataManagement/mitkPropertyList.cpp b/Modules/Core/src/DataManagement/mitkPropertyList.cpp index 5547be1687..68a8091261 100644 --- a/Modules/Core/src/DataManagement/mitkPropertyList.cpp +++ b/Modules/Core/src/DataManagement/mitkPropertyList.cpp @@ -1,343 +1,380 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPropertyList.h" #include "mitkNumericTypes.h" #include "mitkProperties.h" #include "mitkStringProperty.h" +mitk::BaseProperty::ConstPointer mitk::PropertyList::GetConstProperty(const std::string &propertyKey, const std::string &/*contextName*/, bool /*fallBackOnDefaultContext*/) const +{ + PropertyMap::const_iterator it; + + it = m_Properties.find(propertyKey); + if (it != m_Properties.cend()) + return it->second.GetPointer(); + else + return nullptr; +}; + +std::vector mitk::PropertyList::GetPropertyKeys(const std::string &contextName, bool includeDefaultContext) const +{ + std::vector propertyKeys; + + if (contextName.empty() || includeDefaultContext) + { + for (auto property : this->m_Properties) + propertyKeys.push_back(property.first); + } + + return propertyKeys; +}; + +std::vector mitk::PropertyList::GetPropertyContextNames() const +{ + return std::vector(); +}; + mitk::BaseProperty *mitk::PropertyList::GetProperty(const std::string &propertyKey) const { PropertyMap::const_iterator it; it = m_Properties.find(propertyKey); if (it != m_Properties.cend()) return it->second; else return nullptr; } -void mitk::PropertyList::SetProperty(const std::string &propertyKey, BaseProperty *property) +mitk::BaseProperty * mitk::PropertyList::GetNonConstProperty(const std::string &propertyKey, const std::string &/*contextName*/, bool /*fallBackOnDefaultContext*/) { + return this->GetProperty(propertyKey); +} + +void mitk::PropertyList::SetProperty(const std::string &propertyKey, BaseProperty *property, const std::string &/*contextName*/, bool /*fallBackOnDefaultContext*/) +{ + if (propertyKey.empty()) + mitkThrow() << "Property key is empty."; + if (!property) return; // make sure that BaseProperty*, which may have just been created and never been // assigned to a SmartPointer, is registered/unregistered properly. If we do not // do that, it will a) not deleted in case it is identical to the old one or // b) possibly deleted when temporarily added to a smartpointer somewhere below. BaseProperty::Pointer tmpSmartPointerToProperty = property; auto it(m_Properties.find(propertyKey)); // Is a property with key @a propertyKey contained in the list? if (it != m_Properties.cend()) { // yes // is the property contained in the list identical to the new one? if (it->second->operator==(*property)) { // yes? do nothing and return. return; } if (it->second->AssignProperty(*property)) { // The assignment was successfull this->Modified(); } else { MITK_ERROR << "In " __FILE__ ", l." << __LINE__ << ": Trying to set existing property " << it->first - << " of type " << it->second->GetNameOfClass() << " to a property with different type " - << property->GetNameOfClass() << "." - << " Use ReplaceProperty() instead." << std::endl; + << " of type " << it->second->GetNameOfClass() << " to a property with different type " + << property->GetNameOfClass() << "." + << " Use ReplaceProperty() instead." << std::endl; } return; } // no? add it. m_Properties.insert(PropertyMap::value_type(propertyKey, property)); this->Modified(); } void mitk::PropertyList::ReplaceProperty(const std::string &propertyKey, BaseProperty *property) { if (!property) return; auto it(m_Properties.find(propertyKey)); // Is a property with key @a propertyKey contained in the list? if (it != m_Properties.cend()) { it->second = nullptr; m_Properties.erase(it); } // no? add/replace it. m_Properties.insert(PropertyMap::value_type(propertyKey, property)); Modified(); } -void mitk::PropertyList::RemoveProperty(const std::string &propertyKey) +void mitk::PropertyList::RemoveProperty(const std::string &propertyKey, const std::string &/*contextName*/, bool /*fallBackOnDefaultContext*/) { auto it(m_Properties.find(propertyKey)); // Is a property with key @a propertyKey contained in the list? if (it != m_Properties.cend()) { it->second = nullptr; m_Properties.erase(it); Modified(); } } mitk::PropertyList::PropertyList() { } mitk::PropertyList::PropertyList(const mitk::PropertyList &other) : itk::Object() { for (auto i = other.m_Properties.cbegin(); i != other.m_Properties.cend(); ++i) { m_Properties.insert(std::make_pair(i->first, i->second->Clone())); } } mitk::PropertyList::~PropertyList() { Clear(); } /** * Consider the list as changed when any of the properties has changed recently. */ unsigned long mitk::PropertyList::GetMTime() const { for (auto it = m_Properties.cbegin(); it != m_Properties.cend(); ++it) { if (it->second.IsNull()) { itkWarningMacro(<< "Property '" << it->first << "' contains nothing (nullptr)."); continue; } if (Superclass::GetMTime() < it->second->GetMTime()) { Modified(); break; } } return Superclass::GetMTime(); } bool mitk::PropertyList::DeleteProperty(const std::string &propertyKey) { auto it = m_Properties.find(propertyKey); if (it != m_Properties.end()) { it->second = nullptr; m_Properties.erase(it); Modified(); return true; } return false; } void mitk::PropertyList::Clear() { auto it = m_Properties.begin(), end = m_Properties.end(); while (it != end) { it->second = nullptr; ++it; } m_Properties.clear(); } itk::LightObject::Pointer mitk::PropertyList::InternalClone() const { itk::LightObject::Pointer result(new Self(*this)); result->UnRegister(); return result; } void mitk::PropertyList::ConcatenatePropertyList(PropertyList *pList, bool replace) { if (pList) { const PropertyMap *propertyMap = pList->GetMap(); for (auto iter = propertyMap->cbegin(); // m_PropertyList is created in the constructor, so we don't check it here iter != propertyMap->cend(); ++iter) { const std::string key = iter->first; BaseProperty *value = iter->second; if (replace) { ReplaceProperty(key.c_str(), value); } else { SetProperty(key.c_str(), value); } } } } bool mitk::PropertyList::GetBoolProperty(const char *propertyKey, bool &boolValue) const { BoolProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { boolValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs // return GetPropertyValue(propertyKey, boolValue); } bool mitk::PropertyList::GetIntProperty(const char *propertyKey, int &intValue) const { IntProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { intValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs // return GetPropertyValue(propertyKey, intValue); } bool mitk::PropertyList::GetFloatProperty(const char *propertyKey, float &floatValue) const { FloatProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { floatValue = gp->GetValue(); return true; } return false; // Templated Method does not work on Macs // return GetPropertyValue(propertyKey, floatValue); } bool mitk::PropertyList::GetStringProperty(const char *propertyKey, std::string &stringValue) const { StringProperty *sp = dynamic_cast(GetProperty(propertyKey)); if (sp != nullptr) { stringValue = sp->GetValue(); return true; } return false; } void mitk::PropertyList::SetIntProperty(const char *propertyKey, int intValue) { SetProperty(propertyKey, mitk::IntProperty::New(intValue)); } void mitk::PropertyList::SetBoolProperty(const char *propertyKey, bool boolValue) { SetProperty(propertyKey, mitk::BoolProperty::New(boolValue)); } void mitk::PropertyList::SetFloatProperty(const char *propertyKey, float floatValue) { SetProperty(propertyKey, mitk::FloatProperty::New(floatValue)); } void mitk::PropertyList::SetStringProperty(const char *propertyKey, const char *stringValue) { SetProperty(propertyKey, mitk::StringProperty::New(stringValue)); } void mitk::PropertyList::Set(const char *propertyKey, bool boolValue) { this->SetBoolProperty(propertyKey, boolValue); } void mitk::PropertyList::Set(const char *propertyKey, int intValue) { this->SetIntProperty(propertyKey, intValue); } void mitk::PropertyList::Set(const char *propertyKey, float floatValue) { this->SetFloatProperty(propertyKey, floatValue); } void mitk::PropertyList::Set(const char *propertyKey, double doubleValue) { this->SetDoubleProperty(propertyKey, doubleValue); } void mitk::PropertyList::Set(const char *propertyKey, const char *stringValue) { this->SetStringProperty(propertyKey, stringValue); } void mitk::PropertyList::Set(const char *propertyKey, const std::string &stringValue) { this->SetStringProperty(propertyKey, stringValue.c_str()); } bool mitk::PropertyList::Get(const char *propertyKey, bool &boolValue) const { return this->GetBoolProperty(propertyKey, boolValue); } bool mitk::PropertyList::Get(const char *propertyKey, int &intValue) const { return this->GetIntProperty(propertyKey, intValue); } bool mitk::PropertyList::Get(const char *propertyKey, float &floatValue) const { return this->GetFloatProperty(propertyKey, floatValue); } bool mitk::PropertyList::Get(const char *propertyKey, double &doubleValue) const { return this->GetDoubleProperty(propertyKey, doubleValue); } bool mitk::PropertyList::Get(const char *propertyKey, std::string &stringValue) const { return this->GetStringProperty(propertyKey, stringValue); } bool mitk::PropertyList::GetDoubleProperty(const char *propertyKey, double &doubleValue) const { DoubleProperty *gp = dynamic_cast(GetProperty(propertyKey)); if (gp != nullptr) { doubleValue = gp->GetValue(); return true; } return false; } void mitk::PropertyList::SetDoubleProperty(const char *propertyKey, double doubleValue) { SetProperty(propertyKey, mitk::DoubleProperty::New(doubleValue)); } diff --git a/Modules/Core/src/IO/mitkAbstractFileReader.cpp b/Modules/Core/src/IO/mitkAbstractFileReader.cpp index 3a2ddc72ea..ce5922b992 100644 --- a/Modules/Core/src/IO/mitkAbstractFileReader.cpp +++ b/Modules/Core/src/IO/mitkAbstractFileReader.cpp @@ -1,324 +1,324 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include #include #include #include #include namespace mitk { AbstractFileReader::InputStream::InputStream(IFileReader *reader, std::ios_base::openmode mode) : std::istream(nullptr), m_Stream(nullptr) { std::istream *stream = reader->GetInputStream(); if (stream) { this->init(stream->rdbuf()); } else { m_Stream = new std::ifstream(reader->GetInputLocation().c_str(), mode); this->init(m_Stream->rdbuf()); } } AbstractFileReader::InputStream::~InputStream() { delete m_Stream; } class AbstractFileReader::Impl : public FileReaderWriterBase { public: Impl() : FileReaderWriterBase(), m_Stream(nullptr), m_PrototypeFactory(nullptr) {} Impl(const Impl &other) : FileReaderWriterBase(other), m_Stream(nullptr), m_PrototypeFactory(nullptr) {} std::string m_Location; std::string m_TmpFile; std::istream *m_Stream; us::PrototypeServiceFactory *m_PrototypeFactory; us::ServiceRegistration m_Reg; }; AbstractFileReader::AbstractFileReader() : d(new Impl) {} AbstractFileReader::~AbstractFileReader() { UnregisterService(); delete d->m_PrototypeFactory; if (!d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); } } AbstractFileReader::AbstractFileReader(const AbstractFileReader &other) : IFileReader(), d(new Impl(*other.d.get())) { } AbstractFileReader::AbstractFileReader(const CustomMimeType &mimeType, const std::string &description) : d(new Impl) { d->SetMimeType(mimeType); d->SetDescription(description); } ////////////////////// Reading ///////////////////////// std::vector AbstractFileReader::Read() { std::vector result; DataStorage::Pointer ds = StandaloneDataStorage::New().GetPointer(); this->Read(*ds); DataStorage::SetOfObjects::ConstPointer dataNodes = ds->GetAll(); for (DataStorage::SetOfObjects::ConstIterator iter = dataNodes->Begin(), iterEnd = dataNodes->End(); iter != iterEnd; ++iter) { result.push_back(iter.Value()->GetData()); } return result; } DataStorage::SetOfObjects::Pointer AbstractFileReader::Read(DataStorage &ds) { DataStorage::SetOfObjects::Pointer result = DataStorage::SetOfObjects::New(); std::vector data = this->Read(); for (auto iter = data.begin(); iter != data.end(); ++iter) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); this->SetDefaultDataNodeProperties(node, this->GetInputLocation()); ds.Add(node); result->InsertElement(result->Size(), node); } return result; } IFileReader::ConfidenceLevel AbstractFileReader::GetConfidenceLevel() const { if (d->m_Stream) { if (*d->m_Stream) return Supported; } else { if (itksys::SystemTools::FileExists(this->GetInputLocation().c_str(), true)) { return Supported; } } return Unsupported; } //////////// µS Registration & Properties ////////////// us::ServiceRegistration AbstractFileReader::RegisterService(us::ModuleContext *context) { if (d->m_PrototypeFactory) return us::ServiceRegistration(); if (context == nullptr) { context = us::GetModuleContext(); } d->RegisterMimeType(context); if (this->GetMimeType()->GetName().empty()) { MITK_WARN << "Not registering reader due to empty MIME type."; return us::ServiceRegistration(); } struct PrototypeFactory : public us::PrototypeServiceFactory { AbstractFileReader *const m_Prototype; PrototypeFactory(AbstractFileReader *prototype) : m_Prototype(prototype) {} us::InterfaceMap GetService(us::Module * /*module*/, const us::ServiceRegistrationBase & /*registration*/) override { return us::MakeInterfaceMap(m_Prototype->Clone()); } void UngetService(us::Module * /*module*/, const us::ServiceRegistrationBase & /*registration*/, const us::InterfaceMap &service) override { delete us::ExtractInterface(service); } }; d->m_PrototypeFactory = new PrototypeFactory(this); us::ServiceProperties props = this->GetServiceProperties(); d->m_Reg = context->RegisterService(d->m_PrototypeFactory, props); return d->m_Reg; } void AbstractFileReader::UnregisterService() { try { d->m_Reg.Unregister(); } catch (const std::exception &) { } } us::ServiceProperties AbstractFileReader::GetServiceProperties() const { us::ServiceProperties result; result[IFileReader::PROP_DESCRIPTION()] = this->GetDescription(); result[IFileReader::PROP_MIMETYPE()] = this->GetMimeType()->GetName(); result[us::ServiceConstants::SERVICE_RANKING()] = this->GetRanking(); return result; } us::ServiceRegistration AbstractFileReader::RegisterMimeType(us::ModuleContext *context) { return d->RegisterMimeType(context); } std::vector< std::string > AbstractFileReader::GetReadFiles(){ return m_ReadFiles; } void AbstractFileReader::SetMimeType(const CustomMimeType &mimeType) { d->SetMimeType(mimeType); } void AbstractFileReader::SetDescription(const std::string &description) { d->SetDescription(description); } void AbstractFileReader::SetRanking(int ranking) { d->SetRanking(ranking); } int AbstractFileReader::GetRanking() const { return d->GetRanking(); } std::string AbstractFileReader::GetLocalFileName() const { std::string localFileName; if (d->m_Stream) { if (d->m_TmpFile.empty()) { // write the stream contents to temporary file std::string ext = itksys::SystemTools::GetFilenameExtension(this->GetInputLocation()); std::ofstream tmpStream; localFileName = mitk::IOUtil::CreateTemporaryFile( tmpStream, std::ios_base::out | std::ios_base::trunc | std::ios_base::binary, "XXXXXX" + ext); tmpStream << d->m_Stream->rdbuf(); d->m_TmpFile = localFileName; } else { localFileName = d->m_TmpFile; } } else { localFileName = d->m_Location; } return localFileName; } //////////////////////// Options /////////////////////// void AbstractFileReader::SetDefaultOptions(const IFileReader::Options &defaultOptions) { d->SetDefaultOptions(defaultOptions); } IFileReader::Options AbstractFileReader::GetDefaultOptions() const { return d->GetDefaultOptions(); } void AbstractFileReader::SetInput(const std::string &location) { d->m_Location = location; d->m_Stream = nullptr; } void AbstractFileReader::SetInput(const std::string &location, std::istream *is) { if (d->m_Stream != is && !d->m_TmpFile.empty()) { std::remove(d->m_TmpFile.c_str()); d->m_TmpFile.clear(); } d->m_Location = location; d->m_Stream = is; } std::string AbstractFileReader::GetInputLocation() const { return d->m_Location; } std::istream *AbstractFileReader::GetInputStream() const { return d->m_Stream; } MimeType AbstractFileReader::GetRegisteredMimeType() const { return d->GetRegisteredMimeType(); } IFileReader::Options AbstractFileReader::GetOptions() const { return d->GetOptions(); } us::Any AbstractFileReader::GetOption(const std::string &name) const { return d->GetOption(name); } void AbstractFileReader::SetOptions(const Options &options) { d->SetOptions(options); } void AbstractFileReader::SetOption(const std::string &name, const us::Any &value) { d->SetOption(name, value); } ////////////////// MISC ////////////////// void AbstractFileReader::AddProgressCallback(const ProgressCallback &callback) { d->AddProgressCallback(callback); } void AbstractFileReader::RemoveProgressCallback(const ProgressCallback &callback) { d->RemoveProgressCallback(callback); } ////////////////// µS related Getters ////////////////// const CustomMimeType *AbstractFileReader::GetMimeType() const { return d->GetMimeType(); } void AbstractFileReader::SetMimeTypePrefix(const std::string &prefix) { d->SetMimeTypePrefix(prefix); } std::string AbstractFileReader::GetMimeTypePrefix() const { return d->GetMimeTypePrefix(); } std::string AbstractFileReader::GetDescription() const { return d->GetDescription(); } void AbstractFileReader::SetDefaultDataNodeProperties(DataNode *node, const std::string &filePath) { // path if (!filePath.empty()) { mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenamePath(filePath)); node->SetProperty(StringProperty::PATH, pathProp); } // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); - if (nameProp.IsNull() || (strcmp(nameProp->GetValue(), "No Name!") == 0)) + if (nameProp.IsNull() || nameProp->GetValue() == DataNode::NO_NAME_VALUE()) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer()); - if (baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(), "No Name!") == 0)) + if (baseDataNameProp.IsNull() || baseDataNameProp->GetValue() == DataNode::NO_NAME_VALUE()) { // name neither defined in node, nor in BaseData -> name = filebasename; nameProp = mitk::StringProperty::New(this->GetRegisteredMimeType().GetFilenameWithoutExtension(filePath)); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if (!node->GetProperty("visible")) { node->SetVisibility(true); } } } diff --git a/Modules/Core/src/IO/mitkIOUtil.cpp b/Modules/Core/src/IO/mitkIOUtil.cpp index 082c35e44f..303ff51637 100644 --- a/Modules/Core/src/IO/mitkIOUtil.cpp +++ b/Modules/Core/src/IO/mitkIOUtil.cpp @@ -1,1025 +1,1025 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOUtil.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ITK #include // VTK #include #include #include #include #include static std::string GetLastErrorStr() { #ifdef US_PLATFORM_POSIX return std::string(strerror(errno)); #else // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, nullptr); std::string errMsg((LPCTSTR)lpMsgBuf); LocalFree(lpMsgBuf); return errMsg; #endif } #ifdef US_PLATFORM_WINDOWS #include #include // make the posix flags point to the obsolte bsd types on windows #define S_IRUSR S_IREAD #define S_IWUSR S_IWRITE #else #include #include #include #endif #include #include static const char validLetters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; // A cross-platform version of the mkstemps function static int mkstemps_compat(char *tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary files to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary file. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return -1; } /* This is where the Xs start. */ char *XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return -1; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, nullptr); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif for (unsigned int count = 0; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; int fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd >= 0) { errno = savedErrno; return fd; } else if (errno != EEXIST) { return -1; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return -1; } // A cross-platform version of the POSIX mkdtemp function static char *mkdtemps_compat(char *tmpl, int suffixlen) { static unsigned long long value = 0; int savedErrno = errno; // Lower bound on the number of temporary dirs to attempt to generate. #define ATTEMPTS_MIN (62 * 62 * 62) /* The number of times to attempt to generate a temporary dir. To conform to POSIX, this must be no smaller than TMP_MAX. */ #if ATTEMPTS_MIN < TMP_MAX const unsigned int attempts = TMP_MAX; #else const unsigned int attempts = ATTEMPTS_MIN; #endif const int len = strlen(tmpl); if ((len - suffixlen) < 6 || strncmp(&tmpl[len - 6 - suffixlen], "XXXXXX", 6)) { errno = EINVAL; return nullptr; } /* This is where the Xs start. */ char *XXXXXX = &tmpl[len - 6 - suffixlen]; /* Get some more or less random data. */ #ifdef US_PLATFORM_WINDOWS { SYSTEMTIME stNow; FILETIME ftNow; // get system time GetSystemTime(&stNow); stNow.wMilliseconds = 500; if (!SystemTimeToFileTime(&stNow, &ftNow)) { errno = -1; return nullptr; } unsigned long long randomTimeBits = ((static_cast(ftNow.dwHighDateTime) << 32) | static_cast(ftNow.dwLowDateTime)); value = randomTimeBits ^ static_cast(GetCurrentThreadId()); } #else { struct timeval tv; gettimeofday(&tv, nullptr); unsigned long long randomTimeBits = ((static_cast(tv.tv_usec) << 32) | static_cast(tv.tv_sec)); value = randomTimeBits ^ static_cast(getpid()); } #endif unsigned int count = 0; for (; count < attempts; value += 7777, ++count) { unsigned long long v = value; /* Fill in the random bits. */ XXXXXX[0] = validLetters[v % 62]; v /= 62; XXXXXX[1] = validLetters[v % 62]; v /= 62; XXXXXX[2] = validLetters[v % 62]; v /= 62; XXXXXX[3] = validLetters[v % 62]; v /= 62; XXXXXX[4] = validLetters[v % 62]; v /= 62; XXXXXX[5] = validLetters[v % 62]; #ifdef US_PLATFORM_WINDOWS int fd = _mkdir(tmpl); //, _S_IREAD | _S_IWRITE | _S_IEXEC); #else int fd = mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR); #endif if (fd >= 0) { errno = savedErrno; return tmpl; } else if (errno != EEXIST) { return nullptr; } } /* We got out of the loop because we ran out of combinations to try. */ errno = EEXIST; return nullptr; } //#endif //************************************************************** // mitk::IOUtil method definitions namespace mitk { struct IOUtil::Impl { struct FixedReaderOptionsFunctor : public ReaderOptionsFunctorBase { FixedReaderOptionsFunctor(const IFileReader::Options &options) : m_Options(options) {} bool operator()(LoadInfo &loadInfo) const override { IFileReader *reader = loadInfo.m_ReaderSelector.GetSelected().GetReader(); if (reader) { reader->SetOptions(m_Options); } return false; } private: const IFileReader::Options &m_Options; }; struct FixedWriterOptionsFunctor : public WriterOptionsFunctorBase { FixedWriterOptionsFunctor(const IFileReader::Options &options) : m_Options(options) {} bool operator()(SaveInfo &saveInfo) const override { IFileWriter *writer = saveInfo.m_WriterSelector.GetSelected().GetWriter(); if (writer) { writer->SetOptions(m_Options); } return false; } private: const IFileWriter::Options &m_Options; }; static BaseData::Pointer LoadBaseDataFromFile(const std::string &path, const ReaderOptionsFunctorBase* optionsCallback = nullptr); static void SetDefaultDataNodeProperties(mitk::DataNode *node, const std::string &filePath = std::string()); }; BaseData::Pointer IOUtil::Impl::LoadBaseDataFromFile(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { std::vector baseDataList = Load(path, optionsCallback); // The Load(path) call above should throw an exception if nothing could be loaded assert(!baseDataList.empty()); return baseDataList.front(); } #ifdef US_PLATFORM_WINDOWS std::string IOUtil::GetProgramPath() { char path[512]; std::size_t index = std::string(path, GetModuleFileName(nullptr, path, 512)).find_last_of('\\'); return std::string(path, index); } #elif defined(US_PLATFORM_APPLE) #include std::string IOUtil::GetProgramPath() { char path[512]; uint32_t size = sizeof(path); if (_NSGetExecutablePath(path, &size) == 0) { std::size_t index = std::string(path).find_last_of('/'); std::string strPath = std::string(path, index); // const char* execPath = strPath.c_str(); // mitk::StandardFileLocations::GetInstance()->AddDirectoryForSearch(execPath,false); return strPath; } return std::string(); } #else #include #include #include std::string IOUtil::GetProgramPath() { std::stringstream ss; ss << "/proc/" << getpid() << "/exe"; char proc[512] = {0}; ssize_t ch = readlink(ss.str().c_str(), proc, 512); if (ch == -1) return std::string(); std::size_t index = std::string(proc).find_last_of('/'); return std::string(proc, index); } #endif char IOUtil::GetDirectorySeparator() { #ifdef US_PLATFORM_WINDOWS return '\\'; #else return '/'; #endif } std::string IOUtil::GetTempPath() { static std::string result; if (result.empty()) { #ifdef US_PLATFORM_WINDOWS char tempPathTestBuffer[1]; DWORD bufferLength = ::GetTempPath(1, tempPathTestBuffer); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } std::vector tempPath(bufferLength); bufferLength = ::GetTempPath(bufferLength, &tempPath[0]); if (bufferLength == 0) { mitkThrow() << GetLastErrorStr(); } result.assign(tempPath.begin(), tempPath.begin() + static_cast(bufferLength)); #else result = "/tmp/"; #endif } return result; } std::string IOUtil::CreateTemporaryFile(const std::string &templateName, std::string path) { ofstream tmpOutputStream; std::string returnValue = CreateTemporaryFile(tmpOutputStream, templateName, path); tmpOutputStream.close(); return returnValue; } std::string IOUtil::CreateTemporaryFile(std::ofstream &f, const std::string &templateName, std::string path) { return CreateTemporaryFile(f, std::ios_base::out | std::ios_base::trunc, templateName, path); } std::string IOUtil::CreateTemporaryFile(std::ofstream &f, std::ios_base::openmode mode, const std::string &templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? -1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? -1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; int fd = mkstemps_compat(&dst_path[0], suffixlen); if (fd != -1) { path.assign(dst_path.begin(), dst_path.end() - 1); f.open(path.c_str(), mode | std::ios_base::out | std::ios_base::trunc); close(fd); } else { mitkThrow() << "Creating temporary file " << &dst_path[0] << " failed: " << GetLastErrorStr(); } return path; } std::string IOUtil::CreateTemporaryDirectory(const std::string &templateName, std::string path) { if (path.empty()) { path = GetTempPath(); } path += GetDirectorySeparator() + templateName; std::vector dst_path(path.begin(), path.end()); dst_path.push_back('\0'); std::size_t lastX = path.find_last_of('X'); std::size_t firstX = path.find_last_not_of('X', lastX); int firstNonX = firstX == std::string::npos ? -1 : firstX - 1; while (lastX != std::string::npos && (lastX - firstNonX) < 6) { lastX = path.find_last_of('X', firstX); firstX = path.find_last_not_of('X', lastX); firstNonX = firstX == std::string::npos ? -1 : firstX - 1; } std::size_t suffixlen = lastX == std::string::npos ? path.size() : path.size() - lastX - 1; if (mkdtemps_compat(&dst_path[0], suffixlen) == nullptr) { mitkThrow() << "Creating temporary directory " << &dst_path[0] << " failed: " << GetLastErrorStr(); } path.assign(dst_path.begin(), dst_path.end() - 1); return path; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string &path, DataStorage &storage, const ReaderOptionsFunctorBase *optionsCallback) { std::vector paths; paths.push_back(path); return Load(paths, storage, optionsCallback); } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::string &path, const IFileReader::Options &options, DataStorage &storage) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, nodeResult, &storage, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::string &path, const ReaderOptionsFunctorBase *optionsCallback) { std::vector paths; paths.push_back(path); return Load(paths, optionsCallback); } std::vector IOUtil::Load(const std::string &path, const IFileReader::Options &options) { std::vector loadInfos; loadInfos.push_back(LoadInfo(path)); Impl::FixedReaderOptionsFunctor optionsCallback(options); std::string errMsg = Load(loadInfos, nullptr, nullptr, &optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return loadInfos.front().m_Output; } DataStorage::SetOfObjects::Pointer IOUtil::Load(const std::vector &paths, DataStorage &storage, const ReaderOptionsFunctorBase *optionsCallback) { DataStorage::SetOfObjects::Pointer nodeResult = DataStorage::SetOfObjects::New(); std::vector loadInfos; for (auto loadInfo : paths) { loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, nodeResult, &storage, optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } return nodeResult; } std::vector IOUtil::Load(const std::vector &paths, const ReaderOptionsFunctorBase *optionsCallback) { std::vector result; std::vector loadInfos; for (auto loadInfo : paths) { loadInfos.push_back(loadInfo); } std::string errMsg = Load(loadInfos, nullptr, nullptr, optionsCallback); if (!errMsg.empty()) { mitkThrow() << errMsg; } for (std::vector::const_iterator iter = loadInfos.begin(), iterEnd = loadInfos.end(); iter != iterEnd; ++iter) { result.insert(result.end(), iter->m_Output.begin(), iter->m_Output.end()); } return result; } std::string IOUtil::Load(std::vector &loadInfos, DataStorage::SetOfObjects *nodeResult, DataStorage *ds, const ReaderOptionsFunctorBase *optionsCallback) { if (loadInfos.empty()) { return "No input files given"; } int filesToRead = loadInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2 * filesToRead); std::string errMsg; std::map usedReaderItems; std::vector< std::string > read_files; for (auto &loadInfo : loadInfos) { if(std::find(read_files.begin(), read_files.end(), loadInfo.m_Path) != read_files.end()) continue; std::vector readers = loadInfo.m_ReaderSelector.Get(); if (readers.empty()) { if (!itksys::SystemTools::FileExists(loadInfo.m_Path.c_str())) { errMsg += "File '" + loadInfo.m_Path + "' does not exist\n"; } else { errMsg += "No reader available for '" + loadInfo.m_Path + "'\n"; } continue; } bool callOptionsCallback = readers.size() > 1 || !readers.front().GetReader()->GetOptions().empty(); // check if we already used a reader which should be re-used std::vector currMimeTypes = loadInfo.m_ReaderSelector.GetMimeTypes(); std::string selectedMimeType; for (std::vector::const_iterator mimeTypeIter = currMimeTypes.begin(), mimeTypeIterEnd = currMimeTypes.end(); mimeTypeIter != mimeTypeIterEnd; ++mimeTypeIter) { std::map::const_iterator oldSelectedItemIter = usedReaderItems.find(mimeTypeIter->GetName()); if (oldSelectedItemIter != usedReaderItems.end()) { // we found an already used item for a mime-type which is contained // in the current reader set, check all current readers if there service // id equals the old reader for (std::vector::const_iterator currReaderItem = readers.begin(), currReaderItemEnd = readers.end(); currReaderItem != currReaderItemEnd; ++currReaderItem) { if (currReaderItem->GetMimeType().GetName() == mimeTypeIter->GetName() && currReaderItem->GetServiceId() == oldSelectedItemIter->second.GetServiceId() && currReaderItem->GetConfidenceLevel() >= oldSelectedItemIter->second.GetConfidenceLevel()) { // okay, we used the same reader already, re-use its options selectedMimeType = mimeTypeIter->GetName(); callOptionsCallback = false; loadInfo.m_ReaderSelector.Select(oldSelectedItemIter->second.GetServiceId()); loadInfo.m_ReaderSelector.GetSelected().GetReader()->SetOptions( oldSelectedItemIter->second.GetReader()->GetOptions()); break; } } if (!selectedMimeType.empty()) break; } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(loadInfo); if (!callOptionsCallback && !loadInfo.m_Cancel) { usedReaderItems.erase(selectedMimeType); FileReaderSelector::Item selectedItem = loadInfo.m_ReaderSelector.GetSelected(); usedReaderItems.insert(std::make_pair(selectedItem.GetMimeType().GetName(), selectedItem)); } } if (loadInfo.m_Cancel) { errMsg += "Reading operation(s) cancelled."; break; } IFileReader *reader = loadInfo.m_ReaderSelector.GetSelected().GetReader(); if (reader == nullptr) { errMsg += "Unexpected nullptr reader."; break; } // Do the actual reading try { DataStorage::SetOfObjects::Pointer nodes; if (ds != nullptr) { nodes = reader->Read(*ds); std::vector< std::string > new_files = reader->GetReadFiles(); read_files.insert( read_files.end(), new_files.begin(), new_files.end() ); } else { nodes = DataStorage::SetOfObjects::New(); std::vector baseData = reader->Read(); for (auto iter = baseData.begin(); iter != baseData.end(); ++iter) { if (iter->IsNotNull()) { mitk::DataNode::Pointer node = mitk::DataNode::New(); node->SetData(*iter); nodes->InsertElement(nodes->Size(), node); } } std::vector< std::string > new_files = reader->GetReadFiles(); read_files.insert( read_files.end(), new_files.begin(), new_files.end() ); } for (DataStorage::SetOfObjects::ConstIterator nodeIter = nodes->Begin(), nodeIterEnd = nodes->End(); nodeIter != nodeIterEnd; ++nodeIter) { const mitk::DataNode::Pointer &node = nodeIter->Value(); mitk::BaseData::Pointer data = node->GetData(); if (data.IsNull()) { continue; } mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(loadInfo.m_Path); data->SetProperty("path", pathProp); loadInfo.m_Output.push_back(data); if (nodeResult) { nodeResult->push_back(nodeIter->Value()); } } if (loadInfo.m_Output.empty() || (nodeResult && nodeResult->Size() == 0)) { errMsg += "Unknown read error occurred reading " + loadInfo.m_Path; } } catch (const std::exception &e) { errMsg += "Exception occured when reading file " + loadInfo.m_Path + ":\n" + e.what() + "\n\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToRead; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2 * filesToRead); return errMsg; } std::vector IOUtil::Load(const us::ModuleResource &usResource, std::ios_base::openmode mode) { us::ModuleResourceStream resStream(usResource, mode); mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); std::vector mimetypes = mimeTypeProvider->GetMimeTypesForFile(usResource.GetResourcePath()); std::vector data; if (mimetypes.empty()) { mitkThrow() << "No mimetype for resource stream: " << usResource.GetResourcePath(); return data; } mitk::FileReaderRegistry fileReaderRegistry; std::vector> refs = fileReaderRegistry.GetReferences(mimetypes[0]); if (refs.empty()) { mitkThrow() << "No reader available for resource stream: " << usResource.GetResourcePath(); return data; } mitk::IFileReader *reader = fileReaderRegistry.GetReader(refs[0]); reader->SetInput(usResource.GetResourcePath(), &resStream); data = reader->Read(); return data; } void IOUtil::Save(const BaseData *data, const std::string &path) { Save(data, path, IFileWriter::Options()); } void IOUtil::Save(const BaseData *data, const std::string &path, const IFileWriter::Options &options) { Save(data, std::string(), path, options); } void IOUtil::Save(const BaseData *data, const std::string &mimeType, const std::string &path, bool addExtension) { Save(data, mimeType, path, IFileWriter::Options(), addExtension); } void IOUtil::Save(const BaseData *data, const std::string &mimeType, const std::string &path, const IFileWriter::Options &options, bool addExtension) { if ((data == nullptr) || (data->IsEmpty())) mitkThrow() << "BaseData cannotbe null or empty for save methods in IOUtil.h."; std::string errMsg; if (options.empty()) { errMsg = Save(data, mimeType, path, nullptr, addExtension); } else { Impl::FixedWriterOptionsFunctor optionsCallback(options); errMsg = Save(data, mimeType, path, &optionsCallback, addExtension); } if (!errMsg.empty()) { mitkThrow() << errMsg; } } void IOUtil::Save(std::vector &saveInfos) { std::string errMsg = Save(saveInfos, nullptr); if (!errMsg.empty()) { mitkThrow() << errMsg; } } std::string IOUtil::Save(const BaseData *data, const std::string &mimeTypeName, const std::string &path, WriterOptionsFunctorBase *optionsCallback, bool addExtension) { if (path.empty()) { return "No output filename given"; } mitk::CoreServicePointer mimeTypeProvider(mitk::CoreServices::GetMimeTypeProvider()); MimeType mimeType = mimeTypeProvider->GetMimeTypeForName(mimeTypeName); SaveInfo saveInfo(data, mimeType, path); std::string ext = itksys::SystemTools::GetFilenameExtension(path); if (saveInfo.m_WriterSelector.IsEmpty()) { return std::string("No suitable writer found for the current data of type ") + data->GetNameOfClass() + (mimeType.IsValid() ? (std::string(" and mime-type ") + mimeType.GetName()) : std::string()) + (ext.empty() ? std::string() : (std::string(" with extension ") + ext)); } // Add an extension if not already specified if (ext.empty() && addExtension) { saveInfo.m_MimeType.GetExtensions().empty() ? std::string() : "." + saveInfo.m_MimeType.GetExtensions().front(); } std::vector infos; infos.push_back(saveInfo); return Save(infos, optionsCallback); } std::string IOUtil::Save(std::vector &saveInfos, WriterOptionsFunctorBase *optionsCallback) { if (saveInfos.empty()) { return "No data for saving available"; } int filesToWrite = saveInfos.size(); mitk::ProgressBar::GetInstance()->AddStepsToDo(2 * filesToWrite); std::string errMsg; std::set usedSaveInfos; for (auto &saveInfo : saveInfos) { const std::string baseDataType = saveInfo.m_BaseData->GetNameOfClass(); std::vector writers = saveInfo.m_WriterSelector.Get(); // Error out if no compatible Writer was found if (writers.empty()) { errMsg += std::string("No writer available for ") + baseDataType + " data.\n"; continue; } bool callOptionsCallback = writers.size() > 1 || !writers[0].GetWriter()->GetOptions().empty(); // check if we already used a writer for this base data type // which should be re-used auto oldSaveInfoIter = usedSaveInfos.find(saveInfo); if (oldSaveInfoIter != usedSaveInfos.end()) { // we previously saved a base data object of the same data with the same mime-type, // check if the same writer is contained in the current writer set and if the // confidence level matches FileWriterSelector::Item oldSelectedItem = oldSaveInfoIter->m_WriterSelector.Get(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); for (std::vector::const_iterator currWriterItem = writers.begin(), currWriterItemEnd = writers.end(); currWriterItem != currWriterItemEnd; ++currWriterItem) { if (currWriterItem->GetServiceId() == oldSelectedItem.GetServiceId() && currWriterItem->GetConfidenceLevel() >= oldSelectedItem.GetConfidenceLevel()) { // okay, we used the same writer already, re-use its options callOptionsCallback = false; saveInfo.m_WriterSelector.Select(oldSaveInfoIter->m_WriterSelector.GetSelectedId()); saveInfo.m_WriterSelector.GetSelected().GetWriter()->SetOptions(oldSelectedItem.GetWriter()->GetOptions()); break; } } } if (callOptionsCallback && optionsCallback) { callOptionsCallback = (*optionsCallback)(saveInfo); if (!callOptionsCallback && !saveInfo.m_Cancel) { usedSaveInfos.erase(saveInfo); usedSaveInfos.insert(saveInfo); } } if (saveInfo.m_Cancel) { errMsg += "Writing operation(s) cancelled."; break; } IFileWriter *writer = saveInfo.m_WriterSelector.GetSelected().GetWriter(); if (writer == nullptr) { errMsg += "Unexpected nullptr writer."; break; } // Do the actual writing try { writer->SetOutputLocation(saveInfo.m_Path); writer->Write(); } catch (const std::exception &e) { errMsg += std::string("Exception occurred when writing to ") + saveInfo.m_Path + ":\n" + e.what() + "\n"; } mitk::ProgressBar::GetInstance()->Progress(2); --filesToWrite; } if (!errMsg.empty()) { MITK_ERROR << errMsg; } mitk::ProgressBar::GetInstance()->Progress(2 * filesToWrite); return errMsg; } // This method can be removed after the deprecated LoadDataNode() method was removed void IOUtil::Impl::SetDefaultDataNodeProperties(DataNode *node, const std::string &filePath) { // path mitk::StringProperty::Pointer pathProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenamePath(filePath)); node->SetProperty(StringProperty::PATH, pathProp); // name already defined? mitk::StringProperty::Pointer nameProp = dynamic_cast(node->GetProperty("name")); - if (nameProp.IsNull() || (strcmp(nameProp->GetValue(), "No Name!") == 0)) + if (nameProp.IsNull() || nameProp->GetValue() == DataNode::NO_NAME_VALUE()) { // name already defined in BaseData mitk::StringProperty::Pointer baseDataNameProp = dynamic_cast(node->GetData()->GetProperty("name").GetPointer()); - if (baseDataNameProp.IsNull() || (strcmp(baseDataNameProp->GetValue(), "No Name!") == 0)) + if (baseDataNameProp.IsNull() || baseDataNameProp->GetValue() == DataNode::NO_NAME_VALUE()) { // name neither defined in node, nor in BaseData -> name = filename nameProp = mitk::StringProperty::New(itksys::SystemTools::GetFilenameWithoutExtension(filePath)); node->SetProperty("name", nameProp); } else { // name defined in BaseData! nameProp = mitk::StringProperty::New(baseDataNameProp->GetValue()); node->SetProperty("name", nameProp); } } // visibility if (!node->GetProperty("visible")) { node->SetVisibility(true); } } IOUtil::SaveInfo::SaveInfo(const BaseData *baseData, const MimeType &mimeType, const std::string &path) : m_BaseData(baseData), m_WriterSelector(baseData, mimeType.GetName(), path), m_MimeType(mimeType.IsValid() ? mimeType // use the original mime-type : (m_WriterSelector.IsEmpty() ? mimeType // no writer found, use the original invalid mime-type : m_WriterSelector.GetDefault().GetMimeType() // use the found default mime-type )), m_Path(path), m_Cancel(false) { } bool IOUtil::SaveInfo::operator<(const IOUtil::SaveInfo &other) const { int r = strcmp(m_BaseData->GetNameOfClass(), other.m_BaseData->GetNameOfClass()); if (r == 0) { return m_WriterSelector.GetSelected().GetMimeType() < other.m_WriterSelector.GetSelected().GetMimeType(); } return r < 0; } IOUtil::LoadInfo::LoadInfo(const std::string &path) : m_Path(path), m_ReaderSelector(path), m_Cancel(false) {} } diff --git a/Modules/Core/src/Rendering/mitkMapper.cpp b/Modules/Core/src/Rendering/mitkMapper.cpp index a917acf960..6b5c4c0060 100644 --- a/Modules/Core/src/Rendering/mitkMapper.cpp +++ b/Modules/Core/src/Rendering/mitkMapper.cpp @@ -1,152 +1,152 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkMapper.h" #include "mitkBaseRenderer.h" #include "mitkDataNode.h" #include "mitkProperties.h" mitk::Mapper::Mapper() : m_DataNode(nullptr), m_TimeStep(0) { } mitk::Mapper::~Mapper() { } mitk::BaseData *mitk::Mapper::GetData() const { return m_DataNode == nullptr ? nullptr : m_DataNode->GetData(); } mitk::DataNode *mitk::Mapper::GetDataNode() const { return this->m_DataNode; } bool mitk::Mapper::GetColor(float rgb[3], mitk::BaseRenderer *renderer, const char *name) const { const mitk::DataNode *node = GetDataNode(); if (node == nullptr) return false; return node->GetColor(rgb, renderer, name); } bool mitk::Mapper::GetVisibility(bool &visible, mitk::BaseRenderer *renderer, const char *name) const { const mitk::DataNode *node = GetDataNode(); if (node == nullptr) return false; return node->GetVisibility(visible, renderer, name); } bool mitk::Mapper::GetOpacity(float &opacity, mitk::BaseRenderer *renderer, const char *name) const { const mitk::DataNode *node = GetDataNode(); if (node == nullptr) return false; return node->GetOpacity(opacity, renderer, name); } bool mitk::Mapper::GetLevelWindow(mitk::LevelWindow &levelWindow, mitk::BaseRenderer *renderer, const char *name) const { const mitk::DataNode *node = GetDataNode(); if (node == nullptr) return false; return node->GetLevelWindow(levelWindow, renderer, name); } bool mitk::Mapper::IsVisible(mitk::BaseRenderer *renderer, const char *name) const { bool visible = true; GetDataNode()->GetVisibility(visible, renderer, name); return visible; } void mitk::Mapper::CalculateTimeStep(mitk::BaseRenderer *renderer) { if ((renderer != nullptr) && (m_DataNode != nullptr)) { m_TimeStep = renderer->GetTimeStep(m_DataNode->GetData()); } else { m_TimeStep = 0; } } void mitk::Mapper::Update(mitk::BaseRenderer *renderer) { const DataNode *node = GetDataNode(); assert(node != nullptr); auto *data = static_cast(node->GetData()); if (!data) return; // Calculate time step of the input data for the specified renderer (integer value) this->CalculateTimeStep(renderer); // Check if time step is valid const TimeGeometry *dataTimeGeometry = data->GetTimeGeometry(); if ((dataTimeGeometry == nullptr) || (dataTimeGeometry->CountTimeSteps() == 0) || (!dataTimeGeometry->IsValidTimeStep(m_TimeStep))) { // TimeGeometry or time step is not valid for this data: // reset mapper so that nothing is displayed this->ResetMapper(renderer); return; } this->GenerateDataForRenderer(renderer); } bool mitk::Mapper::BaseLocalStorage::IsGenerateDataRequired(mitk::BaseRenderer *renderer, mitk::Mapper *mapper, mitk::DataNode *dataNode) const { if (mapper && m_LastGenerateDataTime < mapper->GetMTime()) return true; if (dataNode) { if (m_LastGenerateDataTime < dataNode->GetDataReferenceChangedTime()) return true; mitk::BaseData *data = dataNode->GetData(); if (data && m_LastGenerateDataTime < data->GetMTime()) return true; } if (renderer && m_LastGenerateDataTime < renderer->GetTimeStepUpdateTime()) return true; return false; } void mitk::Mapper::SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer, bool overwrite) { node->AddProperty("visible", mitk::BoolProperty::New(true), renderer, overwrite); node->AddProperty("layer", mitk::IntProperty::New(0), renderer, overwrite); - node->AddProperty("name", mitk::StringProperty::New("No Name!"), renderer, overwrite); + node->AddProperty("name", mitk::StringProperty::New(DataNode::NO_NAME_VALUE()), renderer, overwrite); } diff --git a/Modules/Core/test/mitkPointSetLocaleTest.cpp b/Modules/Core/test/mitkPointSetLocaleTest.cpp index 62a82e818d..568f6c55eb 100644 --- a/Modules/Core/test/mitkPointSetLocaleTest.cpp +++ b/Modules/Core/test/mitkPointSetLocaleTest.cpp @@ -1,162 +1,162 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIOUtil.h" #include "mitkPointSet.h" #include "mitkStandardFileLocations.h" #include "mitkTestingMacros.h" #include #include #include #include bool ChangeLocale(const std::string &locale) { try { MITK_TEST_OUTPUT(<< "\n** Changing locale from " << setlocale(LC_ALL, nullptr) << " to '" << locale << "'"); setlocale(LC_ALL, locale.c_str()); std::locale l(locale.c_str()); std::cin.imbue(l); std::cout.imbue(l); return true; } catch (...) { MITK_TEST_OUTPUT(<< "Could not activate locale " << locale << "\n"); return false; } } void ReaderLocaleTest(mitk::Point3D &refPoint, std::string filename) { MITK_TEST_OUTPUT(<< "---- Reader Test ---- "); mitk::PointSet::Pointer pointSet = mitk::IOUtil::Load(filename); mitk::Point3D point; if (pointSet->GetPointIfExists(0, &point)) { MITK_TEST_CONDITION_REQUIRED(fabs(refPoint[0] - point[0]) < 0.00001, "read x correct"); MITK_TEST_CONDITION_REQUIRED(fabs(refPoint[1] - point[1]) < 0.00001, "read y correct"); MITK_TEST_CONDITION_REQUIRED(fabs(refPoint[2] - point[2]) < 0.00001, "read z correct"); } else { MITK_TEST_FAILED_MSG(<< "File " << filename << " can not be read - test will not applied."); return; } } void WriterLocaleTest(mitk::Point3D &refPoint, std::string filename) { MITK_TEST_OUTPUT(<< "---- Writer Test---- "); // create pointset mitk::PointSet::Pointer refPointSet = mitk::PointSet::New(); refPointSet->InsertPoint(0, refPoint); // SetPoint(0, refPoint); std::string tmpFilePath = mitk::IOUtil::CreateTemporaryFile("testPointSet_XXXXXX.mps"); // write point set mitk::IOUtil::Save(refPointSet, tmpFilePath); std::ifstream stream(tmpFilePath.c_str()); // compare two .mps files std::ifstream refStream(filename.c_str()); MITK_TEST_CONDITION_REQUIRED(refStream, "Read reference point set"); MITK_TEST_CONDITION_REQUIRED(stream, "Read point set"); bool differ = false; if (stream.is_open() && refStream.is_open()) { std::string streamLine; std::string refStreamLine; while (!stream.eof() && !refStream.eof()) { getline(stream, streamLine); getline(refStream, refStreamLine); if (streamLine.compare(refStreamLine) != 0) { differ = true; break; } } stream.close(); refStream.close(); } MITK_TEST_CONDITION_REQUIRED(!differ, "Write point set correct"); } int mitkPointSetLocaleTest(int, char *[]) { MITK_TEST_BEGIN("PointSetLocaleTest"); // create reference point set mitk::PointSet::Pointer refPointSet = mitk::PointSet::New(); mitk::Point3D refPoint; refPoint[0] = 32.2946; refPoint[1] = -17.7359; refPoint[2] = 29.6502; refPointSet->SetPoint(0, refPoint); // create locale list typedef std::list StringList; StringList alllocales; alllocales.push_back("de_DE"); alllocales.push_back("de_DE.utf8"); alllocales.push_back("de_DE.UTF-8"); alllocales.push_back("de_DE@euro"); alllocales.push_back("German_Germany"); -// QuickFix for MAC OS X +// QuickFix for macOS // See for more the Bug #3894 comments #if defined(__APPLE__) || defined(MACOSX) alllocales.push_back("C"); #endif // write a reference file using the "C" locale once ChangeLocale("C"); std::string referenceFilePath = mitk::IOUtil::CreateTemporaryFile("refPointSet_XXXXXX.mps"); MITK_INFO << "Reference PointSet in " << referenceFilePath; // write point set mitk::IOUtil::Save(refPointSet, referenceFilePath); unsigned int numberOfTestedGermanLocales(0); for (auto iter = alllocales.begin(); iter != alllocales.end(); ++iter) { if (ChangeLocale(*iter)) { ++numberOfTestedGermanLocales; WriterLocaleTest(refPoint, referenceFilePath); ReaderLocaleTest(refPoint, referenceFilePath); } } if (numberOfTestedGermanLocales == 0) { MITK_TEST_OUTPUT(<< "Warning: No German locale was found on the system."); } // MITK_TEST_CONDITION_REQUIRED( numberOfTestedGermanLocales > 0, "Verify that at least one German locale has been // tested."); MITK_TEST_END(); } diff --git a/Modules/DICOMReader/include/mitkBaseDICOMReaderService.h b/Modules/DICOMReader/include/mitkBaseDICOMReaderService.h index fc16890702..8a191076e9 100644 --- a/Modules/DICOMReader/include/mitkBaseDICOMReaderService.h +++ b/Modules/DICOMReader/include/mitkBaseDICOMReaderService.h @@ -1,57 +1,64 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKBASEDICOMREADERSERVICE_H #define MITKBASEDICOMREADERSERVICE_H #include #include #include "MitkDICOMReaderExports.h" namespace mitk { /** Base class for service wrappers that make DICOMFileReader from the DICOMReader module usable. */ class MITKDICOMREADER_EXPORT BaseDICOMReaderService : public AbstractFileReader { public: BaseDICOMReaderService(const std::string& description); BaseDICOMReaderService(const mitk::CustomMimeType& customType, const std::string& description); using AbstractFileReader::Read; /** Uses this->GetRelevantFile() and this->GetReader to load the image. * data and puts it into base data instances-*/ std::vector > Read() override; IFileReader::ConfidenceLevel GetConfidenceLevel() const override; protected: /** Returns the list of all DCM files that are in the same directory * like this->GetLocalFileName().*/ mitk::StringList GetRelevantFiles() const; /** Returns the reader instance that should be used. The descission may be based * one the passed relevant file list.*/ virtual mitk::DICOMFileReader::Pointer GetReader(const mitk::StringList& relevantFiles) const = 0; }; + +class IPropertyProvider; + +/** Helper function that generates a name string (e.g. for DataNode names) from the DICOM properties of the passed + provider instance. If the instance is nullptr, or has no dicom properties DataNode::NO_NAME_VALUE() will be returned.*/ +std::string MITKDICOMREADER_EXPORT GenerateNameFromDICOMProperties(const mitk::IPropertyProvider* provider); + } #endif // MITKBASEDICOMREADERSERVICE_H diff --git a/Modules/DICOMReader/include/mitkDICOMImageBlockDescriptor.h b/Modules/DICOMReader/include/mitkDICOMImageBlockDescriptor.h index a1fff078e9..5e45f3a517 100644 --- a/Modules/DICOMReader/include/mitkDICOMImageBlockDescriptor.h +++ b/Modules/DICOMReader/include/mitkDICOMImageBlockDescriptor.h @@ -1,231 +1,241 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef mitkDICOMImageBlockDescriptor_h #define mitkDICOMImageBlockDescriptor_h #include "mitkDICOMEnums.h" #include "mitkDICOMImageFrameInfo.h" #include "mitkDICOMTag.h" #include "mitkDICOMTagCache.h" #include "mitkImage.h" #include "mitkProperties.h" #include "mitkWeakPointer.h" +#include "mitkIPropertyProvider.h" #include "mitkGantryTiltInformation.h" #include namespace mitk { struct DICOMCachedValueInfo { unsigned int TimePoint; unsigned int SliceInTimePoint; std::string Value; }; class DICOMCachedValueLookupTable : public GenericLookupTable< DICOMCachedValueInfo > { public: typedef DICOMCachedValueLookupTable Self; typedef GenericLookupTable< DICOMCachedValueInfo > Superclass; const char *GetNameOfClass() const override { return "DICOMCachedValueLookupTable"; } DICOMCachedValueLookupTable() {} Superclass& operator=(const Superclass& other) override { return Superclass::operator=(other); } ~DICOMCachedValueLookupTable() override {} }; /** \ingroup DICOMReaderModule \brief Output descriptor for DICOMFileReader. As a result of analysis by a mitk::DICOMFileReader, this class describes the properties of a single mitk::Images that could be loaded by the file reader. The descriptor contains the following information: - the mitk::Image itself. This will be nullptr after analysis and only be present after actual loading. - a list of frames (mostly: filenames) that went into composition of the mitk::Image. - an assessment of the reader's ability to load this set of files (ReaderImplementationLevel) - this can be used for reader selection when one reader is able to load an image with correct colors and the other is able to produce only gray values, for example - description of aspects of the image. Mostly a key-value list implemented by means of mitk::PropertyList. - for specific keys and possible values, see documentation of specific readers. \note an mitk::Image may both consist of multiple files (the "old" DICOM way) or a mitk::Image may be described by a single DICOM file or even only parts of a DICOM file (the newer multi-frame DICOM classes). To reflect this DICOMImageFrameList describes a list of frames from different or a single file. Described aspects of an image are: - whether pixel spacing is meant to be in-patient or on-detector (mitk::PixelSpacingInterpretation) - details about a possible gantry tilt (intended for use by file readers, may be hidden later) */ - class MITKDICOMREADER_EXPORT DICOMImageBlockDescriptor + class MITKDICOMREADER_EXPORT DICOMImageBlockDescriptor: public IPropertyProvider { public: DICOMImageBlockDescriptor(); - ~DICOMImageBlockDescriptor(); + virtual ~DICOMImageBlockDescriptor(); DICOMImageBlockDescriptor(const DICOMImageBlockDescriptor& other); DICOMImageBlockDescriptor& operator=(const DICOMImageBlockDescriptor& other); static DICOMTagList GetTagsOfInterest(); /// List of frames that constitute the mitk::Image (DICOMImageFrame%s) void SetImageFrameList(const DICOMImageFrameList& framelist); /// List of frames that constitute the mitk::Image (DICOMImageFrame%s) const DICOMImageFrameList& GetImageFrameList() const; /// The 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList void SetMitkImage(Image::Pointer image); /// the 3D mitk::Image that is loaded from the DICOM files of a DICOMImageFrameList Image::Pointer GetMitkImage() const; /// Reader's capability to appropriately load this set of frames ReaderImplementationLevel GetReaderImplementationLevel() const; /// Reader's capability to appropriately load this set of frames void SetReaderImplementationLevel(const ReaderImplementationLevel& level); /// Key-value store describing aspects of the image to be loaded void SetProperty(const std::string& key, BaseProperty* value); /// Key-value store describing aspects of the image to be loaded BaseProperty* GetProperty(const std::string& key) const; /// Convenience function around GetProperty() std::string GetPropertyAsString(const std::string&) const; /// Convenience function around SetProperty() void SetFlag(const std::string& key, bool value); /// Convenience function around GetProperty() bool GetFlag(const std::string& key, bool defaultValue) const; /// Convenience function around SetProperty() void SetIntProperty(const std::string& key, int value); /// Convenience function around GetProperty() int GetIntProperty(const std::string& key, int defaultValue) const; + virtual BaseProperty::ConstPointer GetConstProperty(const std::string &propertyKey, + const std::string &contextName = "", + bool fallBackOnDefaultContext = true) const override; + + virtual std::vector GetPropertyKeys(const std::string &contextName = "", + bool includeDefaultContext = false) const override; + + virtual std::vector GetPropertyContextNames() const override; + private: // For future implementation: load slice-by-slice, mark this using these methods void SetSliceIsLoaded(unsigned int index, bool isLoaded); // For future implementation: load slice-by-slice, mark this using these methods bool IsSliceLoaded(unsigned int index) const; // For future implementation: load slice-by-slice, mark this using these methods bool AllSlicesAreLoaded() const; public: /// Describe how the mitk::Image's pixel spacing should be interpreted PixelSpacingInterpretation GetPixelSpacingInterpretation() const; /// Describe the correct x/y pixel spacing of the mitk::Image (which some readers might need to adjust after loading) void GetDesiredMITKImagePixelSpacing(ScalarType& spacingXinMM, ScalarType& spacingYinMM) const; /// Describe the gantry tilt of the acquisition void SetTiltInformation(const GantryTiltInformation& info); /// Describe the gantry tilt of the acquisition const GantryTiltInformation GetTiltInformation() const; /// SOP Class UID of this set of frames void SetSOPClassUID(const std::string& uid); /// SOP Class UID of this set of frames std::string GetSOPClassUID() const; /// SOP Class as human readable name (e.g. "CT Image Storage") std::string GetSOPClassUIDAsName() const; /**Convinience method that returns the property timesteps*/ int GetNumberOfTimeSteps() const; /**return the number of frames that constitute one timestep.*/ int GetNumberOfFramesPerTimeStep() const; void SetTagCache(DICOMTagCache* privateCache); /** Type specifies additional tags of interest. Key is the tag path of interest. * The value is an optional user defined name for the property that should be used to store the tag value(s). * Empty value is default and will imply to use the found DICOMTagPath as property name.*/ typedef std::map AdditionalTagsMapType; /** * \brief Set a list of DICOMTagPaths that specifiy all DICOM-Tags that will be copied into the property of the mitk::Image. * * This method can be used to specify a list of DICOM-tags that shall be available after the loading. * The value in the tagMap is an optional user defined name for the property key that should be used * when storing the property). Empty value is default and will imply to use the found DICOMTagPath * as property key. * By default the content of the DICOM tags will be stored in a StringLookupTable on the mitk::Image. * This behaviour can be changed by setting a different TagLookupTableToPropertyFunctor via * SetTagLookupTableToPropertyFunctor(). */ void SetAdditionalTagsOfInterest(const AdditionalTagsMapType& tagMap); typedef std::function TagLookupTableToPropertyFunctor; /** * \brief Set a functor that defines how the slice-specific tag-values are stored in a Property. * * This method sets a functor that is given a StringLookupTable that contains the values of one DICOM tag * mapped to the slice index. * The functor is supposed to store these values in an mitk Property. * * By default, the StringLookupTable is stored in a StringLookupTableProperty except if all values are * identical. In this case, the unique value is stored only once in a StringProperty. */ void SetTagLookupTableToPropertyFunctor(TagLookupTableToPropertyFunctor); /// Print information about this image block to given stream void Print(std::ostream& os, bool filenameDetails) const; private: // read values from tag cache std::string GetPixelSpacing() const; std::string GetImagerPixelSpacing() const; Image::Pointer FixupSpacing(Image* mitkImage); Image::Pointer DescribeImageWithProperties(Image* mitkImage); void UpdateImageDescribingProperties() const; static mitk::BaseProperty::Pointer GetPropertyForDICOMValues(const DICOMCachedValueLookupTable& cacheLookupTable); double stringtodouble(const std::string& str) const; DICOMImageFrameList m_ImageFrameList; Image::Pointer m_MitkImage; BoolList m_SliceIsLoaded; ReaderImplementationLevel m_ReaderImplementationLevel; GantryTiltInformation m_TiltInformation; PropertyList::Pointer m_PropertyList; mitk::WeakPointer m_TagCache; mutable bool m_PropertiesOutOfDate; AdditionalTagsMapType m_AdditionalTagMap; std::set m_FoundAdditionalTags; TagLookupTableToPropertyFunctor m_PropertyFunctor; }; } #endif diff --git a/Modules/DICOMReader/src/mitkBaseDICOMReaderService.cpp b/Modules/DICOMReader/src/mitkBaseDICOMReaderService.cpp index 08c5d5ba30..c88d333a49 100644 --- a/Modules/DICOMReader/src/mitkBaseDICOMReaderService.cpp +++ b/Modules/DICOMReader/src/mitkBaseDICOMReaderService.cpp @@ -1,199 +1,208 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseDICOMReaderService.h" #include #include #include #include #include #include #include #include "legacy/mitkDicomSeriesReader.h" #include #include +#include "mitkIPropertyProvider.h" +#include "mitkPropertyNameHelper.h" + #include #include #include namespace mitk { BaseDICOMReaderService::BaseDICOMReaderService(const std::string& description) : AbstractFileReader(CustomMimeType(IOMimeTypes::DICOM_MIMETYPE()), description) { } BaseDICOMReaderService::BaseDICOMReaderService(const mitk::CustomMimeType& customType, const std::string& description) : AbstractFileReader(customType, description) { } std::vector > BaseDICOMReaderService::Read() { std::vector result; std::string fileName = this->GetLocalFileName(); //special handling of Philips 3D US DICOM. //Copied from DICOMSeriesReaderService if (DicomSeriesReader::IsPhilips3DDicom(fileName)) { MITK_INFO << "it is a Philips3D US Dicom file" << std::endl; mitk::LocaleSwitch localeSwitch("C"); std::locale previousCppLocale(std::cin.getloc()); std::locale l("C"); std::cin.imbue(l); DataNode::Pointer node = DataNode::New(); mitk::DicomSeriesReader::StringContainer stringvec; stringvec.push_back(fileName); if (DicomSeriesReader::LoadDicomSeries(stringvec, *node)) { BaseData::Pointer data = node->GetData(); StringProperty::Pointer nameProp = StringProperty::New(itksys::SystemTools::GetFilenameName(fileName)); data->GetPropertyList()->SetProperty("name", nameProp); result.push_back(data); } std::cin.imbue(previousCppLocale); return result; } //Normal DICOM handling (It wasn't a Philips 3D US) mitk::StringList relevantFiles = this->GetRelevantFiles(); // check whether directory or file // if directory try to find first file within it instead // We only support this for a single directory at once if (relevantFiles.empty()) { bool pathIsDirectory = itksys::SystemTools::FileIsDirectory(this->GetLocalFileName()); if (pathIsDirectory) { itksys::Directory input; input.Load(this->GetLocalFileName().c_str()); std::vector files; for (unsigned long idx = 0; idxGetLocalFileName() + "/" + std::string(input.GetFile(idx)); files.push_back(fullpath.c_str()); } } relevantFiles = files; } } if (relevantFiles.empty()) { MITK_INFO << "DICOMReader service found no relevant files in specified location. No data is loaded. Location: "<GetReader(relevantFiles); if(reader.IsNull()) { MITK_INFO << "DICOMReader service found no suitable reader configuration for relevant files."; } else { const unsigned int ntotalfiles = relevantFiles.size(); for( unsigned int i=0; i< ntotalfiles; i++) { m_ReadFiles.push_back( relevantFiles.at(i) ); } reader->SetAdditionalTagsOfInterest(mitk::GetCurrentDICOMTagsOfInterest()); reader->SetTagLookupTableToPropertyFunctor(mitk::GetDICOMPropertyForDICOMValuesFunctor); reader->SetInputFiles(relevantFiles); mitk::DICOMDCMTKTagScanner::Pointer scanner = mitk::DICOMDCMTKTagScanner::New(); scanner->AddTagPaths(reader->GetTagsOfInterest()); scanner->SetInputFiles(relevantFiles); scanner->Scan(); reader->SetTagCache(scanner->GetScanCache()); reader->AnalyzeInputFiles(); reader->LoadImages(); for (unsigned int i = 0; i < reader->GetNumberOfOutputs(); ++i) { const mitk::DICOMImageBlockDescriptor& desc = reader->GetOutput(i); mitk::BaseData::Pointer data = desc.GetMitkImage().GetPointer(); - std::string nodeName = "Unnamed_DICOM"; - - std::string studyDescription = desc.GetPropertyAsString("studyDescription"); - std::string seriesDescription = desc.GetPropertyAsString("seriesDescription"); - - if (!studyDescription.empty()) - { - nodeName = studyDescription; - } - - if (!seriesDescription.empty()) - { - if (!studyDescription.empty()) - { - nodeName += "/"; - } - nodeName += seriesDescription; - } + std::string nodeName = GenerateNameFromDICOMProperties(&desc); StringProperty::Pointer nameProp = StringProperty::New(nodeName); data->SetProperty("name", nameProp); result.push_back(data); } } } return result; } StringList BaseDICOMReaderService::GetRelevantFiles() const { std::string fileName = this->GetLocalFileName(); mitk::StringList relevantFiles = mitk::GetDICOMFilesInSameDirectory(fileName); return relevantFiles; } IFileReader::ConfidenceLevel BaseDICOMReaderService::GetConfidenceLevel() const { IFileReader::ConfidenceLevel abstractConfidence = AbstractFileReader::GetConfidenceLevel(); if (Unsupported == abstractConfidence) { if (itksys::SystemTools::FileIsDirectory(this->GetInputLocation().c_str())) { // In principle we support dicom directories return Supported; } } return abstractConfidence; } +std::string GenerateNameFromDICOMProperties(const mitk::IPropertyProvider* provider) +{ + std::string nodeName = mitk::DataNode::NO_NAME_VALUE(); + + auto studyProp = provider->GetConstProperty(mitk::GeneratePropertyNameForDICOMTag(0x0020, 0x000D).c_str()); + if (studyProp.IsNotNull()) + { + nodeName = studyProp->GetValueAsString(); + } + + auto seriesProp = provider->GetConstProperty(mitk::GeneratePropertyNameForDICOMTag(0x0020, 0x000E).c_str()); + + if (seriesProp.IsNotNull()) + { + if (studyProp.IsNotNull()) + { + nodeName += " / "; + } + nodeName += seriesProp->GetValueAsString(); + } + + return nodeName; +}; } diff --git a/Modules/DICOMReader/src/mitkDICOMImageBlockDescriptor.cpp b/Modules/DICOMReader/src/mitkDICOMImageBlockDescriptor.cpp index 4ddcf30c79..b8bee82a21 100644 --- a/Modules/DICOMReader/src/mitkDICOMImageBlockDescriptor.cpp +++ b/Modules/DICOMReader/src/mitkDICOMImageBlockDescriptor.cpp @@ -1,865 +1,884 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkDICOMImageBlockDescriptor.h" #include "mitkStringProperty.h" #include "mitkLevelWindowProperty.h" #include +#include mitk::DICOMImageBlockDescriptor::DICOMImageBlockDescriptor() : m_ReaderImplementationLevel( SOPClassUnknown ) , m_PropertyList( PropertyList::New() ) , m_TagCache( nullptr ) , m_PropertiesOutOfDate( true ) { m_PropertyFunctor = &mitk::DICOMImageBlockDescriptor::GetPropertyForDICOMValues; } mitk::DICOMImageBlockDescriptor::~DICOMImageBlockDescriptor() { } mitk::DICOMImageBlockDescriptor::DICOMImageBlockDescriptor( const DICOMImageBlockDescriptor& other ) : m_ImageFrameList( other.m_ImageFrameList ) , m_MitkImage( other.m_MitkImage ) , m_SliceIsLoaded( other.m_SliceIsLoaded ) , m_ReaderImplementationLevel( other.m_ReaderImplementationLevel ) , m_TiltInformation( other.m_TiltInformation ) , m_PropertyList( other.m_PropertyList->Clone() ) , m_TagCache( other.m_TagCache ) , m_PropertiesOutOfDate( other.m_PropertiesOutOfDate ) , m_AdditionalTagMap(other.m_AdditionalTagMap) , m_FoundAdditionalTags(other.m_FoundAdditionalTags) , m_PropertyFunctor(other.m_PropertyFunctor) { if ( m_MitkImage ) { m_MitkImage = m_MitkImage->Clone(); } m_PropertyFunctor = &mitk::DICOMImageBlockDescriptor::GetPropertyForDICOMValues; } mitk::DICOMImageBlockDescriptor& mitk::DICOMImageBlockDescriptor:: operator=( const DICOMImageBlockDescriptor& other ) { if ( this != &other ) { m_ImageFrameList = other.m_ImageFrameList; m_MitkImage = other.m_MitkImage; m_SliceIsLoaded = other.m_SliceIsLoaded; m_ReaderImplementationLevel = other.m_ReaderImplementationLevel; m_TiltInformation = other.m_TiltInformation; m_AdditionalTagMap = other.m_AdditionalTagMap; m_FoundAdditionalTags = other.m_FoundAdditionalTags; m_PropertyFunctor = other.m_PropertyFunctor; if ( other.m_PropertyList ) { m_PropertyList = other.m_PropertyList->Clone(); } if ( other.m_MitkImage ) { m_MitkImage = other.m_MitkImage->Clone(); } m_TagCache = other.m_TagCache; m_PropertiesOutOfDate = other.m_PropertiesOutOfDate; } return *this; } mitk::DICOMTagList mitk::DICOMImageBlockDescriptor::GetTagsOfInterest() { DICOMTagList completeList; completeList.push_back( DICOMTag( 0x0018, 0x1164 ) ); // pixel spacing completeList.push_back( DICOMTag( 0x0028, 0x0030 ) ); // imager pixel spacing completeList.push_back( DICOMTag( 0x0008, 0x0018 ) ); // sop instance UID completeList.push_back( DICOMTag( 0x0008, 0x0016 ) ); // sop class UID completeList.push_back( DICOMTag( 0x0020, 0x0011 ) ); // series number completeList.push_back( DICOMTag( 0x0008, 0x1030 ) ); // study description completeList.push_back( DICOMTag( 0x0008, 0x103e ) ); // series description completeList.push_back( DICOMTag( 0x0008, 0x0060 ) ); // modality completeList.push_back( DICOMTag( 0x0018, 0x0024 ) ); // sequence name completeList.push_back( DICOMTag( 0x0020, 0x0037 ) ); // image orientation completeList.push_back( DICOMTag( 0x0020, 0x1041 ) ); // slice location completeList.push_back( DICOMTag( 0x0020, 0x0012 ) ); // acquisition number completeList.push_back( DICOMTag( 0x0020, 0x0013 ) ); // instance number completeList.push_back( DICOMTag( 0x0020, 0x0032 ) ); // image position patient completeList.push_back( DICOMTag( 0x0028, 0x1050 ) ); // window center completeList.push_back( DICOMTag( 0x0028, 0x1051 ) ); // window width completeList.push_back( DICOMTag( 0x0008, 0x0008 ) ); // image type completeList.push_back( DICOMTag( 0x0028, 0x0004 ) ); // photometric interpretation return completeList; } void mitk::DICOMImageBlockDescriptor::SetAdditionalTagsOfInterest( const AdditionalTagsMapType& tagMap) { m_AdditionalTagMap = tagMap; } void mitk::DICOMImageBlockDescriptor::SetTiltInformation( const GantryTiltInformation& info ) { m_TiltInformation = info; } const mitk::GantryTiltInformation mitk::DICOMImageBlockDescriptor::GetTiltInformation() const { return m_TiltInformation; } void mitk::DICOMImageBlockDescriptor::SetImageFrameList( const DICOMImageFrameList& framelist ) { m_ImageFrameList = framelist; m_SliceIsLoaded.resize( framelist.size() ); m_SliceIsLoaded.assign( framelist.size(), false ); m_PropertiesOutOfDate = true; } const mitk::DICOMImageFrameList& mitk::DICOMImageBlockDescriptor::GetImageFrameList() const { return m_ImageFrameList; } void mitk::DICOMImageBlockDescriptor::SetMitkImage( Image::Pointer image ) { if ( m_MitkImage != image ) { if ( m_TagCache.IsExpired() ) { MITK_ERROR << "Unable to describe MITK image with properties without a tag-cache object!"; m_MitkImage = nullptr; return; } if ( m_ImageFrameList.empty() ) { MITK_ERROR << "Unable to describe MITK image with properties without a frame list!"; m_MitkImage = nullptr; return; } // Should verify that the image matches m_ImageFrameList and m_TagCache // however, this is hard to do without re-analyzing all // TODO we should at least make sure that the number of frames is identical (plus rows/columns, // orientation) // without gantry tilt correction, we can also check image origin m_MitkImage = this->DescribeImageWithProperties( this->FixupSpacing( image ) ); } } mitk::Image::Pointer mitk::DICOMImageBlockDescriptor::GetMitkImage() const { return m_MitkImage; } mitk::Image::Pointer mitk::DICOMImageBlockDescriptor::FixupSpacing( Image* mitkImage ) { if ( mitkImage ) { Vector3D imageSpacing = mitkImage->GetGeometry()->GetSpacing(); ScalarType desiredSpacingX = imageSpacing[0]; ScalarType desiredSpacingY = imageSpacing[1]; this->GetDesiredMITKImagePixelSpacing( desiredSpacingX, desiredSpacingY ); // prefer pixel spacing over imager pixel spacing if ( desiredSpacingX <= 0 || desiredSpacingY <= 0 ) { return mitkImage; } MITK_DEBUG << "Loaded image with spacing " << imageSpacing[0] << ", " << imageSpacing[1]; MITK_DEBUG << "Found correct spacing info " << desiredSpacingX << ", " << desiredSpacingY; imageSpacing[0] = desiredSpacingX; imageSpacing[1] = desiredSpacingY; mitkImage->GetGeometry()->SetSpacing( imageSpacing ); } return mitkImage; } void mitk::DICOMImageBlockDescriptor::SetSliceIsLoaded( unsigned int index, bool isLoaded ) { if ( index < m_SliceIsLoaded.size() ) { m_SliceIsLoaded[index] = isLoaded; } else { std::stringstream ss; ss << "Index " << index << " out of range (" << m_SliceIsLoaded.size() << " indices reserved)"; throw std::invalid_argument( ss.str() ); } } bool mitk::DICOMImageBlockDescriptor::IsSliceLoaded( unsigned int index ) const { if ( index < m_SliceIsLoaded.size() ) { return m_SliceIsLoaded[index]; } else { std::stringstream ss; ss << "Index " << index << " out of range (" << m_SliceIsLoaded.size() << " indices reserved)"; throw std::invalid_argument( ss.str() ); } } bool mitk::DICOMImageBlockDescriptor::AllSlicesAreLoaded() const { bool allLoaded = true; for ( auto iter = m_SliceIsLoaded.cbegin(); iter != m_SliceIsLoaded.cend(); ++iter ) { allLoaded &= *iter; } return allLoaded; } /* PS defined IPS defined PS==IPS 0 0 --> UNKNOWN spacing, loader will invent 0 1 --> spacing as at detector surface 1 0 --> spacing as in patient 1 1 0 --> detector surface spacing CORRECTED for geometrical magnifications: spacing as in patient 1 1 1 --> detector surface spacing NOT corrected for geometrical magnifications: spacing as at detector */ mitk::PixelSpacingInterpretation mitk::DICOMImageBlockDescriptor::GetPixelSpacingInterpretation() const { if ( m_ImageFrameList.empty() || m_TagCache.IsExpired() ) { MITK_ERROR << "Invalid call to GetPixelSpacingInterpretation. Need to have initialized tag-cache!"; return SpacingUnknown; } const std::string pixelSpacing = this->GetPixelSpacing(); const std::string imagerPixelSpacing = this->GetImagerPixelSpacing(); if ( pixelSpacing.empty() ) { if ( imagerPixelSpacing.empty() ) { return SpacingUnknown; } else { return SpacingAtDetector; } } else // Pixel Spacing defined { if ( imagerPixelSpacing.empty() ) { return SpacingInPatient; } else if ( pixelSpacing != imagerPixelSpacing ) { return SpacingInPatient; } else { return SpacingAtDetector; } } } std::string mitk::DICOMImageBlockDescriptor::GetPixelSpacing() const { if ( m_ImageFrameList.empty() || m_TagCache.IsExpired() ) { MITK_ERROR << "Invalid call to GetPixelSpacing. Need to have initialized tag-cache!"; return std::string( "" ); } static const DICOMTag tagPixelSpacing( 0x0028, 0x0030 ); return m_TagCache.Lock()->GetTagValue( m_ImageFrameList.front(), tagPixelSpacing ).value; } std::string mitk::DICOMImageBlockDescriptor::GetImagerPixelSpacing() const { if ( m_ImageFrameList.empty() || m_TagCache.IsExpired() ) { MITK_ERROR << "Invalid call to GetImagerPixelSpacing. Need to have initialized tag-cache!"; return std::string( "" ); } static const DICOMTag tagImagerPixelSpacing( 0x0018, 0x1164 ); return m_TagCache.Lock()->GetTagValue( m_ImageFrameList.front(), tagImagerPixelSpacing ).value; } void mitk::DICOMImageBlockDescriptor::GetDesiredMITKImagePixelSpacing( ScalarType& spacingX, ScalarType& spacingY ) const { const std::string pixelSpacing = this->GetPixelSpacing(); // preference for "in patient" pixel spacing if ( !DICOMStringToSpacing( pixelSpacing, spacingX, spacingY ) ) { const std::string imagerPixelSpacing = this->GetImagerPixelSpacing(); // fallback to "on detector" spacing if ( !DICOMStringToSpacing( imagerPixelSpacing, spacingX, spacingY ) ) { // at this point we have no hints whether the spacing is correct // do a quick sanity check and either trust in the input or set both to 1 // We assume neither spacing to be negative, zero or unexpectedly large for // medical images if (spacingX < mitk::eps || spacingX > 1000 || spacingY < mitk::eps || spacingY > 1000) { spacingX = spacingY = 1.0; } } } } void mitk::DICOMImageBlockDescriptor::SetProperty( const std::string& key, BaseProperty* value ) { m_PropertyList->SetProperty( key, value ); } mitk::BaseProperty* mitk::DICOMImageBlockDescriptor::GetProperty( const std::string& key ) const { this->UpdateImageDescribingProperties(); return m_PropertyList->GetProperty( key ); } std::string mitk::DICOMImageBlockDescriptor::GetPropertyAsString( const std::string& key ) const { this->UpdateImageDescribingProperties(); const mitk::BaseProperty::Pointer property = m_PropertyList->GetProperty( key ); if ( property.IsNotNull() ) { return property->GetValueAsString(); } else { return std::string( "" ); } } void mitk::DICOMImageBlockDescriptor::SetFlag( const std::string& key, bool value ) { m_PropertyList->ReplaceProperty( key, BoolProperty::New( value ) ); } bool mitk::DICOMImageBlockDescriptor::GetFlag( const std::string& key, bool defaultValue ) const { this->UpdateImageDescribingProperties(); BoolProperty::ConstPointer boolProp = dynamic_cast( this->GetProperty( key ) ); if ( boolProp.IsNotNull() ) { return boolProp->GetValue(); } else { return defaultValue; } } void mitk::DICOMImageBlockDescriptor::SetIntProperty( const std::string& key, int value ) { m_PropertyList->ReplaceProperty( key, IntProperty::New( value ) ); } int mitk::DICOMImageBlockDescriptor::GetIntProperty( const std::string& key, int defaultValue ) const { this->UpdateImageDescribingProperties(); IntProperty::ConstPointer intProp = dynamic_cast( this->GetProperty( key ) ); if ( intProp.IsNotNull() ) { return intProp->GetValue(); } else { return defaultValue; } } double mitk::DICOMImageBlockDescriptor::stringtodouble( const std::string& str ) const { double d; std::string trimmedstring( str ); try { trimmedstring = trimmedstring.erase( trimmedstring.find_last_not_of( " \n\r\t" ) + 1 ); } catch ( ... ) { // no last not of } std::string firstcomponent( trimmedstring ); try { firstcomponent = trimmedstring.erase( trimmedstring.find_first_of( "\\" ) ); } catch ( ... ) { // no last not of } std::istringstream converter( firstcomponent ); if ( !firstcomponent.empty() && ( converter >> d ) && converter.eof() ) { return d; } else { throw std::invalid_argument( "Argument is not a convertable number" ); } } mitk::Image::Pointer mitk::DICOMImageBlockDescriptor::DescribeImageWithProperties( Image* mitkImage ) { // TODO: this is a collection of properties that have been provided by the // legacy DicomSeriesReader. // We should at some point clean up this collection and name them in a more // consistent way! if ( !mitkImage ) return mitkImage; // first part: add some tags that describe individual slices // these propeties are defined at analysis time (see UpdateImageDescribingProperties()) const char* propertyKeySliceLocation = "dicom.image.0020.1041"; const char* propertyKeyInstanceNumber = "dicom.image.0020.0013"; const char* propertyKeySOPInstanceUID = "dicom.image.0008.0018"; mitkImage->SetProperty( propertyKeySliceLocation, this->GetProperty( "sliceLocationForSlices" ) ); mitkImage->SetProperty( propertyKeyInstanceNumber, this->GetProperty( "instanceNumberForSlices" ) ); mitkImage->SetProperty( propertyKeySOPInstanceUID, this->GetProperty( "SOPInstanceUIDForSlices" ) ); mitkImage->SetProperty( "files", this->GetProperty( "filenamesForSlices" ) ); // second part: add properties that describe the whole image block mitkImage->SetProperty( "dicomseriesreader.SOPClassUID", StringProperty::New( this->GetSOPClassUID() ) ); mitkImage->SetProperty( "dicomseriesreader.SOPClass", StringProperty::New( this->GetSOPClassUIDAsName() ) ); mitkImage->SetProperty( "dicomseriesreader.PixelSpacingInterpretationString", StringProperty::New( PixelSpacingInterpretationToString( this->GetPixelSpacingInterpretation() ) ) ); mitkImage->SetProperty( "dicomseriesreader.PixelSpacingInterpretation", GenericProperty::New( this->GetPixelSpacingInterpretation() ) ); mitkImage->SetProperty( "dicomseriesreader.ReaderImplementationLevelString", StringProperty::New( ReaderImplementationLevelToString( m_ReaderImplementationLevel ) ) ); mitkImage->SetProperty( "dicomseriesreader.ReaderImplementationLevel", GenericProperty::New( m_ReaderImplementationLevel ) ); mitkImage->SetProperty( "dicomseriesreader.GantyTiltCorrected", BoolProperty::New( this->GetTiltInformation().IsRegularGantryTilt() ) ); mitkImage->SetProperty( "dicomseriesreader.3D+t", BoolProperty::New( this->GetFlag( "3D+t", false ) ) ); // level window const std::string windowCenter = this->GetPropertyAsString( "windowCenter" ); const std::string windowWidth = this->GetPropertyAsString( "windowWidth" ); try { const double level = stringtodouble( windowCenter ); const double window = stringtodouble( windowWidth ); mitkImage->SetProperty( "levelwindow", LevelWindowProperty::New( LevelWindow( level, window ) ) ); } catch ( ... ) { // nothing, no levelwindow to be predicted... } const std::string modality = this->GetPropertyAsString( "modality" ); mitkImage->SetProperty( "modality", StringProperty::New( modality ) ); mitkImage->SetProperty( "dicom.pixel.PhotometricInterpretation", this->GetProperty( "photometricInterpretation" ) ); mitkImage->SetProperty( "dicom.image.imagetype", this->GetProperty( "imagetype" ) ); mitkImage->SetProperty( "dicom.study.StudyDescription", this->GetProperty( "studyDescription" ) ); mitkImage->SetProperty( "dicom.series.SeriesDescription", this->GetProperty( "seriesDescription" ) ); mitkImage->SetProperty( "dicom.pixel.Rows", this->GetProperty( "rows" ) ); mitkImage->SetProperty( "dicom.pixel.Columns", this->GetProperty( "columns" ) ); // third part: get all found additional tags of interest for (auto tag : m_FoundAdditionalTags) { BaseProperty* prop = this->GetProperty(tag); if (prop) { mitkImage->SetProperty(tag.c_str(), prop); } } // fourth part: get something from ImageIO. BUT this needs to be created elsewhere. or not at all! return mitkImage; } void mitk::DICOMImageBlockDescriptor::SetReaderImplementationLevel( const ReaderImplementationLevel& level ) { m_ReaderImplementationLevel = level; } mitk::ReaderImplementationLevel mitk::DICOMImageBlockDescriptor::GetReaderImplementationLevel() const { return m_ReaderImplementationLevel; } std::string mitk::DICOMImageBlockDescriptor::GetSOPClassUID() const { if ( !m_ImageFrameList.empty() && !m_TagCache.IsExpired() ) { static const DICOMTag tagSOPClassUID( 0x0008, 0x0016 ); return m_TagCache.Lock()->GetTagValue( m_ImageFrameList.front(), tagSOPClassUID ).value; } else { MITK_ERROR << "Invalid call to DICOMImageBlockDescriptor::GetSOPClassUID(). Need to have initialized tag-cache!"; return std::string( "" ); } } std::string mitk::DICOMImageBlockDescriptor::GetSOPClassUIDAsName() const { if ( !m_ImageFrameList.empty() && !m_TagCache.IsExpired() ) { gdcm::UIDs uidKnowledge; uidKnowledge.SetFromUID( this->GetSOPClassUID().c_str() ); const char* name = uidKnowledge.GetName(); if ( name ) { return std::string( name ); } else { return std::string( "" ); } } else { MITK_ERROR << "Invalid call to DICOMImageBlockDescriptor::GetSOPClassUIDAsName(). Need to have " "initialized tag-cache!"; return std::string( "" ); } } int mitk::DICOMImageBlockDescriptor::GetNumberOfTimeSteps() const { int result = 1; this->m_PropertyList->GetIntProperty("timesteps", result); return result; }; int mitk::DICOMImageBlockDescriptor::GetNumberOfFramesPerTimeStep() const { const int numberOfTimesteps = this->GetNumberOfTimeSteps(); int numberOfFramesPerTimestep = this->m_ImageFrameList.size() / numberOfTimesteps; assert(int(double((double)this->m_ImageFrameList.size() / (double)numberOfTimesteps)) == numberOfFramesPerTimestep); // this should hold return numberOfFramesPerTimestep; }; void mitk::DICOMImageBlockDescriptor::SetTagCache( DICOMTagCache* privateCache ) { // this must only be used during loading and never afterwards m_TagCache = privateCache; } #define printPropertyRange( label, property_name ) \ \ { \ const std::string first = this->GetPropertyAsString( #property_name "First" ); \ const std::string last = this->GetPropertyAsString( #property_name "Last" ); \ if ( !first.empty() || !last.empty() ) \ { \ if ( first == last ) \ { \ os << " " label ": '" << first << "'" << std::endl; \ } \ else \ { \ os << " " label ": '" << first << "' - '" << last << "'" << std::endl; \ } \ } \ \ } #define printProperty( label, property_name ) \ \ { \ const std::string first = this->GetPropertyAsString( #property_name ); \ if ( !first.empty() ) \ { \ os << " " label ": '" << first << "'" << std::endl; \ } \ \ } #define printBool( label, commands ) \ \ { \ os << " " label ": '" << ( commands ? "yes" : "no" ) << "'" << std::endl; \ \ } void mitk::DICOMImageBlockDescriptor::Print(std::ostream& os, bool filenameDetails) const { os << " Number of Frames: '" << m_ImageFrameList.size() << "'" << std::endl; os << " SOP class: '" << this->GetSOPClassUIDAsName() << "'" << std::endl; printProperty( "Series Number", seriesNumber ); printProperty( "Study Description", studyDescription ); printProperty( "Series Description", seriesDescription ); printProperty( "Modality", modality ); printProperty( "Sequence Name", sequenceName ); printPropertyRange( "Slice Location", sliceLocation ); printPropertyRange( "Acquisition Number", acquisitionNumber ); printPropertyRange( "Instance Number", instanceNumber ); printPropertyRange( "Image Position", imagePositionPatient ); printProperty( "Image Orientation", orientation ); os << " Pixel spacing interpretation: '" << PixelSpacingInterpretationToString( this->GetPixelSpacingInterpretation() ) << "'" << std::endl; printBool( "Gantry Tilt", this->GetTiltInformation().IsRegularGantryTilt() ) // printBool("3D+t", this->GetFlag("3D+t",false)) // os << " MITK image loaded: '" << (this->GetMitkImage().IsNotNull() ? "yes" : "no") << "'" << // std::endl; if ( filenameDetails ) { os << " Files in this image block:" << std::endl; for ( auto frameIter = m_ImageFrameList.begin(); frameIter != m_ImageFrameList.end(); ++frameIter ) { os << " " << ( *frameIter )->Filename; if ( ( *frameIter )->FrameNo > 0 ) { os << ", " << ( *frameIter )->FrameNo; } os << std::endl; } } } #define storeTagValueToProperty( tag_name, tag_g, tag_e ) \ \ { \ const DICOMTag t( tag_g, tag_e ); \ const std::string tagValue = tagCache->GetTagValue( firstFrame, t ).value; \ const_cast( this ) \ ->SetProperty( #tag_name, StringProperty::New( tagValue ) ); \ \ } #define storeTagValueRangeToProperty( tag_name, tag_g, tag_e ) \ \ { \ const DICOMTag t( tag_g, tag_e ); \ const std::string tagValueFirst = tagCache->GetTagValue( firstFrame, t ).value; \ const std::string tagValueLast = tagCache->GetTagValue( lastFrame, t ).value; \ const_cast( this ) \ ->SetProperty( #tag_name "First", StringProperty::New( tagValueFirst ) ); \ const_cast( this ) \ ->SetProperty( #tag_name "Last", StringProperty::New( tagValueLast ) ); \ \ } void mitk::DICOMImageBlockDescriptor::UpdateImageDescribingProperties() const { if ( !m_PropertiesOutOfDate ) return; if ( !m_ImageFrameList.empty() ) { if ( m_TagCache.IsExpired() ) { MITK_ERROR << "Invalid call to DICOMImageBlockDescriptor::UpdateImageDescribingProperties(). Need to " "have initialized tag-cache!"; return; } auto tagCache = m_TagCache.Lock(); const DICOMImageFrameInfo::Pointer firstFrame = m_ImageFrameList.front(); const DICOMImageFrameInfo::Pointer lastFrame = m_ImageFrameList.back(); // see macros above storeTagValueToProperty( seriesNumber, 0x0020, 0x0011 ); storeTagValueToProperty( studyDescription, 0x0008, 0x1030 ); storeTagValueToProperty( seriesDescription, 0x0008, 0x103e ); storeTagValueToProperty( modality, 0x0008, 0x0060 ); storeTagValueToProperty( sequenceName, 0x0018, 0x0024 ); storeTagValueToProperty( orientation, 0x0020, 0x0037 ); storeTagValueToProperty( rows, 0x0028, 0x0010 ); storeTagValueToProperty( columns, 0x0028, 0x0011 ); storeTagValueRangeToProperty( sliceLocation, 0x0020, 0x1041 ); storeTagValueRangeToProperty( acquisitionNumber, 0x0020, 0x0012 ); storeTagValueRangeToProperty( instanceNumber, 0x0020, 0x0013 ); storeTagValueRangeToProperty( imagePositionPatient, 0x0020, 0x0032 ); storeTagValueToProperty( windowCenter, 0x0028, 0x1050 ); storeTagValueToProperty( windowWidth, 0x0028, 0x1051 ); storeTagValueToProperty( imageType, 0x0008, 0x0008 ); storeTagValueToProperty( photometricInterpretation, 0x0028, 0x0004 ); // some per-image attributes // frames are just numbered starting from 0. timestep 1 (the second time-step) has frames starting at // (number-of-frames-per-timestep) // std::string propertyKeySliceLocation = "dicom.image.0020.1041"; // std::string propertyKeyInstanceNumber = "dicom.image.0020.0013"; // std::string propertyKeySOPInstanceNumber = "dicom.image.0008.0018"; StringLookupTable sliceLocationForSlices; StringLookupTable instanceNumberForSlices; StringLookupTable SOPInstanceUIDForSlices; StringLookupTable filenamesForSlices; const DICOMTag tagSliceLocation( 0x0020, 0x1041 ); const DICOMTag tagInstanceNumber( 0x0020, 0x0013 ); const DICOMTag tagSOPInstanceNumber( 0x0008, 0x0018 ); std::unordered_map additionalTagResultList; unsigned int slice(0); int timePoint(-1); const int framesPerTimeStep = this->GetNumberOfFramesPerTimeStep(); for ( auto frameIter = m_ImageFrameList.begin(); frameIter != m_ImageFrameList.end(); ++slice, ++frameIter ) { unsigned int zSlice = slice%framesPerTimeStep; if ( zSlice == 0) { timePoint++; } const std::string sliceLocation = tagCache->GetTagValue( *frameIter, tagSliceLocation ).value; sliceLocationForSlices.SetTableValue( slice, sliceLocation ); const std::string instanceNumber = tagCache->GetTagValue( *frameIter, tagInstanceNumber ).value; instanceNumberForSlices.SetTableValue( slice, instanceNumber ); const std::string sopInstanceUID = tagCache->GetTagValue( *frameIter, tagSOPInstanceNumber ).value; SOPInstanceUIDForSlices.SetTableValue( slice, sopInstanceUID ); const std::string filename = ( *frameIter )->Filename; filenamesForSlices.SetTableValue( slice, filename ); MITK_DEBUG << "Tag info for slice " << slice << ": SL '" << sliceLocation << "' IN '" << instanceNumber << "' SOP instance UID '" << sopInstanceUID << "'"; for (const auto& tag : m_AdditionalTagMap) { const DICOMTagCache::FindingsListType findings = tagCache->GetTagValue( *frameIter, tag.first ); for (const auto& finding : findings) { if (finding.isValid) { std::string propKey = (tag.second.empty()) ? DICOMTagPathToPropertyName(finding.path) : tag.second; DICOMCachedValueInfo info{ static_cast(timePoint), zSlice, finding.value }; additionalTagResultList[propKey].SetTableValue(slice, info); } } } } // add property or properties with proper names auto* thisInstance = const_cast( this ); thisInstance->SetProperty( "sliceLocationForSlices", StringLookupTableProperty::New( sliceLocationForSlices ) ); thisInstance->SetProperty( "instanceNumberForSlices", StringLookupTableProperty::New( instanceNumberForSlices ) ); thisInstance->SetProperty( "SOPInstanceUIDForSlices", StringLookupTableProperty::New( SOPInstanceUIDForSlices ) ); thisInstance->SetProperty( "filenamesForSlices", StringLookupTableProperty::New( filenamesForSlices ) ); //add properties for additional tags of interest for ( auto iter = additionalTagResultList.cbegin(); iter != additionalTagResultList.cend(); ++iter ) { thisInstance->SetProperty( iter->first, m_PropertyFunctor( iter->second ) ); thisInstance->m_FoundAdditionalTags.insert(m_FoundAdditionalTags.cend(),iter->first); } m_PropertiesOutOfDate = false; } } mitk::BaseProperty::Pointer mitk::DICOMImageBlockDescriptor::GetPropertyForDICOMValues(const DICOMCachedValueLookupTable& cacheLookupTable) { const auto& lookupTable = cacheLookupTable.GetLookupTable(); typedef std::pair PairType; if ( std::adjacent_find( lookupTable.cbegin(), lookupTable.cend(), []( const PairType& lhs, const PairType& rhs ) { return lhs.second.Value != rhs.second.Value; } ) == lookupTable.cend() ) { return static_cast( mitk::StringProperty::New(cacheLookupTable.GetTableValue(0).Value).GetPointer()); } StringLookupTable stringTable; for (auto element : lookupTable) { stringTable.SetTableValue(element.first, element.second.Value); } return static_cast( mitk::StringLookupTableProperty::New(stringTable).GetPointer()); } void mitk::DICOMImageBlockDescriptor::SetTagLookupTableToPropertyFunctor( TagLookupTableToPropertyFunctor functor ) { if ( functor != nullptr ) { m_PropertyFunctor = functor; } } + +mitk::BaseProperty::ConstPointer mitk::DICOMImageBlockDescriptor::GetConstProperty(const std::string &propertyKey, + const std::string &/*contextName*/, bool /*fallBackOnDefaultContext*/) const +{ + this->UpdateImageDescribingProperties(); + return m_PropertyList->GetConstProperty(propertyKey); +}; + +std::vector mitk::DICOMImageBlockDescriptor::GetPropertyKeys(const std::string &/*contextName*/, bool /*includeDefaultContext*/) const +{ + this->UpdateImageDescribingProperties(); + return m_PropertyList->GetPropertyKeys(); +}; + +std::vector mitk::DICOMImageBlockDescriptor::GetPropertyContextNames() const +{ + return std::vector(); +}; diff --git a/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp b/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp index d299111837..c280fd4f3a 100644 --- a/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp +++ b/Modules/DICOMReader/src/mitkITKDICOMSeriesReaderHelper.cpp @@ -1,458 +1,458 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //#define MBILOG_ENABLE_DEBUG #include #define BOOST_DATE_TIME_NO_LIB //Prevent unnecessary/unwanted auto link in this compilation when activating boost libraries in the MITK superbuild //It is necessary because BOOST_ALL_DYN_LINK overwrites BOOST_DATE_TIME_NO_LIB #if defined(BOOST_ALL_DYN_LINK) #undef BOOST_ALL_DYN_LINK #endif #include #include "mitkITKDICOMSeriesReaderHelper.h" #include "mitkITKDICOMSeriesReaderHelper.txx" #include "mitkDICOMGDCMTagScanner.h" #include "mitkArbitraryTimeGeometry.h" #include "dcmtk/dcmdata/dcvrda.h" const mitk::DICOMTag mitk::ITKDICOMSeriesReaderHelper::AcquisitionDateTag = mitk::DICOMTag( 0x0008, 0x0022 ); const mitk::DICOMTag mitk::ITKDICOMSeriesReaderHelper::AcquisitionTimeTag = mitk::DICOMTag( 0x0008, 0x0032 ); const mitk::DICOMTag mitk::ITKDICOMSeriesReaderHelper::TriggerTimeTag = mitk::DICOMTag( 0x0018, 0x1060 ); #define switch3DCase( IOType, T ) \ case IOType: \ return LoadDICOMByITK( filenames, correctTilt, tiltInfo, io ); bool mitk::ITKDICOMSeriesReaderHelper::CanHandleFile( const std::string& filename ) { MITK_DEBUG << "ITKDICOMSeriesReaderHelper::CanHandleFile " << filename; itk::GDCMImageIO::Pointer tester = itk::GDCMImageIO::New(); return tester->CanReadFile( filename.c_str() ); } mitk::Image::Pointer mitk::ITKDICOMSeriesReaderHelper::Load( const StringContainer& filenames, bool correctTilt, const GantryTiltInformation& tiltInfo ) { if ( filenames.empty() ) { MITK_DEBUG << "Calling LoadDicomSeries with empty filename string container. Probably invalid application logic."; return nullptr; // this is not actually an error but the result is very simple } typedef itk::GDCMImageIO DcmIoType; DcmIoType::Pointer io = DcmIoType::New(); try { if ( io->CanReadFile( filenames.front().c_str() ) ) { io->SetFileName( filenames.front().c_str() ); io->ReadImageInformation(); if ( io->GetPixelType() == itk::ImageIOBase::SCALAR ) { switch ( io->GetComponentType() ) { switch3DCase(DcmIoType::UCHAR, unsigned char) switch3DCase(DcmIoType::CHAR, char) switch3DCase( DcmIoType::USHORT, unsigned short) switch3DCase(DcmIoType::SHORT, short) switch3DCase(DcmIoType::UINT, unsigned int) switch3DCase(DcmIoType::INT, int) switch3DCase( DcmIoType::ULONG, long unsigned int) switch3DCase(DcmIoType::LONG, long int) switch3DCase(DcmIoType::FLOAT, float) switch3DCase(DcmIoType::DOUBLE, double) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } else if ( io->GetPixelType() == itk::ImageIOBase::RGB ) { switch ( io->GetComponentType() ) { switch3DCase(DcmIoType::UCHAR, itk::RGBPixel) switch3DCase( DcmIoType::CHAR, itk::RGBPixel) switch3DCase(DcmIoType::USHORT, itk::RGBPixel) switch3DCase(DcmIoType::SHORT, itk::RGBPixel) switch3DCase( DcmIoType::UINT, itk::RGBPixel) switch3DCase(DcmIoType::INT, itk::RGBPixel) switch3DCase(DcmIoType::ULONG, itk::RGBPixel) switch3DCase(DcmIoType::LONG, itk::RGBPixel) switch3DCase( DcmIoType::FLOAT, itk::RGBPixel) switch3DCase(DcmIoType::DOUBLE, itk::RGBPixel) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } MITK_ERROR << "Unsupported DICOM pixel type"; return nullptr; } } catch ( const itk::MemoryAllocationError& e ) { MITK_ERROR << "Out of memory. Cannot load DICOM series: " << e.what(); } catch ( const std::exception& e ) { MITK_ERROR << "Error encountered when loading DICOM series:" << e.what(); } catch ( ... ) { MITK_ERROR << "Unspecified error encountered when loading DICOM series."; } return nullptr; } #define switch3DnTCase( IOType, T ) \ case IOType: \ return LoadDICOMByITK3DnT( filenamesLists, correctTilt, tiltInfo, io ); mitk::Image::Pointer mitk::ITKDICOMSeriesReaderHelper::Load3DnT( const StringContainerList& filenamesLists, bool correctTilt, const GantryTiltInformation& tiltInfo ) { if ( filenamesLists.empty() || filenamesLists.front().empty() ) { MITK_DEBUG << "Calling LoadDicomSeries with empty filename string container. Probably invalid application logic."; return nullptr; // this is not actually an error but the result is very simple } typedef itk::GDCMImageIO DcmIoType; DcmIoType::Pointer io = DcmIoType::New(); try { if ( io->CanReadFile( filenamesLists.front().front().c_str() ) ) { io->SetFileName( filenamesLists.front().front().c_str() ); io->ReadImageInformation(); if ( io->GetPixelType() == itk::ImageIOBase::SCALAR ) { switch ( io->GetComponentType() ) { switch3DnTCase(DcmIoType::UCHAR, unsigned char) switch3DnTCase(DcmIoType::CHAR, char) switch3DnTCase(DcmIoType::USHORT, unsigned short) switch3DnTCase( DcmIoType::SHORT, short) switch3DnTCase(DcmIoType::UINT, unsigned int) switch3DnTCase(DcmIoType::INT, int) switch3DnTCase(DcmIoType::ULONG, long unsigned int) switch3DnTCase(DcmIoType::LONG, long int) switch3DnTCase(DcmIoType::FLOAT, float) switch3DnTCase(DcmIoType::DOUBLE, double) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } else if ( io->GetPixelType() == itk::ImageIOBase::RGB ) { switch ( io->GetComponentType() ) { switch3DnTCase(DcmIoType::UCHAR, itk::RGBPixel) switch3DnTCase(DcmIoType::CHAR, itk::RGBPixel) switch3DnTCase( DcmIoType::USHORT, itk::RGBPixel) switch3DnTCase(DcmIoType::SHORT, itk::RGBPixel) switch3DnTCase(DcmIoType::UINT, itk::RGBPixel) switch3DnTCase( DcmIoType::INT, itk::RGBPixel) switch3DnTCase(DcmIoType::ULONG, itk::RGBPixel) switch3DnTCase(DcmIoType::LONG, itk::RGBPixel) switch3DnTCase( DcmIoType::FLOAT, itk::RGBPixel) switch3DnTCase(DcmIoType::DOUBLE, itk::RGBPixel) default : MITK_ERROR << "Found unsupported DICOM scalar pixel type: (enum value) " << io->GetComponentType(); } } MITK_ERROR << "Unsupported DICOM pixel type"; return nullptr; } } catch ( const itk::MemoryAllocationError& e ) { MITK_ERROR << "Out of memory. Cannot load DICOM series: " << e.what(); } catch ( const std::exception& e ) { MITK_ERROR << "Error encountered when loading DICOM series:" << e.what(); } catch ( ... ) { MITK_ERROR << "Unspecified error encountered when loading DICOM series."; } return nullptr; } bool ConvertDICOMDateTimeString( const std::string& dateString, const std::string& timeString, OFDateTime& time ) { OFString content( timeString.c_str() ); if ( !dateString.empty() ) { content = OFString( dateString.c_str() ).append( content ); } else { // This is a workaround for DICOM data that has an AquisitionTime but no AquisitionDate. // In this case, we use the current date. That's not really nice, but is absolutely OK // as we're only interested in the time anyways... OFString currentDate; DcmDate::getCurrentDate( currentDate ); content = currentDate.append( content ); } const OFCondition result = DcmDateTime::getOFDateTimeFromString( content, time ); return result.good(); } boost::posix_time::ptime ConvertOFDateTimeToPTime( const OFDateTime& time ) { const boost::gregorian::date boostDate( time.getDate().getYear(), time.getDate().getMonth(), time.getDate().getDay() ); const boost::posix_time::time_duration boostTime = boost::posix_time::hours( time.getTime().getHour() ) + boost::posix_time::minutes( time.getTime().getMinute() ) - + boost::posix_time::seconds( time.getTime().getSecond() ) + + boost::posix_time::seconds( static_cast(time.getTime().getSecond()) ) + boost::posix_time::milliseconds( time.getTime().getMilliSecond() ); boost::posix_time::ptime result( boostDate, boostTime ); return result; } OFDateTime GetLowerDateTime( const OFDateTime& time1, const OFDateTime& time2 ) { OFDateTime result = time1; if ( ( time2.getDate() < time1.getDate() ) || ( ( time2.getDate() == time1.getDate() ) && ( time2.getTime() < time1.getTime() ) ) ) { result = time2; } return result; } OFDateTime GetUpperDateTime( const OFDateTime& time1, const OFDateTime& time2 ) { OFDateTime result = time1; if ( ( time2.getDate() > time1.getDate() ) || ( ( time2.getDate() == time1.getDate() ) && ( time2.getTime() > time1.getTime() ) ) ) { result = time2; } return result; } double ComputeMiliSecDuration( const OFDateTime& start, const OFDateTime& stop ) { const boost::posix_time::ptime startTime = ConvertOFDateTimeToPTime( start ); const boost::posix_time::ptime stopTime = ConvertOFDateTimeToPTime( stop ); ::boost::posix_time::time_duration duration = stopTime - startTime; return duration.total_milliseconds(); } bool mitk::ITKDICOMSeriesReaderHelper::ExtractDateTimeBoundsAndTriggerOfTimeStep( const StringContainer& filenamesOfTimeStep, DateTimeBounds& bounds, TimeBounds& triggerBounds) { DICOMGDCMTagScanner::Pointer filescanner = DICOMGDCMTagScanner::New(); filescanner->SetInputFiles(filenamesOfTimeStep); filescanner->AddTag(AcquisitionDateTag); filescanner->AddTag(AcquisitionTimeTag); filescanner->AddTag(TriggerTimeTag); filescanner->Scan(); const DICOMDatasetAccessingImageFrameList frameList = filescanner->GetFrameInfoList(); bool result = false; bool firstAq = true; bool firstTr = true; triggerBounds = TimeBounds(0.0); for (auto pos = frameList.cbegin(); pos != frameList.cend(); ++pos) { const std::string aqDateStr = (*pos)->GetTagValueAsString(AcquisitionDateTag).value; const std::string aqTimeStr = (*pos)->GetTagValueAsString(AcquisitionTimeTag).value; const std::string triggerTimeStr = (*pos)->GetTagValueAsString(TriggerTimeTag).value; OFDateTime aqDateTime; const bool convertAqResult = ConvertDICOMDateTimeString(aqDateStr, aqTimeStr, aqDateTime); OFBool convertTriggerResult; mitk::ScalarType triggerTime = OFStandard::atof(triggerTimeStr.c_str(), &convertTriggerResult); if (convertAqResult) { if (firstAq) { bounds[0] = aqDateTime; bounds[1] = aqDateTime; firstAq = false; } else { bounds[0] = GetLowerDateTime(bounds[0], aqDateTime); bounds[1] = GetUpperDateTime(bounds[1], aqDateTime); } result = true; } if (convertTriggerResult) { if (firstTr) { triggerBounds[0] = triggerTime; triggerBounds[1] = triggerTime; firstTr = false; } else { triggerBounds[0] = std::min(triggerBounds[0], triggerTime); triggerBounds[1] = std::max(triggerBounds[1], triggerTime); } result = true; } } return result; }; bool mitk::ITKDICOMSeriesReaderHelper::ExtractTimeBoundsOfTimeStep( const StringContainer& filenamesOfTimeStep, TimeBounds& bounds, const OFDateTime& baselineDateTime ) { DateTimeBounds aqDTBounds; TimeBounds triggerBounds; bool result = ExtractDateTimeBoundsAndTriggerOfTimeStep(filenamesOfTimeStep, aqDTBounds, triggerBounds); mitk::ScalarType lowerBound = ComputeMiliSecDuration( baselineDateTime, aqDTBounds[0] ); mitk::ScalarType upperBound = ComputeMiliSecDuration( baselineDateTime, aqDTBounds[1] ); if ( lowerBound < mitk::eps || upperBound < mitk::eps ) { lowerBound = triggerBounds[0]; upperBound = triggerBounds[1]; } bounds[0] = lowerBound; bounds[1] = upperBound; return result; }; mitk::ITKDICOMSeriesReaderHelper::TimeBoundsList mitk::ITKDICOMSeriesReaderHelper::ExtractTimeBoundsOfTimeSteps( const StringContainerList& filenamesOfTimeSteps ) { TimeBoundsList result; OFDateTime baseLine; // extract the timebounds DateTimeBounds baselineDateTimeBounds; TimeBounds triggerBounds; auto pos = filenamesOfTimeSteps.cbegin(); ExtractDateTimeBoundsAndTriggerOfTimeStep(*pos, baselineDateTimeBounds, triggerBounds); baseLine = baselineDateTimeBounds[0]; // timebounds for baseline is 0 TimeBounds bounds( 0.0 ); result.push_back( bounds ); // iterate over the remaining timesteps for ( ++pos; pos != filenamesOfTimeSteps.cend(); ++pos ) { TimeBounds bounds( 0.0 ); TimeBounds dateTimeBounds; // extract the timebounds relative to the baseline if ( ExtractTimeBoundsOfTimeStep( *pos, dateTimeBounds, baseLine ) ) { bounds[0] = dateTimeBounds[0]; bounds[1] = dateTimeBounds[1]; } result.push_back( bounds ); } return result; }; mitk::TimeGeometry::Pointer mitk::ITKDICOMSeriesReaderHelper::GenerateTimeGeometry( const BaseGeometry* templateGeometry, const TimeBoundsList& boundsList ) { TimeGeometry::Pointer timeGeometry; double check = 0.0; const auto boundListSize = boundsList.size(); for ( std::size_t pos = 0; pos < boundListSize; ++pos ) { check += boundsList[pos][0]; check += boundsList[pos][1]; } if ( check < mitk::eps ) { // if all bounds are zero we assume that the bounds could not be correctly determined // and as a fallback generate a time geometry in the old mitk style ProportionalTimeGeometry::Pointer newTimeGeometry = ProportionalTimeGeometry::New(); newTimeGeometry->Initialize( templateGeometry, boundListSize ); timeGeometry = newTimeGeometry.GetPointer(); } else { ArbitraryTimeGeometry::Pointer newTimeGeometry = ArbitraryTimeGeometry::New(); newTimeGeometry->ClearAllGeometries(); newTimeGeometry->ReserveSpaceForGeometries( boundListSize ); for ( std::size_t pos = 0; pos < boundListSize; ++pos ) { TimeBounds bounds = boundsList[pos]; if ( pos + 1 < boundListSize ) { //Currently we do not explicitly support "gaps" in the time coverage //thus we set the max time bound of a time step to the min time bound //of its successor. bounds[1] = boundsList[pos + 1][0]; } newTimeGeometry->AppendNewTimeStepClone(templateGeometry, bounds[0], bounds[1]); } timeGeometry = newTimeGeometry.GetPointer(); } return timeGeometry; }; diff --git a/Modules/IGTBase/src/mitkRealTimeClock.cpp b/Modules/IGTBase/src/mitkRealTimeClock.cpp index 8e3a83d24e..ee2201f5c2 100644 --- a/Modules/IGTBase/src/mitkRealTimeClock.cpp +++ b/Modules/IGTBase/src/mitkRealTimeClock.cpp @@ -1,38 +1,38 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRealTimeClock.h" // check if MITK runs on a Windows-System #ifdef _WIN32 #include "mitkWindowsRealTimeClock.h" -#else // should be Linux or Mac OSX +#else // should be Linux or macOS #include "mitkLinuxRealTimeClock.h" #endif mitk::RealTimeClock::Pointer mitk::RealTimeClock::New() { mitk::RealTimeClock::Pointer smartPtr; #ifdef _WIN32 smartPtr = mitk::WindowsRealTimeClock::New(); #else smartPtr = mitk::LinuxRealTimeClock::New(); #endif return smartPtr; } diff --git a/Modules/Multilabel/mitkLabel.cpp b/Modules/Multilabel/mitkLabel.cpp index 2190301a80..e4045dbd12 100644 --- a/Modules/Multilabel/mitkLabel.cpp +++ b/Modules/Multilabel/mitkLabel.cpp @@ -1,301 +1,301 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkLabel.h" #include "itkProcessObject.h" #include "tinyxml.h" #include #include #include const mitk::Label::PixelType mitk::Label::MAX_LABEL_VALUE = std::numeric_limits::max(); mitk::Label::Label() : PropertyList() { if (GetProperty("locked") == nullptr) SetLocked(true); if (GetProperty("visible") == nullptr) SetVisible(true); if (GetProperty("opacity") == nullptr) SetOpacity(0.6); if (GetProperty("center.coordinates") == nullptr) { mitk::Point3D pnt; pnt.SetElement(0, 0); pnt.SetElement(1, 0); pnt.SetElement(2, 0); SetCenterOfMassCoordinates(pnt); } if (GetProperty("center.index") == nullptr) { mitk::Point3D pnt; pnt.SetElement(0, 0); pnt.SetElement(1, 0); pnt.SetElement(2, 0); SetCenterOfMassIndex(pnt); } if (GetProperty("color") == nullptr) { mitk::Color col; col.Set(0, 0, 0); SetColor(col); } if (GetProperty("name") == nullptr) SetName("noName!"); if (GetProperty("value") == nullptr) SetValue(0); if (GetProperty("layer") == nullptr) SetLayer(0); } mitk::Label::Label(const Label &other) : PropertyList(other) // copyconstructer of property List handles the coping action { auto *map = this->GetMap(); auto it = map->begin(); auto end = map->end(); for (; it != end; ++it) { itk::SimpleMemberCommand