# This is a CMake file that sets up the add_python_module() macro.  This macro
# lets you easily make python modules that use dlib.  
#
# The macro takes the module name as its first argument and then a list of
# source files to compile into the module.  See ../tools/python/CMakeLists.txt
# for an example.
#
# It also sets up a macro called install_${module_name}_to() where
# ${module_name} is whatever you named your module.  This install_*_to() macro
# takes a folder name and creates an install target that will copy the compiled
# python module to that folder when you run "make install".  Note that the path
# given to install_*_to() is relative to your CMakeLists.txt file.
#


option(PYTHON3 "Build a Python3 compatible library rather than Python2." OFF)

# Avoid cmake warnings about changes in behavior of some Mac OS X path 
# variable we don't care about.
if (POLICY CMP0042)
    cmake_policy(SET CMP0042 NEW)
endif()


# Sometimes a computer will have multiple python verions installed.  So in this
# block of code we find the one in the user's path and add its home folder into
# cmake's search path.  That way it will use that version of python first. 
find_program(PYTHON_EXECUTABLE python)
# Resolve symbolic links, hopefully this will give us a path in the proper
# python home directory.
get_filename_component(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} REALPATH)
# Pick out the parent directories
get_filename_component(PYTHON_PATH ${PYTHON_EXECUTABLE} PATH)
get_filename_component(PYTHON_PATH ${PYTHON_PATH} PATH)
set(CMAKE_PREFIX_PATH ${PYTHON_PATH})


# To avoid dll hell, always link everything statically when compiling in
# visual studio.  This way, the resulting library won't depend on a bunch
# of other dll files and can be safely copied to someone elese's computer
# and expected to run.
if (MSVC)
    include(${CMAKE_CURRENT_LIST_DIR}/tell_visual_studio_to_use_static_runtime.cmake)
    add_definitions(-DBOOST_PYTHON_STATIC_LIB)
    SET(Boost_USE_STATIC_LIBS ON)
    SET(Boost_USE_MULTITHREADED ON)
    SET(Boost_USE_STATIC_RUNTIME ON)
endif()

set(Boost_NO_BOOST_CMAKE ON)

if (NOT WIN32)
    set(BOOST_LIBRARYDIR ${BOOST_LIBRARYDIR} $ENV{BOOST_LIBRARYDIR}  
            /usr/lib/x86_64-linux-gnu/)
else()
    link_directories($ENV{BOOST_LIBRARYDIR})
endif()
if (PYTHON3)
    # On some systems the boost python3 module is called python-py34 so check
    # for that one first.  
    FIND_PACKAGE(Boost 1.41.0  COMPONENTS python-py34 )
    if (NOT Boost_FOUND)
        FIND_PACKAGE(Boost 1.41.0 COMPONENTS python-py35)
    endif()
    if (NOT Boost_FOUND)
        FIND_PACKAGE(Boost 1.41.0 COMPONENTS python3)
    endif()
    if (NOT Boost_FOUND)
        FIND_PACKAGE(Boost 1.41.0 COMPONENTS python)
    endif()
    set(Python_ADDITIONAL_VERSIONS 3.5 3.6)
    FIND_PACKAGE(PythonLibs 3.4)
else()
    FIND_PACKAGE(Boost 1.41.0 COMPONENTS python)
    FIND_PACKAGE(PythonLibs 2.6)
endif()

if (NOT Boost_FOUND)
    message(STATUS " *****************************************************************************************************")
    if (WIN32)
        message(STATUS "We couldn't find the right version of boost python.  If you installed boost and you are still "
                "getting this error then you might have installed a version of boost that was compiled with a different "
                "version of visual studio than the one you are using.  So you have to make sure that the version of "
                "visual studio is the same version that was used to compile the copy of boost you are using.")
        message(STATUS " Set the BOOST_ROOT and BOOST_LIBRARYDIR environment variables before running cmake. ")
        message(STATUS " E.g.  Something like this: ")
        message(STATUS "    set BOOST_ROOT=C:\\local\\boost_1_57_0 " )
        message(STATUS "    set BOOST_LIBRARYDIR=C:\\local\\boost_1_57_0\\stage\\lib")
        message(STATUS "")
        message(STATUS " You will also likely need to compile boost yourself rather than using one of the precompiled ")
        message(STATUS " windows binaries.  Do this by going to the folder tools\\build\\ within boost and running ")
        message(STATUS " bootstrap.bat.  Then run the command: ")
        message(STATUS "    b2 install")
        message(STATUS " And then add the output bin folder to your PATH.  Usually this is the C:\\boost-build-engine\\bin")
        message(STATUS " folder. Finally, go to the boost root and run a command like this:")
        message(STATUS "    b2 -a --with-python address-model=64 toolset=msvc runtime-link=static")
        message(STATUS " When it completes, set BOOST_LIBRARYDIR equal to wherever b2 put the compiled libraries.")
        message(STATUS " Note that you will need to set the address-model based on if you want a 32 or 64bit python library.")
        message(STATUS "")
        message(STATUS " Next, when you invoke cmake to compile dlib you may have to use cmake's -G option to set the ")
        message(STATUS " 64 vs. 32bit mode of visual studio.  Also, if you want a Python3 library you will need to ")
        message(STATUS " add -DPYTHON3=1.  You do this with a statement like: ")
        message(STATUS "    cmake -G \"Visual Studio 12 2013 Win64\" -DPYTHON3=1 ..\\..\\tools\\python")
        message(STATUS " Rather than:")
        message(STATUS "    cmake ..\\..\\tools\\python")
        message(STATUS " Which will build a 32bit Python2 module by default on most systems.")
        message(STATUS "")
    else()
        message(STATUS " To compile Boost.Python yourself download boost from boost.org and then go into the boost root folder")
        message(STATUS " and run these commands: ")
        message(STATUS "    ./bootstrap.sh --with-libraries=python") 
        message(STATUS "    ./b2")
        message(STATUS "    sudo ./b2 install")
    endif()
    message(STATUS " *****************************************************************************************************")
    message(FATAL_ERROR " Boost python library not found. ")
endif()



INCLUDE_DIRECTORIES("${Boost_INCLUDE_DIRS}")
if (PYTHON_INCLUDE_PATH)
   INCLUDE_DIRECTORIES("${PYTHON_INCLUDE_PATH}" )
else()
   INCLUDE_DIRECTORIES("${PYTHON_INCLUDE_DIRS}" )
endif()

message(STATUS "USING BOOST_LIBS: ${Boost_LIBRARIES}")
if (WIN32)
    message(STATUS "USING PYTHON_LIBS: ${PYTHON_LIBRARIES}")
endif()

if (CMAKE_COMPILER_IS_GNUCXX)
    # Just setting CMAKE_POSITION_INDEPENDENT_CODE should be enough to set
    # -fPIC for GCC but sometimes it still doesn't get set, so make sure it
    # does.
    add_definitions("-fPIC")
    set(CMAKE_POSITION_INDEPENDENT_CODE True)
else()
    set(CMAKE_POSITION_INDEPENDENT_CODE True)
endif()

# include dlib so we can link against it
include(${CMAKE_CURRENT_LIST_DIR}/../cmake)


# We put the extra _ on the end of the name just so it's possible to
# have a module name of dlib and not get a conflict with the target named
# dlib in ../dlib/cmake.  We use the target OUPUT_NAME property to ensure the
# output name is set to what the user asked for (i.e. no _).
macro(add_python_module module_name module_sources )
   ADD_LIBRARY(${module_name}_ SHARED ${module_sources} ${ARGN} )
   TARGET_LINK_LIBRARIES(${module_name}_ ${Boost_LIBRARIES} dlib::dlib)

   if(WIN32 AND NOT CYGWIN)
      TARGET_LINK_LIBRARIES(${module_name}_ ${PYTHON_LIBRARIES})
      SET_TARGET_PROPERTIES( ${module_name}_
         PROPERTIES
         PREFIX ""
         SUFFIX ".pyd"
         OUTPUT_NAME ${module_name}
         )
   elseif(CYGWIN)
      SET_TARGET_PROPERTIES( ${module_name}_
         PROPERTIES
         PREFIX ""
         SUFFIX ".dll"
         OUTPUT_NAME ${module_name}
         )
    elseif(APPLE)
      SET_TARGET_PROPERTIES( ${module_name}_
         PROPERTIES
         LINK_FLAGS "-undefined dynamic_lookup"
         PREFIX ""
         SUFFIX ".so"
         OUTPUT_NAME ${module_name}
         )
   else()
      SET_TARGET_PROPERTIES( ${module_name}_
         PROPERTIES
         LINK_FLAGS "-shared"
         PREFIX ""
         SUFFIX ".so"
         OUTPUT_NAME ${module_name}
         )
   endif()

   macro(install_${module_name}_to path)
       # Determine the path to our CMakeLists.txt file.
       string(REGEX REPLACE "CMakeLists.txt$" "" base_path ${CMAKE_CURRENT_LIST_FILE})
       INSTALL(TARGETS ${module_name}_ 
            RUNTIME DESTINATION  "${base_path}/${path}"
            LIBRARY DESTINATION  "${base_path}/${path}"
           )
   endmacro()

endmacro()



