#!
#! @ingroup group_sdk_cmake_camitk
#!
#! macro camitk_library simplifies the declaration of a library inside CamiTK
#! and is to be used for all inner project libraries
#!
#! The name of the CEP library is automatically deduced from the name of the directory, 
#! unless LIBNAME is provided
#!
#! \note 
#! To be more precise, after the execution of this macro, the variable `LIBRARY_TARGET_NAME`
#! holds the name of the CMake target produced by this macro.
#! The target name itself is equals to `library-name, where `name` is the name of the current 
#! folder in lowercase unless `LIBNAME` is provided.
#!
#! If the library is compiled as shared, it adds the needed library properties
#! If it needs relocation flag fPIC (on some plateforms), this macro should determine
#! if this is the case and specify this flag.
#!
#! usage:
#! \code
#! camitk_library(
#!     SHARED|STATIC
#!     SOURCES source1.cpp source1.h...
#!     [LIBNAME libname]
#!     [OUTPUT_SUBDIRECTORY actions|components|viewers]
#!     [PUBLIC]
#!     [NEEDS_CEP_LIBRARIES lib1 lib2...]
#!     [NEEDS_ITK]
#!     [NEEDS_LIBXML2]
#!     [NEEDS_XERCESC]
#!     [NEEDS_XSD]
#!     [NEEDS_QT]
#!     [NEEDS_CAMITKCORE]
#!     [DEFINES flag1 flag2 ...]
#!     [EXTERNAL_LIBRARIES lib1 lib2... ]
#!     [INCLUDE_DIRECTORIES dir1 dir2...]
#!     [LINK_DIRECTORIES dir1 dir2...]
#!     [HEADERS_TO_INSTALL]
#!     [INSTALL_NO_HEADERS]
#!     [CEP_NAME]
#!     [DESCRIPTION]
#!     [EXTRA_TRANSLATE_LANGUAGE lang1 lang2...]
#!     [CXX_FLAGS flag1 flag2 ...]
#!
#! )
#! \endcode
#!
#! \param SHARED                        optional, if the library should be compiled as shared
#! \param OUTPUT_SUBDIRECTORY       optional, added to the output directory (for private lib dir, e.g. "actions")
#! \param SOURCES                       all sources to be included in the library
#! \param INCLUDE_DIRECTORIES           all needed include directories (${CMAKE_CURRENT_SOURCE_DIR} 
#!                                        and ${CMAKE_CURRENT_BINARY_DIR} are automatically added)
#! \param EXTERNAL_LIBRARIES            all the libraries to be used during the link (shared or static)
#! \param NEEDS_CEP_LIBRARIES           all the libraries to be used during the link (shared or static)
#! \param NEEDS_ITK                     add this if your component needs ITK.
#! \param NEEDS_LIBXML2                 add this if the CEP library needs libxml2
#! \param NEEDS_XERCESC                 add this if your action / component needs XercesC library
#! \param NEEDS_XSD                     add this if your action needs Codesynthesis xsd cxx (xml schema compiler)
#! \param NEEDS_QT                      add this if your library depends on Qt 5.x
#! \param NEEDS_CAMITKCORE              add this if your library depends on CamiTK (implies NEEDS_QT)
#! \param LIBNAME                       force the CEP library name to be different from the directory it is in
#! \param LINK_DIRECTORIES              additional directories to use in link_directories(...)
#! \param DEFINES                       list of define flags to add at compilation time
#! \param PUBLIC                        The library is a public library that has to be loaded directly by the operating system.
#!                                        It is generally only needed for SDK library. A public library should not be installed in the
#!                                        lib/${CAMITK_SHORT_VERSION_STRING} but directly in lib/ (on Unix/MacOS) or bin/ (on windows)
#! \param HEADERS_TO_INSTALL            list of header files to install. File would be copied at build and installation time
#!                                        in the ./include/libraries/library-name subdirectory.
#!                                        Note that, if no header files are provided, all header files (*.h) will be install.
#! \param INSTALL_NO_HEADERS            No headers will be installed (do not use with HEADERS_TO_INSTALL)
#! \param CEP_NAME                      specify the CEP_NAME, which is used to categorized the extension for packaging purpose
#!                                        No CEP_NAME provided will result in default categorization (generic extension).
#! \param DESCRIPTION                   Simple description of the extension. Used for packaging presentation for instance.
#! \param EXTRA_TRANSLATE_LANGUAGE      Additional extra language to translate the application
#! \param CXX_FLAGS                     list of compiler flags to add (such as warning levels (-Wall ...)).
#!

macro(camitk_library)

    # Instruct CMake to run moc automatically when needed.
    set(CMAKE_AUTOMOC ON)

    #########################################################################
    #                                                                       #
    #   ARGUMENTS PARSING                                                   #
    #                                                                       #
    #   * Use a macro to create the CMAKE variables according to the        #
    #     provided options as input.                                        #
    #                                                                       #
    #########################################################################

    get_directory_name(${CMAKE_CURRENT_SOURCE_DIR} DEFAULT_LIBRARY_NAME)

    set(options SHARED STATIC NEEDS_CAMITKCORE NEEDS_ITK NEEDS_LIBXML2 NEEDS_XERCESC NEEDS_XSD NEEDS_QT PUBLIC INSTALL_NO_HEADERS)
    set(oneValueArgs LIBNAME CEP_NAME DESCRIPTION OUTPUT_SUBDIRECTORY)
    set(multiValueArgs SOURCES NEEDS_CEP_LIBRARIES EXTERNAL_LIBRARIES INCLUDE_DIRECTORIES DEFINES LINK_DIRECTORIES HEADERS_TO_INSTALL EXTRA_TRANSLATE_LANGUAGE CXX_FLAGS)
    cmake_parse_arguments(${DEFAULT_LIBRARY_NAME_CMAKE} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
    
    #########################################################################
    #                                                                       #
    #   Consider moc sources files                                          #
    #                                                                       #
    #   * if you use Q_OBJECT in your classes                               #
    #                                                                       #
    #########################################################################
    file(GLOB_RECURSE MOC_SRCS ${CMAKE_CURRENT_BINARY_DIR}/moc_*.cxx)
    set(${DEFAULT_LIBRARY_NAME_CMAKE}_SOURCES ${${DEFAULT_LIBRARY_NAME_CMAKE}_SOURCES} ${MOC_SRCS})


    #########################################################################
    #                                                                       #
    #   CREATE CMAKE VARIABLES                                              #
    #                                                                       #
    #   * Create required and useful CMake variables for the macro          #
    #                                                                       #
    #########################################################################

    # TARGET NAME
    # The target name is composed of the following: library-name
    # * library is the suffix
    # * name is deduced from the input folder containing the calling CMakeLists.txt file of the extension.
    # "-" is replaced by "_" if configuring for packaging with NSIS, the program to create a Windows installer.
    if (PACKAGING_NSIS)
        if ("${${DEFAULT_LIBRARY_NAME_CMAKE}_LIBNAME}" STREQUAL "")
            set(LIBRARY_TARGET_NAME library_${DEFAULT_LIBRARY_NAME})
        else()
            set(LIBRARY_TARGET_NAME library_${${DEFAULT_LIBRARY_NAME_CMAKE}_LIBNAME})
        endif()
    else()
        if ("${${DEFAULT_LIBRARY_NAME_CMAKE}_LIBNAME}" STREQUAL "")
            set(LIBRARY_TARGET_NAME library-${DEFAULT_LIBRARY_NAME})
        else()
            set(LIBRARY_TARGET_NAME library-${${DEFAULT_LIBRARY_NAME_CMAKE}_LIBNAME})
        endif()
    endif()

    # BASIC DIRECTORIES
    include_directories(${CMAKE_CURRENT_SOURCE_DIR})
    include_directories(${CMAKE_CURRENT_BINARY_DIR})
    
    #########################################################################
    #                                                                       #
    #   Consider moc sources files                                          #
    #                                                                       #
    #   * if you use Q_OBJECT in your classes                               #
    #                                                                       #
    #########################################################################
    #file(GLOB_RECURSE MOC_SRCS ${CMAKE_CURRENT_BINARY_DIR}/moc_*.cxx ${CMAKE_CURRENT_BINARY_DIR}/moc_*.cpp)
    #set(${DEFAULT_LIBRARY_NAME_CMAKE}_SOURCES ${${DEFAULT_LIBRARY_NAME_CMAKE}_SOURCES} ${MOC_SRCS})

    #########################################################################
    #                                                                       #
    #   INCLUDE DIRECTORIES                                                 #
    #                                                                       #
    #   * Include library directories where to look for header files        #
    #   * Include also additional user provided directories                 #
    #   * These directories are used for compilation step                   #
    #                                                                       #
    #########################################################################

    # BASIC DIRECTORIES
    include_directories(${CMAKE_CURRENT_SOURCE_DIR})
    include_directories(${CMAKE_CURRENT_BINARY_DIR})
    include_directories(${CAMITK_INCLUDE_DIRECTORIES})

    # USER PROVIDED ADDITIONAL DIRECTORIEs
    include_directories(${${DEFAULT_LIBRARY_NAME_CMAKE}_INCLUDE_DIRECTORIES})
    
    
    
    #########################################################################
    #                                                                       #
    #   GROUP RESOURCES                                                     #
    #                                                                       #
    #   * On Windows, Visual Studio, group .moc and .ui files               #
    #     in subdirectories                                                 # 
    #                                                                       #
    #########################################################################
    if(MSVC)
        source_group("Header Files\\UI Files" REGULAR_EXPRESSION "^ui_.*")
        source_group("Source Files\\Resources Files" REGULAR_EXPRESSION "^qrc_.*")
        source_group("Source Files\\Resources Files" REGULAR_EXPRESSION ".*\\.qrc$")
        source_group("UI Files" REGULAR_EXPRESSION ".*\\.ui$")
        source_group("Source Files\\Moc Files" REGULAR_EXPRESSION "^moc_.*")
        source_group("Source Files\\CLI Files" REGULAR_EXPRESSION "^CommandLineOptions.*")
    endif()



    #########################################################################
    #                                                                       #
    #   ADDITIONAL KNOWN LIBRARY DEPENDENCIES                               #
    #                                                                       #
    #   * Look for specific library needed                                  #
    #   * Specific libraries are specified as option with the               #
    #     NEEDS_LIBRARY syntax (see macro syntax for more options)          #
    #   * Backward compatibility : Warn user if using old NEEDS_TOOL syntax #
    #                                                                       #
    #########################################################################

    # Looking for ITK
    set(ITK_LIBRARIES "")
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_ITK)
        find_package(ITK REQUIRED)
            if(ITK_FOUND)
                include(${ITK_USE_FILE})
                set(ITK_VERSION ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}.${ITK_VERSION_PATCH}) #ITK_VERSION is not always set
                set(CAMITK_ITK_VERSION ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR})
                message(STATUS "${LIBRARY_TARGET_NAME}: Found ITK version ${ITK_VERSION}")
                set(CAMITK_ITK_LIBRARIES ${ITK_LIBRARIES})
            else()
                message(FATAL_ERROR "ITK not found but required by ${LIBRARY_TARGET_NAME}")
            endif()
    endif()

    # LIBXML2
    set(LIBXML2_LIBRARY "")
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_LIBXML2)
        # LibXml2 is required
        find_package(Xml2)
        if (LIBXML2_FOUND)
            add_definitions(${LIBXML2_DEFINITIONS})
            include_directories(${LIBXML2_INCLUDE_DIR})
            set(LIBXML2_LIBRARY ${LIBXML2_LIBRARIES})
        else()
            # most probably win32 or crosscompiling
            message(WARNING "${LIBRARY_TARGET_NAME}: libxml2 required")
        endif()
    endif()

    # XERCES-C
    set(XERCESC_LIBRARIES)
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_XERCESC)
        # XercesC is required
        find_package(XercesC REQUIRED)
        if (XERCESC_FOUND)
            include_directories(${XERCESC_INCLUDE_DIR})
            set(XERCESC_LIBRARIES ${XERCESC_LIBRARY})
        else()
            # most probably win32 or crosscompiling
            message(FATAL_ERROR "${LIBRARY_TARGET_NAME}: xerces-c required. Please provide Xerces-C path.")
        endif()
    endif()

    # XSD
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_XSD)
        # XercesC is required
        find_package(XercesC REQUIRED)
        if (XERCESC_FOUND)
            include_directories(${XERCESC_INCLUDE_DIR})
            set(XERCESC_LIBRARIES ${XERCESC_LIBRARY})
            find_package(XSD REQUIRED)
            include_directories(${XSD_INCLUDE_DIR})
        else()
            # most probably win32 or crosscompiling
            message(FATAL_ERROR "${LIBRARY_TARGET_NAME}: xerces-c required because of XSD cxx, please set XERCESC_INCLUDE_DIR")
        endif()
        # with C++11 MSVC requires explicit XSD_CXX11 flag definition
        add_definitions(-DXSD_CXX11)
    endif()

    # If Qt is needed, add it to the target link library
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_QT OR ${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_CAMITKCORE)
        set(${DEFAULT_LIBRARY_NAME_CMAKE}_QT_LIBRARIES ${CAMITK_QT_LIBRARIES})
    else()
        unset(${DEFAULT_LIBRARY_NAME_CMAKE}_QT_LIBRARIES)
    endif()


    # EXTERNAL DEPENDENCIES
    set(LINKER_EXTERNAL_LIBRARIES)
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_EXTERNAL_LIBRARIES)
        foreach(EXTERNAL_LIBRARY ${${DEFAULT_LIBRARY_NAME_CMAKE}_EXTERNAL_LIBRARIES})
            if (MSVC)
                set(LINKER_EXTERNAL_LIBRARIES ${LINKER_EXTERNAL_LIBRARIES}
                                       debug ${EXTERNAL_LIBRARY}${CAMITK_DEBUG_POSTFIX}.lib
                                       optimized ${EXTERNAL_LIBRARY}.lib
                )
                message(STATUS "LINKER_EXTERNAL_LIBRARIES = ${LINKER_EXTERNAL_LIBRARIES}")
            else()
                set(LINKER_EXTERNAL_LIBRARIES ${LINKER_EXTERNAL_LIBRARIES} ${EXTERNAL_LIBRARY})
            endif()
        endforeach()
    endif()



    #########################################################################
    #                                                                       #
    #   LINK DIRECTORIES                                                    #
    #                                                                       #
    #   * Link directories are used to indicate the compiler where          #
    #     to look for folder containing libraries to link with.             #
    #   * Additional link directories provided by the user                  #
    #                                                                       #
    #########################################################################
    # CAMITK BASIC LIB DIRECTORIES
    link_directories(${CAMITK_LINK_DIRECTORIES})

    # ADDITIONAL LINK DIRECTORIES
    if (NOT "${${DEFAULT_LIBRARY_NAME_CMAKE}_LINK_DIRECTORIES}" STREQUAL "")
        link_directories(${${DEFAULT_LIBRARY_NAME_CMAKE}_LINK_DIRECTORIES})
    endif()



    #########################################################################
    #                                                                       #
    #   TARGET COMPILATION  DEFINITION                                      #
    #                                                                       #
    #   * Additional sources files to consider at compilation (.cpp)        #
    #   * CMake project target definition  depending on library type        #
    #     public / private                                                  #
    #                                                                       #
    #########################################################################
    # CMAKE TARGET DEFINITION DEPENDENDING ON THE LIBRARY TYPE (SHARED or STATIC)
    if (${DEFAULT_LIBRARY_NAME_CMAKE}_SHARED) # shared library
        message(STATUS "Building shared library: ${LIBRARY_TARGET_NAME}")
        add_library(${LIBRARY_TARGET_NAME} SHARED ${${DEFAULT_LIBRARY_NAME_CMAKE}_SOURCES})
        # prepare the library specific info (SONAME...)
        set(${LIBRARY_TARGET_NAME}_LIBRARY_PROPERTIES ${${LIBRARY_TARGET_NAME}_LIBRARY_PROPERTIES}
            VERSION   "${CAMITK_VERSION_MAJOR}.${CAMITK_VERSION_MINOR}.${CAMITK_VERSION_PATCH}"
            SOVERSION "${CAMITK_VERSION_MAJOR}"
        )
        # 
        set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES ${${LIBRARY_TARGET_NAME}_LIBRARY_PROPERTIES} LINK_INTERFACE_LIBRARIES "")
    elseif (${DEFAULT_LIBRARY_NAME_CMAKE}_STATIC) # static library
        message(STATUS "Building static library: ${LIBRARY_TARGET_NAME}")
        add_library(${LIBRARY_TARGET_NAME} STATIC ${${DEFAULT_LIBRARY_NAME_CMAKE}_SOURCES})        
    else()
        message(FATAL_ERROR "In adding static library ${LIBRARY_TARGET_NAME}.\n   Please specify the library type: SHARED or STATIC")
    endif()

        
    #########################################################################
    #                                                                       #
    #   CAMITK CORE LIBRARIES                                               #
    #                                                                       #
    #   * If a library build on top of CamiTKCore add required dependencies #
    #                                                                       #
    #########################################################################
    set(LIBRARIES_DEPENDENCY_LIST "") #use for generating the project.xml file
    # Check if camitk core is needed
    # CAMITK_CORE_LIBRARIES = camitkcore, CAMITK_LIBRARIES = VTK, qtpropertybrowser and extensionmanager
    if (${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_CAMITKCORE)
        # include directories from build, camitk (local or global install).
        include_directories(${CAMITK_BUILD_INCLUDE_DIR}/libraries/${CAMITK_CORE_LIB_NAME})
        include_directories(${CAMITK_INCLUDE_DIR}/libraries/${CAMITK_CORE_LIB_NAME})
        include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../libraries/${CAMITK_CORE_LIB_NAME})
        set(CAMITK_LIBRARIES_DEPENDENCIES ${CAMITK_CORE_LIBRARIES} ${CAMITK_LIBRARIES})
        if (TARGET library-${CAMITK_CORE_LIB_NAME})
            add_dependencies(${LIBRARY_TARGET_NAME} library-${CAMITK_CORE_LIB_NAME})
        endif()
        list(APPEND LIBRARIES_DEPENDENCY_LIST library-${CAMITK_CORE_LIB_NAME})
    endif()


    ####################################################################"#####
    #                                                                        #
    #   CAMITK LIBRARIES DEPENDENCIES                                        #
    #                                                                        #
    #   * Add in this section library dependencies to other camitk libraries #
    #     to keep a correct build order (NEEDS_CEP_LIBRARIES).               #
    #                                                                        #
    ##########################################################################

    # CEP LIBRARIES DEPENDENCIES
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_CEP_LIBRARIES)
        set(CEP_LIBRARIES "")
        foreach(CEP_LIBRARY_NEEDED ${${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_CEP_LIBRARIES})
            # include directories from build, camitk (local or global install).
            include_directories(${CAMITK_BUILD_INCLUDE_DIR}/libraries/${CEP_LIBRARY_NEEDED})
            include_directories(${CAMITK_INCLUDE_DIR}/libraries/${CEP_LIBRARY_NEEDED})
            include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../libraries/${CEP_LIBRARY_NEEDED})
            # file dependency
            if (MSVC)
                list(APPEND CEP_LIBRARIES debug  ${CEP_LIBRARY_NEEDED}${CAMITK_DEBUG_POSTFIX}.lib
                                          optimized ${CEP_LIBRARY_NEEDED}
                )
            else()
                list(APPEND CEP_LIBRARIES ${CEP_LIBRARY_NEEDED})
            endif()
            # CMake / CDash dependencies
            if(PACKAGING_NSIS)
                if (EXISTS ${CAMITK_BUILD_INCLUDE_DIR}/libraries/${CEP_LIBRARY_NEEDED} AND NOT TARGET library_${CEP_LIBRARY_NEEDED})
                        message(STATUS "Importing target library_${CEP_LIBRARY_NEEDED}")
                        add_library(library_${CEP_LIBRARY_NEEDED} INTERFACE IMPORTED)
                endif()
                # now add the dependency
                add_dependencies(${LIBRARY_TARGET_NAME} library_${CEP_LIBRARY_NEEDED}) 
            else()
                if (NOT TARGET library-${CEP_LIBRARY_NEEDED})
                        message(STATUS "Importing target library-${CEP_LIBRARY_NEEDED}")
                        add_library(library-${CEP_LIBRARY_NEEDED} INTERFACE IMPORTED)
                endif()
                add_dependencies(${LIBRARY_TARGET_NAME} library-${CEP_LIBRARY_NEEDED})
                list(APPEND LIBRARIES_DEPENDENCY_LIST library-${CEP_LIBRARY_NEEDED})
            endif()
        endforeach()
    endif()



    #########################################################################
    #                                                                       #
    #   LINKING                                                             #
    #                                                                       #
    #   * Linking is the last stage of compilation                          #
    #   * Indicate what libraries to use for linking the target             #
    #                                                                       #
    #########################################################################
    # LINKING LIBRARIES
    target_link_libraries(${LIBRARY_TARGET_NAME} PRIVATE ${CAMITK_LIBRARIES_DEPENDENCIES} ${CEP_LIBRARIES} ${LINKER_EXTERNAL_LIBRARIES} ${LIBXML2_LIBRARY} ${CAMITK_ITK_LIBRARIES} ${XERCESC_LIBRARIES} ${${DEFAULT_LIBRARY_NAME_CMAKE}_QT_LIBRARIES})

    if (${DEFAULT_LIBRARY_NAME_CMAKE}_NEEDS_CAMITKCORE)
        # for VTK9, see https://docs.vtk.org/en/latest/advanced/migration_guides/ModuleMigration.html
        if("${VTK_VERSION}" VERSION_GREATER_EQUAL 9.0)
            vtk_module_autoinit(
                TARGETS ${LIBRARY_TARGET_NAME}
                MODULES ${CAMITK_VTK_LIBRARIES})
        endif()
    endif()


    #########################################################################
    #                                                                       #
    #   OUTPUT                                                              #
    #                                                                       #
    #   * Define the output directory (location and name)                   #
    #   * Define the output name of the library                             #
    #   * Add ${CAMITK_DEBUG_POSTFIX} suffix to Debug MSVC built libraries  #
    #                                                                       #
    #########################################################################

    # OUTPUT DIRECTORY LOCATION and NAME depending on the type of the library (PUBLIC or PRIVATE)
    # DEBGUG POSTFIX FOR MSVC
    if (${DEFAULT_LIBRARY_NAME_CMAKE}_PUBLIC) # Public library => build in the bin folder
        if (MSVC)
            # With Visual Studio, public libraries are built in build\bin directory, else it's in build\lib
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CAMITK_BUILD_BIN_DIR}
                                                                    LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_BIN_DIR}
                                                                    LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_BIN_DIR}
            )
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CAMITK_BUILD_BIN_DIR}
                                                                    RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_BIN_DIR}
                                                                    RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_BIN_DIR}
            )
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CAMITK_BUILD_BIN_DIR}
                                                                    ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_BIN_DIR}
                                                                    ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_BIN_DIR}
            )
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES DEBUG_POSTFIX ${CAMITK_DEBUG_POSTFIX})
        else()
            # for xcode generation, the <CONFIG> postfix should also be used, but "a la" UNIX (lib in /lib etc...)
            # no need to check the generator with if(CMAKE_GENERATOR STREQUAL Xcode), as the <CONFIG> postfix should
            # not affect the other unix generators
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CAMITK_BUILD_PUBLIC_LIB_DIR}
                                                                    LIBRARY_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_PUBLIC_LIB_DIR}
                                                                    LIBRARY_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_PUBLIC_LIB_DIR}
            )
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CAMITK_BUILD_PUBLIC_LIB_DIR}
                                                                    RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_PUBLIC_LIB_DIR}
                                                                    RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_PUBLIC_LIB_DIR}
            )
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CAMITK_BUILD_PUBLIC_LIB_DIR}
                                                                    ARCHIVE_OUTPUT_DIRECTORY_DEBUG ${CAMITK_BUILD_PUBLIC_LIB_DIR}
                                                                    ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${CAMITK_BUILD_PUBLIC_LIB_DIR}
            )
        endif()
    else() # Private library => build in lib folder
        if (MSVC)
            set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES DEBUG_POSTFIX ${CAMITK_DEBUG_POSTFIX})
        endif()
        # add OUTPUT_SUBDIRECTORY if provided
        if (${DEFAULT_LIBRARY_NAME_CMAKE}_OUTPUT_SUBDIRECTORY)
            set(OUTPUT_DIRECTORY ${CAMITK_BUILD_PRIVATE_LIB_DIR}/${${DEFAULT_LIBRARY_NAME_CMAKE}_OUTPUT_SUBDIRECTORY})
        else()
            set(OUTPUT_DIRECTORY ${CAMITK_BUILD_PRIVATE_LIB_DIR})
        endif()
        set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY         ${OUTPUT_DIRECTORY}
                                                                LIBRARY_OUTPUT_DIRECTORY_DEBUG   ${OUTPUT_DIRECTORY}
                                                                LIBRARY_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY}
        )
        set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY         ${OUTPUT_DIRECTORY}
                                                                RUNTIME_OUTPUT_DIRECTORY_DEBUG   ${OUTPUT_DIRECTORY}
                                                                RUNTIME_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY}
        )
        set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES ARCHIVE_OUTPUT_DIRECTORY         ${OUTPUT_DIRECTORY}
                                                                ARCHIVE_OUTPUT_DIRECTORY_DEBUG   ${OUTPUT_DIRECTORY}
                                                                ARCHIVE_OUTPUT_DIRECTORY_RELEASE ${OUTPUT_DIRECTORY}
        )
    endif()

    # OUTPUT LIBRARY NAME (without the prefix "library-").
    string(REGEX REPLACE "^library_|^library-" "" LIBRARY_NAME "${LIBRARY_TARGET_NAME}")
    set_target_properties(${LIBRARY_TARGET_NAME}
                           PROPERTIES OUTPUT_NAME ${LIBRARY_NAME}
    )



    #########################################################################
    #                                                                       #
    #   COMPILATION FLAG                                                    #
    #                                                                       #
    #   * Flags are options to give to the compiler                         #
    #   * Add user input flags                                              #
    #   * Add platform specific flags                                       #
    #                                                                       #
    #########################################################################

    # USER INPUT COMPILER FLAG
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_DEFINES)
      foreach (FLAG ${${DEFAULT_LIBRARY_NAME_CMAKE}_DEFINES})
        add_definitions(-D${FLAG})
      endforeach()
    endif()

    # USER INPUT CUSTOM COMPILER FLAG
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_CXX_FLAGS)
      foreach (FLAG ${${DEFAULT_LIBRARY_NAME_CMAKE}_CXX_FLAGS})
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}")
      endforeach()
    endif()

    # PLATFORM SPECIFIC COMPILER FLAG
    # 64bits and other platform with relocation needs -fPIC
    include(TestCXXAcceptsFlag)
    check_cxx_accepts_flag(-fPIC FPIC_FLAG_ACCEPTED)
    # no need to add -fPIC on mingw, otherwise it generates a warning: -fPIC ignored for target (all code is position independent) [enabled by default]
    # msvc is also accepting the flag, but then produce warning D9002 : ignoring unknown option '-fPIC'   cl
    if(FPIC_FLAG_ACCEPTED AND NOT WIN32)
        set_property(TARGET ${LIBRARY_TARGET_NAME} APPEND PROPERTY COMPILE_FLAGS -fPIC)
    endif()



    #########################################################################
    #                                                                       #
    #   INSTALLATION                                                        #
    #                                                                       #
    #   * When installing the project, header files (.h) and test data are  #
    #     copied into an installation folder to determine.                  #
    #   * Indicate in this section, where to install your project and which #
    #     files to copy into that folder (during local/global installation) #
    #                                                                       #
    #########################################################################

    # FOLDER INSTALLATION
    # Indicate where to install the library, dependending on its property (public / private)
    message(STATUS "Installing library ${LIBRARY_TARGET_NAME} in ${CMAKE_INSTALL_LIBDIR}")
    if (${DEFAULT_LIBRARY_NAME_CMAKE}_PUBLIC) # public library   
        if(WIN32)
            # public library -> install in bin folder
            install(TARGETS ${LIBRARY_TARGET_NAME}
                    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
                    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
                    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CAMITK_SHORT_VERSION_STRING}
                    COMPONENT ${LIBRARY_NAME_INSTALL}
                    )
        else()
            # other public libraries -> install in lib folder
            install(TARGETS ${LIBRARY_TARGET_NAME}
                    RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
                    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
                    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
                    COMPONENT ${LIBRARY_NAME_INSTALL}
                    )
        endif()
    else()
         # private library -> install in lib/camitk-version folder
            install(TARGETS ${LIBRARY_TARGET_NAME}
                RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CAMITK_SHORT_VERSION_STRING}
                LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CAMITK_SHORT_VERSION_STRING}
                ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/${CAMITK_SHORT_VERSION_STRING}
                COMPONENT ${LIBRARY_NAME_INSTALL}
            )
    endif()

    # HEADER FILES (.h) INSTALLATION
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_HEADERS_TO_INSTALL)
        # If headers information provided for installation => install them
        export_headers(${${DEFAULT_LIBRARY_NAME_CMAKE}_HEADERS_TO_INSTALL} COMPONENT ${LIBRARY_TARGET_NAME} GROUP libraries)
    else()
        if (NOT ${DEFAULT_LIBRARY_NAME_CMAKE}_INSTALL_NO_HEADERS)
            # By default, install all headers and keep include directories structure
            camitk_install_all_headers(COMPONENT ${LIBRARY_TARGET_NAME} GROUP libraries)
        endif()
    endif()

    #########################################################################
    #                                                                       #
    #   CDASH SUBPROJECT DESCRIPTION                                        #
    #                                                                       #
    #   * Update the XML descriton of the subprojects dependencies          #
    #     for CDash.                                                        #
    #                                                                       #
    #########################################################################
    # CDASH XML SUBPROJECTS DESCRIPTION UPDATE
    if(LIBRARY_TARGET_NAME STREQUAL "library-qtpropertybrowser")
        # library-qtpropertybrowser is a corelib as library-camitkcore depends on it
        camitk_register_subproject(CORELIB ${LIBRARY_TARGET_NAME} DEPENDENCIES ${LIBRARIES_DEPENDENCY_LIST})
    else()
        camitk_register_subproject(CEP_LIBRARY ${LIBRARY_TARGET_NAME} DEPENDENCIES ${LIBRARIES_DEPENDENCY_LIST})
    endif()



    #####################################################################################
    #                                                                                   #
    #   TRANSLATION                                                                     #
    #                                                                                   #
    #   * CAMITK_TRANSLATIONS contains the list of language to translate                #
    #    the QString to.                                                                #
    #                                                                                   #
    #   * Create the translate.pro file which contains 4 sections:                      #
    #        - HEADERS:      list of .h/.hpp files to look for tr("") QString           #     
    #        - SOURCES:      list of .cpp files to look for tr("") QString              #
    #        - FORMS:        list of .ui files to look for tr("") QString               #            
    #        - TRANSLATIONS: list of .ts files which use CAMITK_TRANSLATIONS            #
    #            to define each .ts file                                                #
    #                                                                                   #
    #    * Execute lupdate program to update the .ts files with new QString             #
    #          found.                                                                   #
    #                                                                                   #
    #   * Execute lrelease program to create .qm files (binary equivalent of            #
    #       .ts files                                                                   #
    #                                                                                   #
    #   * Create translate.qrc which contains the list of .qm files.                    #
    #   * Create the flags.qrc file which contains the list of .png flags               #
    #         images                                                                    #
    #                                                                                   #
    #####################################################################################
    if(CAMITK_TRANSLATE)
        if(${DEFAULT_LIBRARY_NAME_CMAKE}_EXTRA_TRANSLATE_LANGUAGE)
            camitk_translate(EXTRA_LANGUAGE ${${DEFAULT_LIBRARY_NAME_CMAKE}_EXTRA_TRANSLATE_LANGUAGE})
        else()
            camitk_translate()
        endif()
    endif()
    
    
    
    #########################################################################
    #                                                                       #
    #   PACKAGING CATEGORIZATION                                            #
    #                                                                       #
    #   * On Windows, when building a package (win32 installer), the        #
    #     install shield wizard proposes you to select which component      #
    #     to install.                                                       #
    #   * Each component to install has a short description following its   #
    #     name to understand its role.                                      #
    #   * This section deals with the categorization and the description    #
    #     of the component in this installer.                               #
    #                                                                       #
    #########################################################################

    # WINDOWS INSTALLER CATEGORIZATION
    if(${DEFAULT_LIBRARY_NAME_CMAKE}_CEP_NAME) # This input variable describes the category
        if (${DEFAULT_LIBRARY_NAME_CMAKE}_CEP_NAME MATCHES "SDK")
            # The default SDK extensions are categorized as "required" and are not "unselectable" by the user at installation time
            cpack_add_component(${LIBRARY_TARGET_NAME}
                                DISPLAY_NAME ${LIBRARY_TARGET_NAME}
                                DESCRIPTION ${${DEFAULT_LIBRARY_NAME_CMAKE}_DESCRIPTION}
                                REQUIRED
                                GROUP SDK
                                )

        else()
            # Extension is selectable for installation in the wizard of the installer
            cpack_add_component(${LIBRARY_TARGET_NAME}
                                DISPLAY_NAME ${LIBRARY_TARGET_NAME}
                                DESCRIPTION ${${DEFAULT_LIBRARY_NAME_CMAKE}_DESCRIPTION}
                                GROUP ${${DEFAULT_LIBRARY_NAME_CMAKE}_CEP_NAME}
                                )
        endif()
    else()
        # Extension if not categorized for packaging presentation
        cpack_add_component(${LIBRARY_TARGET_NAME}
                            DISPLAY_NAME ${LIBRARY_TARGET_NAME}
                            DESCRIPTION ${${DEFAULT_LIBRARY_NAME_CMAKE}_DESCRIPTION}
                            )

    endif()

endmacro()
