#[[
function(__config_build_types)
    set(CMAKE_CONFIGURATION_TYPES
        "DbgMt;DbgMd;RelMt;RelMd" CACHE STRING "" FORCE
    )
    string(REPLACE "/MDd" "/MTd" CXX_FLAGS_DBGMT  ${CMAKE_CXX_FLAGS_DEBUG})
    set(CMAKE_CXX_FLAGS_DBGMT ${CXX_FLAGS_DBGMT} PARENT_SCOPE)
    set(CMAKE_CXX_FLAGS_DBGMD ${CMAKE_CXX_FLAGS_DEBUG} PARENT_SCOPE)
    string(REPLACE "/MD" "/MT" CXX_FLAGS_RELMT ${CMAKE_CXX_FLAGS_RELEASE})
    set(CMAKE_CXX_FLAGS_RELMT ${CXX_FLAGS_RELMT} PARENT_SCOPE)
    set(CMAKE_CXX_FLAGS_RELMD ${CMAKE_CXX_FLAGS_RELEASE} PARENT_SCOPE)
    set(CMAKE_EXE_LINKER_FLAGS_DBGMT ${CMAKE_EXE_LINKER_FLAGS_DEBUG} PARENT_SCOPE)
    set(CMAKE_EXE_LINKER_FLAGS_DBGMD ${CMAKE_EXE_LINKER_FLAGS_DEBUG} PARENT_SCOPE)
    set(CMAKE_EXE_LINKER_FLAGS_RELMT ${CMAKE_EXE_LINKER_FLAGS_RELEASE} PARENT_SCOPE)
    set(CMAKE_EXE_LINKER_FLAGS_RELMD ${CMAKE_EXE_LINKER_FLAGS_RELEASE} PARENT_SCOPE)
endfunction(__config_build_types)

__config_build_types()
]]#
set(CMAKE_CONFIGURATION_TYPES
"DbgMt;DbgMd;RelMt;RelMd" CACHE STRING "" FORCE
)

if(${CMAKE_VS_PLATFORM_NAME} STREQUAL "Win32")
    set(MSVC_COMPILER_FLAGS "/ZI")            
elseif(${CMAKE_VS_PLATFORM_NAME} STREQUAL "x64")
    set(MSVC_COMPILER_FLAGS "/Zi")
else()
    message(FATAL_ERROR "Can't support this VS platform.")
endif()


string(REPLACE "/MDd" "/MTd" CXX_FLAGS_DBGMT  ${CMAKE_CXX_FLAGS_DEBUG})
set(CMAKE_CXX_FLAGS_DBGMT "${CXX_FLAGS_DBGMT} ${MSVC_COMPILER_FLAGS}" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_DBGMD "${CMAKE_CXX_FLAGS_DEBUG} ${MSVC_COMPILER_FLAGS}" CACHE INTERNAL "" FORCE)
string(REPLACE "/MD" "/MT" CXX_FLAGS_RELMT ${CMAKE_CXX_FLAGS_RELEASE})
set(CMAKE_CXX_FLAGS_RELMT "${CXX_FLAGS_RELMT} /Zi" CACHE INTERNAL "" FORCE)
set(CMAKE_CXX_FLAGS_RELMD "${CMAKE_CXX_FLAGS_RELEASE} /Zi" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_DBGMT "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_DBGMD "${CMAKE_EXE_LINKER_FLAGS_DEBUG} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_RELMT "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS_RELMD "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DEBUG" CACHE INTERNAL "" FORCE)

set(CMAKE_SHARED_LINKER_FLAGS_DBGMT "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_DBGMD "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_RELMT "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_SHARED_LINKER_FLAGS_RELMD "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG" CACHE INTERNAL "" FORCE)

set(CMAKE_MODULE_LINKER_FLAGS_DBGMT "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS_DBGMD "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS_RELMT "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /DEBUG" CACHE INTERNAL "" FORCE)
set(CMAKE_MODULE_LINKER_FLAGS_RELMD "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} /DEBUG" CACHE INTERNAL "" FORCE)

function(generate_target_file_postfix CFG CFG_POSTFIX)
    if (MSVC)
        if(${CMAKE_VS_PLATFORM_NAME} STREQUAL "Win32")
            set(__PN "x86")
        elseif(${CMAKE_VS_PLATFORM_NAME} STREQUAL "x64")
            set(__PN "x64")
        else()
            message(FATAL_ERROR "Can't support this VS platform.")
        endif()
        string(REGEX MATCHALL "[A-Z]([a-z]+)" OUT "${CFG}")
        list(GET OUT 0 a0)
        list(GET OUT 1 a1)
        string(TOLOWER ${a0} a00)
        string(TOLOWER ${a1} a10)
        set(${CFG_POSTFIX} "[${CMAKE_VS_PLATFORM_TOOLSET}_${__PN}_${a10}_${a00}]" PARENT_SCOPE)
    elseif (MINGW)
        if(${CFG} STREQUAL "Debug")
            set(cfg "dbg")
        elseif(${CFG} STREQUAL "Release")
            set(cfg "rel")
        endif(${CFG} STREQUAL "Debug")
        set(${CFG_POSTFIX} "gw_${cfg}" PARENT_SCOPE)
    endif(MSVC)
endfunction()

function(generate_libary_suffix_expression EXPR)
    foreach(CFG IN LISTS CMAKE_CONFIGURATION_TYPES)
        generate_target_file_postfix(${CFG} CFB_POSTFIX) 
        set(OUT "${OUT}$<$<CONFIG:${CFG}>:${CFB_POSTFIX}>")
    endforeach()
    set(EXPR ${OUT} PARENT_SCOPE)
endfunction()

function(set_target_postfix TGT CFG)
    generate_target_file_postfix(${CFG} CFG_POSTFIX)
    string(TOUPPER ${CFG} CFG)
    set_property(TARGET ${TGT} PROPERTY ${CFG}_POSTFIX ${CFG_POSTFIX})
endfunction()

function(add_target_link_libraries TGT_NAME)
    generate_libary_suffix_expression(EXPR)
    set(link_expr_ "")
    foreach(LIB IN LISTS ARGV)
        if(NOT ${LIB} STREQUAL ${TGT_NAME})
            string(APPEND link_expr_ "${LIB}${EXPR}${CMAKE_STATIC_LIBRARY_SUFFIX};")
        endif()
    endforeach(LIB IN ARGV)
    target_link_libraries(${TGT_NAME} ${link_expr_})
endfunction()

function(set_target_regular_postfix target_name)
    foreach(CFG  IN LISTS CMAKE_CONFIGURATION_TYPES)
        set_target_postfix(${target_name} ${CFG})
    endforeach()
endfunction(set_target_regular_postfix)

function(target_link_regular_libraries)
    generate_libary_suffix_expression(EXPR)
    set(link_expr_ "")
    list(GET ARGV 0 target_name)
    list(REMOVE_AT ARGV 0)
    list(GET ARGV 0 aexpr)
    if(${aexpr} STREQUAL "PRIVATE" OR ${aexpr} STREQUAL "PUBLIC" OR ${aexpr} STREQUAL "INTERFACE")
        list(REMOVE_AT ARGV 0)
    else(${aexpr} STREQUAL "PRIVATE" OR ${aexpr} STREQUAL "PUBLIC" OR ${aexpr} STREQUAL "INTERFACE")
        set(aexpr "")
    endif(${aexpr} STREQUAL "PRIVATE" OR ${aexpr} STREQUAL "PUBLIC" OR ${aexpr} STREQUAL "INTERFACE")
    foreach(LIB IN LISTS ARGV)
        string(APPEND link_expr_ "${LIB}${EXPR}${CMAKE_STATIC_LIBRARY_SUFFIX};")
    endforeach(LIB IN ARGV)
    if(NOT ${aexpr} STREQUAL "")
        target_link_libraries(${target_name} ${aexpr} ${link_expr_})
    else(NOT ${aexpr} STREQUAL "")
        target_link_libraries(${target_name} ${link_expr_})
    endif(NOT ${aexpr} STREQUAL "")
    
endfunction(target_link_regular_libraries target_name)