
cmake_minimum_required(VERSION 3.8.0)


# Check if we are being built as part of a pybind11 module. 
if (COMMAND pybind11_add_module)
   # For python users, enable SSE4 and AVX if they have these instructions.
   include(${CMAKE_CURRENT_LIST_DIR}/check_if_sse4_instructions_executable_on_host.cmake)
   if (SSE4_IS_AVAILABLE_ON_HOST)
      set(USE_SSE4_INSTRUCTIONS ON CACHE BOOL "Compile your program with SSE4 instructions")
   endif()
   include(${CMAKE_CURRENT_LIST_DIR}/check_if_avx_instructions_executable_on_host.cmake)
   if (AVX_IS_AVAILABLE_ON_HOST)
      set(USE_AVX_INSTRUCTIONS ON CACHE BOOL "Compile your program with AVX instructions")
   endif()
   include(${CMAKE_CURRENT_LIST_DIR}/check_if_neon_available.cmake)
   if (ARM_NEON_IS_AVAILABLE)
      set(USE_NEON_INSTRUCTIONS ON CACHE BOOL "Compile your program with ARM-NEON instructions")
   endif()
endif()




set(gcc_like_compilers GNU Clang  Intel)
set(intel_archs x86_64 i386 i686 AMD64 amd64 x86)


# Setup some options to allow a user to enable SSE and AVX instruction use.  
if ((";${gcc_like_compilers};" MATCHES ";${CMAKE_CXX_COMPILER_ID};")  AND
   (";${intel_archs};"        MATCHES ";${CMAKE_SYSTEM_PROCESSOR};") AND NOT USE_AUTO_VECTOR)
   option(USE_SSE2_INSTRUCTIONS "Compile your program with SSE2 instructions" OFF)
   option(USE_SSE4_INSTRUCTIONS "Compile your program with SSE4 instructions" OFF)
   option(USE_AVX_INSTRUCTIONS  "Compile your program with AVX instructions"  OFF)
   if(USE_AVX_INSTRUCTIONS)
      list(APPEND active_compile_opts -mavx)
      message(STATUS "Enabling AVX instructions")
   elseif (USE_SSE4_INSTRUCTIONS)
      list(APPEND active_compile_opts -msse4)
      message(STATUS "Enabling SSE4 instructions")
   elseif(USE_SSE2_INSTRUCTIONS)
      list(APPEND active_compile_opts -msse2)
      message(STATUS "Enabling SSE2 instructions")
   endif()
elseif (MSVC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # else if using Visual Studio 
   # Use SSE2 by default when using Visual Studio.
   option(USE_SSE2_INSTRUCTIONS "Compile your program with SSE2 instructions" ON)
   option(USE_SSE4_INSTRUCTIONS "Compile your program with SSE4 instructions" OFF)
   option(USE_AVX_INSTRUCTIONS  "Compile your program with AVX instructions"  OFF)

   include(CheckTypeSize)
   check_type_size( "void*" SIZE_OF_VOID_PTR)
   if(USE_AVX_INSTRUCTIONS)
      list(APPEND active_compile_opts /arch:AVX)
      message(STATUS "Enabling AVX instructions")
   elseif (USE_SSE4_INSTRUCTIONS)
      # Visual studio doesn't have an /arch:SSE2 flag when building in 64 bit modes.
      # So only give it when we are doing a 32 bit build.
      if (SIZE_OF_VOID_PTR EQUAL 4)
         list(APPEND active_compile_opts /arch:SSE2)
      endif()
      message(STATUS "Enabling SSE4 instructions")
      list(APPEND active_preprocessor_switches "-DDLIB_HAVE_SSE2")
      list(APPEND active_preprocessor_switches "-DDLIB_HAVE_SSE3")
      list(APPEND active_preprocessor_switches "-DDLIB_HAVE_SSE41")
   elseif(USE_SSE2_INSTRUCTIONS)
      # Visual studio doesn't have an /arch:SSE2 flag when building in 64 bit modes.
      # So only give it when we are doing a 32 bit build.
      if (SIZE_OF_VOID_PTR EQUAL 4)
         list(APPEND active_compile_opts /arch:SSE2)
      endif()
      message(STATUS "Enabling SSE2 instructions")
      list(APPEND active_preprocessor_switches "-DDLIB_HAVE_SSE2")
   endif()

elseif((";${gcc_like_compilers};" MATCHES ";${CMAKE_CXX_COMPILER_ID};")  AND
        ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "^arm"))
   option(USE_NEON_INSTRUCTIONS "Compile your program with ARM-NEON instructions" OFF)
   if(USE_NEON_INSTRUCTIONS)
      list(APPEND active_compile_opts -mfpu=neon)
      message(STATUS "Enabling ARM-NEON instructions")
   endif()
endif()




if (CMAKE_COMPILER_IS_GNUCXX)
   # By default, g++ won't warn or error if you forget to return a value in a
   # function which requires you to do so.  This option makes it give a warning
   # for doing this.
   list(APPEND active_compile_opts "-Wreturn-type")
endif()

if ("Clang" MATCHES ${CMAKE_CXX_COMPILER_ID} AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0.0)
   # Clang 6 had a default template recursion depth of 256. This was changed to 1024 in Clang 7.
   # It must be increased on Clang 6 and below to ensure that the dnn examples don't error out.
   list(APPEND active_compile_opts "-ftemplate-depth=500")
endif()

if (MSVC)
   # By default Visual Studio does not support .obj files with more than 65k sections.
   # However, code generated by file_to_code_ex and code using DNN module can have
   # them.  So this flag enables > 65k sections, but produces .obj files
   # that will not be readable by VS 2005.
   list(APPEND active_compile_opts "/bigobj")

   # Build dlib with all cores.  Don't propagate the setting to client programs
   # though since they might compile large translation units that use too much
   # RAM.
   list(APPEND active_compile_opts_private "/MP")

   if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 3.3) 
      # Clang can compile all Dlib's code at Windows platform. Tested with Clang 5
      list(APPEND active_compile_opts -Xclang)
      list(APPEND active_compile_opts -fcxx-exceptions)
   endif()
endif()


