ITK/Release 4/DICOM/DCMTK Integration CMakeList

From KitwarePublic
Jump to navigationJump to search

Experimenting with CMake to properly find the libraries

Please forgive the mess, but here is some experimental (incomplete) code to find the proper libraries and include files for an external software package (in this case DCMTK). Basically there are three scenarios:

  • Use System DCMTK from its installed location
  • Use System DCMTK from its build tree (where CMakeCache.txt is located)
  • Build DCMTK with ExternalProject_add() under part of the main project

There are a few key things to look for:

  • Setting the EP_BASE property on the directorty to control where the ExternalProject files are located
  • The process needed to look for the installed software compared to the build tree. Also, MSVC build trees have the <config> type as an extra level in the directory tree, so we have to do a little more scanning in that case.
  • How to call ExternalProject_add() to get the necessary files into our build tree, but not worry about installing to the system

The bugs have *NOT* been fully worked out.

cmake_minimum_required(VERSION 2.8)

project(ext2)
add_executable(ext2 Main.cpp)

include(ExternalProject)

# Set the ExternalProject (ep) base directory
# For each external project, the layout should be:
#  ${ep_base}/tmp/<name>
#  ${ep_base}/Stamp/<name>
#  ${ep_base}/Download/<name>
#  ${ep_base}/Source/<name>
#  ${ep_base}/Build/<name>
#  ${ep_base}/Install/<name>
SET(ep_base "${CMAKE_BINARY_DIR}/CMakeExternals")
set_property(DIRECTORY PROPERTY "EP_BASE" ${ep_base})

option(USE_SYSTEM_DCMTK "Should we use a version of DCMTK already installed on this machine?" ON)

# External build of DCMTK if desired
if(USE_SYSTEM_DCMTK)
  set(DCMTK_DIR CACHE PATH "Location of the /bin, /include and /lib directories for DCMTK")
  
  message("Checking if DCMTK_DIR (${DCMTK_DIR}) is a build tree")
  find_path(DCMTK_Local_Build CMakeCache.txt PATHS "${DCMTK_DIR}" NO_DEFAULT_PATH )
  if (DCMTK_Local_Build)
    load_cache("${DCMTK_Local_Build}/" READ_WITH_PREFIX "ITK_" DCMTK_SOURCE_DIR DCMTK_INCLUDE_DIR DCMTK_BINARY_DIR DCMTK_MODULES LIBXL_INCDIR)
    message("ITK_DCMTK_SOURCE_DIR is ${ITK_DCMTK_SOURCE_DIR}")
    message("ITK_DCMTK_INCLUDE_DIR is ${ITK_DCMTK_INCLUDE_DIR}")
    message("ITK_DCMTK_BINARY_DIR is ${ITK_DCMTK_BINARY_DIR}")
    message("ITK_DCMTK_DCMTK_MODULES is ${ITK_DCMTK_MODULES}")
  endif()

  if(WIN32)
    list(APPEND DCMTK_LIBRARIES netapi32 wsock32)
  endif()
else()
  ###
  ###  Build with:  cmake .. -DUSE_SYSTEM_DCMTK:BOOL=OFF
  ###

  # include(External_DCMTK)
  ExternalProject_Add( ITK_DCMTK
    GIT_REPOSITORY http://git.dcmtk.org/dcmtk.git
    INSTALL_COMMAND ""
    # INSTALL ITK_DCMTK_INSTALL
  )
  
  # WJR - I'm not sure if this is necessary...
  add_dependencies(ext2 ITK_DCMTK)
  
  
  message("Looking for ITK_DCMTK build directory ${ep_base}/Build/ITK_DCMTK")
  find_path(DCMTK_Local_Build CMakeCache.txt PATHS "${ep_base}/Build/ITK_DCMTK" NO_DEFAULT_PATH )
  if (DCMTK_Local_Build)
    message("Found ITK_DCMTK build directory ${DCMTK_Local_Build}")
    load_cache("${DCMTK_Local_Build}/" READ_WITH_PREFIX "ITK_" DCMTK_SOURCE_DIR DCMTK_INCLUDE_DIR DCMTK_BINARY_DIR DCMTK_MODULES LIBXL_INCDIR)
    message("ITK_DCMTK_SOURCE_DIR is ${ITK_DCMTK_SOURCE_DIR}")
    message("ITK_DCMTK_INCLUDE_DIR is ${ITK_DCMTK_INCLUDE_DIR}")
    message("ITK_DCMTK_BINARY_DIR is ${ITK_DCMTK_BINARY_DIR}")
    message("ITK_DCMTK_DCMTK_MODULES is ${ITK_DCMTK_MODULES}")

    # Save the directory
    set(DCMTK_DIR ${ITK_DCMTK_BINARY_DIR} CACHE PATH "Location of the /bin, /include and /lib directories for DCMTK")
  endif()

  # --------------------
  # Other possibilities:
  # --------------------
  # ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/support/zlib-1.2.5.tar.gz
  # ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/support/tiff-3.9.4.tar.gz
  # ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/support/libpng-1.4.3.tar.gz
  # ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/support/libxml2-2.7.7.tar.gz
  # ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/support/libiconv-1.13.1.tar.gz
endif()

message("ep_base is ${ep_base}")

message("DCMTK_FOUND is ${DCMTK_FOUND}")

message("DCMTK_DIR is ${DCMTK_DIR}")
message("DCMTK_INCLUDE_DIRS is ${DCMTK_INCLUDE_DIRS}")


####################################################################
####################################################################


message("Looking for DCMTK libraries for linking")

  foreach(lib
      charls
      dcmdata
      dcmdsig
      dcmimage
      dcmimgle
      dcmjpeg
      dcmjpls
      dcmnet
      dcmpstat
      dcmqrdb
      dcmsr
      dcmtls
      dcmwlm
      i2d
      ijg12
      ijg16
      ijg8
      oflog
      ofstd )

    find_library(DCMTK_${lib}_LIBRARY
      ${lib}
      PATHS
      ${DCMTK_DIR}/lib               # Typical for INSTALL directory
      ${DCMTK_DIR}/${lib}/libsrc     # External build tree (for most libs)
      ${DCMTK_DIR}/dcmsign/libsrc    # External build tree (for dcmdsig, dirname does not match libname)
      ${DCMTK_DIR}/dcmjpeg/lib${lib} # External build tree (ijg8, ijg12, ijg16)
      ${DCMTK_DIR}/dcmdata/lib${lib} # External build tree (i2d)
      ${DCMTK_DIR}/dcmjpls/lib${lib} # External build tree (charls)
    )

    mark_as_advanced(DCMTK_${lib}_LIBRARY)

    if(DCMTK_${lib}_LIBRARY)
      list(APPEND DCMTK_LIBRARIES ${DCMTK_${lib}_LIBRARY})
    elseif(CMAKE_CONFIGURATION_TYPES)
      # Library was not found above, look under each build type
      foreach(configtype ${CMAKE_CONFIGURATION_TYPES})
        find_library(DCMTK_${lib}_LIBRARY_${configtype}
          ${lib}
          PATHS
          ${DCMTK_DIR}/${lib}/libsrc/${configtype}     # External build tree (for most libs)
          ${DCMTK_DIR}/dcmsign/libsrc/${configtype}    # External build tree (for dcmdsig, dirname does not match libname)
          ${DCMTK_DIR}/dcmjpeg/lib${lib}/${configtype} # External build tree (ijg8, ijg12, ijg16)
          ${DCMTK_DIR}/dcmdata/lib${lib}/${configtype} # External build tree (i2d)
          ${DCMTK_DIR}/dcmjpls/lib${lib}/${configtype} # External build tree (charls)
        )
        
        if (DCMTK_${lib}_LIBRARY_${configtype})
          # Check to see if we've already added the library
          list(FIND DCMTK_LIBRARIES DCMTK_${lib}_IMP list_index)
          if ( list_index EQUAL "-1" )
            # Create a new entry
            message("Creating library DCMTK_${lib}_LIBRARY")
            add_library(DCMTK_${lib}_IMP STATIC IMPORTED)
            list(APPEND DCMTK_LIBRARIES DCMTK_${lib}_IMP)
          endif()
          
          # Now set the config-specific location properties
          string(TOUPPER ${configtype} UPPER_CONFIG_TYPE)
          message("Setting DCMTK_${lib}_IMP PROPERTY IMPORTED_LOCATION_${UPPER_CONFIG_TYPE} = ${DCMTK_${lib}_LIBRARY_${configtype}}")
          set_property(TARGET DCMTK_${lib}_IMP PROPERTY IMPORTED_LOCATION_${UPPER_CONFIG_TYPE} ${DCMTK_${lib}_LIBRARY_${configtype}})
          
          
        endif()
      endforeach()
    endif()
  endforeach()
  
message("DCMTK_LIBRARIES is ${DCMTK_LIBRARIES}")

target_link_libraries(ext2 ${DCMTK_LIBRARIES})



######################################
# Search for DCMTK Include Directories
######################################
if(DCMTK_DIR)
  set(DCMTK_config_TEST_HEADER osconfig.h)
  set(DCMTK_dcmdata_TEST_HEADER dctypes.h)
  set(DCMTK_dcmimage_TEST_HEADER dicoimg.h)
  set(DCMTK_dcmimgle_TEST_HEADER dcmimage.h)
  set(DCMTK_dcmjpeg_TEST_HEADER djdecode.h)
  set(DCMTK_dcmnet_TEST_HEADER assoc.h)
  set(DCMTK_dcmpstat_TEST_HEADER dcmpstat.h)
  set(DCMTK_dcmqrdb_TEST_HEADER dcmqrdba.h)
  set(DCMTK_dcmsign_TEST_HEADER sicert.h)
  set(DCMTK_dcmsr_TEST_HEADER dsrtree.h)
  set(DCMTK_dcmtls_TEST_HEADER tlslayer.h)
  set(DCMTK_ofstd_TEST_HEADER ofstdinc.h)

  foreach(dir
      config
      dcmdata
      dcmimage
      dcmimgle
      dcmjpeg
      dcmnet
      dcmpstat
      dcmqrdb
      dcmsign
      dcmsr
      dcmtls
      ofstd)
    find_path(DCMTK_${dir}_INCLUDE_DIR
      dcmtk/${dir}/${DCMTK_${dir}_TEST_HEADER}
      PATHS
      ${DCMTK_DIR}/include                        # Installed Path
      ${ITK_DCMTK_SOURCE_DIR}/${dir}/include      # Source for the local build
      ${ep_base}/Source/ITK_DCMTK/${dir}/include  # When built as ExternalProject_add()
      )

    mark_as_advanced(DCMTK_${dir}_INCLUDE_DIR)
    message("Looking for file ${DCMTK_DIR}/dcmtk/${dir}/${DCMTK_${dir}_TEST_HEADER}")
    message("DCMTK_${dir}_INCLUDE_DIR is ${DCMTK_${dir}_INCLUDE_DIR}")

    if(DCMTK_${dir}_INCLUDE_DIR)
      list(APPEND
        DCMTK_INCLUDE_DIRS
        ${DCMTK_${dir}_INCLUDE_DIR})
    endif()
  endforeach()

  # Clean up the include list
  list(REMOVE_DUPLICATES DCMTK_INCLUDE_DIRS)
  
  # Add to our project
  include_directories(${DCMTK_INCLUDE_DIRS})
endif()