cjolivier01 closed pull request #9955: [DO NOT MERGE] Cython CI check
URL: https://github.com/apache/incubator-mxnet/pull/9955
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7f68ed25c82..efc7ce14c3f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,3 +1,20 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
 cmake_minimum_required(VERSION 3.0.2)
 
 project(mxnet C CXX)
@@ -533,14 +550,14 @@ if(USE_CUDA)
     add_definitions(-DMXNET_USE_CUDA=1)
     if(CUDA_LIBRARY_PATH)
         if(IS_CONTAINER_BUILD)
-        # In case of building on a production-like build container which may 
not have Cuda installed
-        if(NOT CMAKE_SYSTEM_HAS_CUDA)
-            # Assuming building in a container that doesn't have CUDA 
installed (ie CPU-only build machine)
-            # so use the stub cuda driver shared library
-            if(EXISTS ${CUDA_LIBRARY_PATH}/stubs/libcuda.so)
-            link_directories(${CUDA_LIBRARY_PATH}/stubs)
-            endif()
-        endif()
+          # In case of building on a production-like build container which may 
not have Cuda installed
+          if(NOT CMAKE_SYSTEM_HAS_CUDA)
+              # Assuming building in a container that doesn't have CUDA 
installed (ie CPU-only build machine)
+              # so use the stub cuda driver shared library
+              if(EXISTS ${CUDA_LIBRARY_PATH}/stubs/libcuda.so)
+                link_directories(${CUDA_LIBRARY_PATH}/stubs)
+              endif()
+          endif()
         endif()
     endif()
  endif()
@@ -568,6 +585,9 @@ else()
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHsc")
 endif()
 
+#
+# MXNet libraries
+#
 set(MXNET_INSTALL_TARGETS mxnet)
 if(UNIX)
   list(APPEND MXNET_INSTALL_TARGETS mxnet_static)
@@ -580,12 +600,11 @@ else()
   add_library(mxnet SHARED ${SOURCE})
 endif()
 
-if(USE_CUDA)
-  if(FIRST_CUDA AND MSVC)
-    target_compile_options(mxnet PUBLIC "$<$<CONFIG:DEBUG>:-Xcompiler=-MTd>")
-    target_compile_options(mxnet PUBLIC "$<$<CONFIG:RELEASE>:-Xcompiler=-MT>")
-  endif()
+if(USE_CUDA AND FIRST_CUDA AND MSVC)
+  target_compile_options(mxnet PUBLIC "$<$<CONFIG:DEBUG>:-Xcompiler=-MTd>")
+  target_compile_options(mxnet PUBLIC "$<$<CONFIG:RELEASE>:-Xcompiler=-MT>")
 endif()
+
 if(USE_DIST_KVSTORE)
   if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/ps-lite/CMakeLists.txt)
     add_subdirectory("ps-lite")
@@ -615,6 +634,16 @@ if(USE_PLUGINS_WARPCTC)
   target_link_libraries(mxnet PUBLIC optimized ${WARPCTC_LIB_RELEASE})
 endif()
 
+#
+# BEGIN Cython Build
+#
+include(cmake/CythonUtil.cmake)
+mxnet_external_build_cython(2)
+#mxnet_external_build_cython(3)
+#
+# END Cython build
+#
+
 
 if(USE_OPENCV)
   add_executable(im2rec "tools/im2rec.cc")
diff --git a/cmake/CythonUtil.cmake b/cmake/CythonUtil.cmake
new file mode 100644
index 00000000000..cd6ef3c2422
--- /dev/null
+++ b/cmake/CythonUtil.cmake
@@ -0,0 +1,189 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+################################################################################################
+# Build a cython module
+#
+# Usage:
+#   mxnet_external_build_cython(<python major version>)
+#
+function(mxnet_build_cython_module python_version)
+  string(REGEX REPLACE "@" ";" PROP_MXNET_INCLUDE_DIRECTORIES 
"${MXNET_INCLUDE_DIRECTORIES}")
+  string(REGEX REPLACE "@" ";" PROP_MXNET_INTERFACE_LINK_LIBRARIES 
"${MXNET_INTERFACE_LINK_LIBRARIES}")
+
+  foreach(var ${PROP_MXNET_INCLUDE_DIRECTORIES})
+    include_directories(${var})
+  endforeach()
+
+  unset(PYTHONLIBS_FOUND)
+  unset(PYTHON_LIBRARIES)
+  unset(PYTHON_INCLUDE_PATH)
+  unset(PYTHON_INCLUDE_DIRS)
+  unset(PYTHON_DEBUG_LIBRARIES)
+  unset(PYTHONLIBS_VERSION_STRING)
+  unset(PYTHONINTERP_FOUND)
+  unset(PYTHON_EXECUTABLE)
+  unset(PYTHON_VERSION_STRING)
+  unset(PYTHON_VERSION_MAJOR)
+  unset(PYTHON_VERSION_MINOR)
+  unset(PYTHON_VERSION_PATCH)
+
+  if(python_version EQUAL 2)
+    set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
+  elseif(python_version EQUAL 3)
+    set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+  else()
+    message(FATAL_ERROR "Nov alid python_version set (must be 2 or 3)")
+    return()
+  endif()
+
+  set(python_libs_version ${python_version})
+  include(${MXNET_ROOT_DIR}/cmake/UseCython.cmake)  # set from 
mxnet_external_build_cython
+
+  if(NOT CYTHON${python_version}_FOUND)
+    message(WARNING " Could not build cython target for Python 
${python_version}")
+    return()
+  endif()
+
+  set(CYTHON_SUBDIR ".")
+
+  file(GLOB_RECURSE CYTHON_SOURCE 
"${MXNET_ROOT_DIR}/python/mxnet/cython/*.pyx")
+
+  if(NOT MXNET_LIB_LOCATION)
+    set(MXNET_LIB_LOCATION mxnet)
+  endif()
+
+  set(CYTHON_CXX_SOURCE "")
+  foreach(cy_file ${CYTHON_SOURCE})
+    set_source_files_properties(${cy_file} PROPERTIES CYTHON_IS_CXX TRUE)
+    list(APPEND CYTHON_CXX_SOURCE ${cy_file_generated})
+    get_filename_component(cy_module ${cy_file} NAME_WE)
+    # We need cmake to have different target names for python 2 and 3
+    set(cy_module_name ${cy_module})
+    cython_add_module(${cy_module_name} "${CYTHON_SUBDIR}" ${cy_file})
+    set_target_properties(${cy_module_name}
+      PROPERTIES
+      LIBRARY_OUTPUT_DIRECTORY "${CYTHON_SUBDIR}/"
+      INTERFACE_LINK_LIBRARIES "${PROP_MXNET_INTERFACE_LINK_LIBRARIES}"
+      )
+    target_link_libraries(${cy_module_name} ${MXNET_LIB_LOCATION})
+  endforeach()
+endfunction()
+
+
+################################################################################################
+# Spawn external CMakeLists.txt in order to build a particular cython/python 
version
+#
+# The spawn approach is because we need to detect and build with both python 
version 2 and 3
+# This is not osmething that a single process of cmake can deal with, so we 
launch
+# a cmake process for the cython build 2, then for 3, passing it our relevant 
config
+#
+# Usage:
+#   mxnet_external_build_cython(<python major version>)
+#
+function(mxnet_external_build_cython python_major_version)
+  set(PMV ${python_major_version})
+
+  if(CYTHON_WITHOUT_MXNET_TARGET)
+    set(CYTHON_DEPS "")
+    set(CYTHON_MXNET_LIB_LOCATION "")
+  else()
+    set(CYTHON_DEPS mxnet)
+    set(CYTHON_MXNET_LIB_LOCATION $<TARGET_LINKER_FILE:mxnet>)
+  endif()
+
+  file(GLOB_RECURSE CYTHON_SOURCE "python/mxnet/cython/*.pyx")
+
+  get_cmake_property(CACHE_VARS CACHE_VARIABLES)
+  foreach(_cache_var ${CACHE_VARS})
+    #message(STATUS "${_cache_var}=${${_cache_var}}")
+    get_property(CACHE_VAR_HELPSTRING CACHE ${_cache_var} PROPERTY HELPSTRING)
+    if(NOT _cache_var MATCHES "CMAKE_EXTRA_GENERATOR_.+"
+      AND NOT _cache_var MATCHES "FIND_PACKAGE_MESSAGE_.+"
+      )
+      if(_cache_var MATCHES "USE_.+"
+        OR _cache_var MATCHES "CMAKE_MODULE_.+"
+        OR CACHE_VAR_HELPSTRING STREQUAL "No help, variable specified on the 
command line."
+        )
+        get_property(_cache_var_type CACHE ${_cache_var} PROPERTY TYPE)
+        if(_cache_var_type STREQUAL "UNINITIALIZED")
+          set(_cache_var_type)
+        else()
+          set(_cache_var_type :${_cache_var_type})
+        endif()
+        set(CMAKE_ARGS "${CMAKE_ARGS} 
-D${_cache_var}${_cache_var_type}=\"${${_cache_var}}\"")
+      endif()
+    endif()
+  endforeach()
+
+  get_property(PROP_MXNET_INCLUDE_DIRECTORIES TARGET mxnet PROPERTY 
INCLUDE_DIRECTORIES)
+  string(REGEX REPLACE "\;" "@" MXNET_INCLUDE_DIRECTORIES 
"${PROP_MXNET_INCLUDE_DIRECTORIES}")
+
+  get_property(PROP_MXNET_INTERFACE_LINK_LIBRARIES TARGET mxnet PROPERTY 
INTERFACE_LINK_LIBRARIES)
+  string(REGEX REPLACE "\;" "@" MXNET_INTERFACE_LINK_LIBRARIES 
"${PROP_MXNET_INTERFACE_LINK_LIBRARIES}")
+
+  set(CYTHON_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/cython/cy${PMV})
+
+  set(_config_cleanup_files "")
+  set(_config_cleanup_files_ex "")
+
+  foreach(_file ${CYTHON_SOURCE})
+    get_filename_component(_cy_module ${_file} NAME_WE)
+    list(APPEND _config_cleanup_files  "${CYTHON_BINARY_DIR}/${_cy_module}.so")
+    list(APPEND _config_cleanup_files  
"${CYTHON_BINARY_DIR}/${_cy_module}.cxx")
+    list(APPEND _config_cleanup_files  "${CYTHON_BINARY_DIR}/${_cy_module}.c")
+  endforeach()
+
+  # Clear some cmake-generated files
+  list(APPEND _config_cleanup_files_ex "${CYTHON_BINARY_DIR}/CMakeCache.txt")
+  list(APPEND _config_cleanup_files_ex "${CYTHON_BINARY_DIR}/Makefile")
+
+  # Get current cleanup files
+  get_directory_property(CLEANUP_FILES ADDITIONAL_MAKE_CLEAN_FILES)
+  list(APPEND CLEANUP_FILES ${_config_cleanup_files})
+  list(APPEND CLEANUP_FILES ${_config_cleanup_files_ex})
+  # Set new list of cleanup files
+  set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES 
"${CLEANUP_FILES}")
+
+  add_custom_target(build-time-make-cython-directory${PMV} ALL
+    COMMAND ${CMAKE_COMMAND} -E make_directory ${CYTHON_BINARY_DIR})
+
+  add_custom_target(${PROJECT_NAME}_ConfigCython${PMV} ALL
+    ${CMAKE_COMMAND}
+    ${CMAKE_ARGS}
+    -G "${CMAKE_GENERATOR}"
+    -DCMAKE_MODULE_PATH="${CMAKE_MODULE_PATH}"
+    -DMXNET_INCLUDE_DIRECTORIES="${MXNET_INCLUDE_DIRECTORIES}"
+    -DMXNET_INTERFACE_LINK_LIBRARIES="${MXNET_INTERFACE_LINK_LIBRARIES}"
+    -DMXNET_LIB_LOCATION=${CYTHON_MXNET_LIB_LOCATION}
+    -DMXNET_ROOT_DIR=${CMAKE_CURRENT_SOURCE_DIR}
+    -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
+    -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}
+    -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
+    ${CMAKE_CURRENT_SOURCE_DIR}/src/cython/cy${PMV}
+    WORKING_DIRECTORY ${CYTHON_BINARY_DIR}
+    DEPENDS ${CYTHON_DEPS} build-time-make-cython-directory${PMV}
+    )
+
+  add_custom_target(${PROJECT_NAME}_BuildCython${PMV} ALL
+    ${CMAKE_COMMAND}
+    --build ${CYTHON_BINARY_DIR}
+    --config ${CMAKE_BUILD_TYPE}
+    WORKING_DIRECTORY ${CYTHON_BINARY_DIR}
+    DEPENDS ${PROJECT_NAME}_ConfigCython${PMV}
+    )
+endfunction()
diff --git a/cmake/Modules/FindCython.cmake b/cmake/Modules/FindCython.cmake
new file mode 100644
index 00000000000..132de501299
--- /dev/null
+++ b/cmake/Modules/FindCython.cmake
@@ -0,0 +1,69 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Find the Cython compiler.
+#
+# This code sets the following variables:
+#
+#  CYTHON_EXECUTABLE
+#
+# See also UseCython.cmake
+
+#=============================================================================
+# Copyright 2011 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Use the Cython executable that lives next to the Python executable
+# if it is a local installation.
+
+if(PACKAGE_FIND_VERSION_MAJOR EQUAL 3)
+  set(CYTHON_EXE_NAMES cython3 cython.bat cython)
+  message(STATUS " Looking for Cython version 3")
+else()
+  set(CYTHON_EXE_NAMES cython.bat cython cython3)
+endif()
+
+if(PYTHONINTERP_FOUND)
+  get_filename_component( _python_path ${PYTHON_EXECUTABLE} PATH )
+  find_program(CYTHON_EXECUTABLE
+    NAMES ${CYTHON_EXE_NAMES}
+    HINTS ${_python_path}
+    )
+else()
+  find_program(CYTHON_EXECUTABLE NAMES ${CYTHON_EXE_NAMES})
+endif()
+
+include( FindPackageHandleStandardArgs )
+find_package_handle_standard_args(Cython DEFAULT_MSG CYTHON_EXECUTABLE)
+
+if(CYTHON_FOUND)
+  message(STATUS "Found Cython (executable: ${CYTHON_EXECUTABLE})")
+  mark_as_advanced( CYTHON_EXECUTABLE )
+endif()
+
diff --git a/cmake/Modules/FindOpenBLAS.cmake b/cmake/Modules/FindOpenBLAS.cmake
index a3a79caae46..e325b9e16cd 100644
--- a/cmake/Modules/FindOpenBLAS.cmake
+++ b/cmake/Modules/FindOpenBLAS.cmake
@@ -15,7 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-file(TO_CMAKE_PATH "$ENV{OpenBLAS_HOME}" OpenBLAS_HOME)
 file(TO_CMAKE_PATH "$ENV{OpenBLAS}" OpenBLAS_DIR)
 
 SET(Open_BLAS_INCLUDE_SEARCH_PATHS
@@ -31,6 +30,8 @@ SET(Open_BLAS_INCLUDE_SEARCH_PATHS
   ${PROJECT_SOURCE_DIR}/thirdparty/OpenBLAS/include
   ${OpenBLAS_HOME}
   ${OpenBLAS_HOME}/include
+  $ENV{OpenBLAS_HOME}
+  $ENV{OpenBLAS_HOME}/include
 )
 
 SET(Open_BLAS_LIB_SEARCH_PATHS
@@ -46,10 +47,12 @@ SET(Open_BLAS_LIB_SEARCH_PATHS
         /usr/local/opt/openblas/lib
         ${PROJECT_SOURCE_DIR}/3rdparty/OpenBLAS/lib
         ${PROJECT_SOURCE_DIR}/thirdparty/OpenBLAS/lib
-       ${OpenBLAS_DIR}
-       ${OpenBLAS_DIR}/lib
+             ${OpenBLAS_DIR}
+             ${OpenBLAS_DIR}/lib
         ${OpenBLAS_HOME}
         ${OpenBLAS_HOME}/lib
+        $ENV{OpenBLAS_HOME}
+        $ENV{OpenBLAS_HOME}/lib
  )
 
 FIND_PATH(OpenBLAS_INCLUDE_DIR NAMES cblas.h PATHS 
${Open_BLAS_INCLUDE_SEARCH_PATHS})
diff --git a/cmake/UseCython.cmake b/cmake/UseCython.cmake
new file mode 100644
index 00000000000..535bea57e51
--- /dev/null
+++ b/cmake/UseCython.cmake
@@ -0,0 +1,383 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+# Define a function to create Cython modules.
+#
+# For more information on the Cython project, see http://cython.org/.
+# "Cython is a language that makes writing C extensions for the Python language
+# as easy as Python itself."
+#
+# This file defines a CMake function to build a Cython Python module.
+# To use it, first include this file.
+#
+#   include( UseCython )
+#
+# Then call cython_add_module to create a module.
+#
+#   cython_add_module( <module_name> <src1> <src2> ... <srcN> )
+#
+# To create a standalone executable, the function
+#
+#   cython_add_standalone_executable( <executable_name> [MAIN_MODULE src1] 
<src1> <src2> ... <srcN> )
+#
+# To avoid dependence on Python, set the PYTHON_LIBRARY cache variable to point
+# to a static library.  If a MAIN_MODULE source is specified,
+# the "if __name__ == '__main__':" from that module is used as the C main() 
method
+# for the executable.  If MAIN_MODULE, the source with the same basename as
+# <executable_name> is assumed to be the MAIN_MODULE.
+#
+# Where <module_name> is the name of the resulting Python module and
+# <src1> <src2> ... are source files to be compiled into the module, e.g. 
*.pyx,
+# *.py, *.c, *.cxx, etc.  A CMake target is created with name <module_name>.  
This can
+# be used for target_link_libraries(), etc.
+#
+# The sample paths set with the CMake include_directories() command will be 
used
+# for include directories to search for *.pxd when running the Cython complire.
+#
+# Cache variables that effect the behavior include:
+#
+#  CYTHON_ANNOTATE
+#  CYTHON_NO_DOCSTRINGS
+#  CYTHON_FLAGS
+#
+# Source file properties that effect the build process are
+#
+#  CYTHON_IS_CXX
+#
+# If this is set of a *.pyx file with CMake set_source_files_properties()
+# command, the file will be compiled as a C++ file.
+#
+# See also FindCython.cmake
+
+#=============================================================================
+# Copyright 2011 Kitware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#=============================================================================
+
+# Configuration options.
+set( CYTHON_ANNOTATE OFF
+  CACHE BOOL "Create an annotated .html file when compiling *.pyx." )
+set( CYTHON_NO_DOCSTRINGS OFF
+  CACHE BOOL "Strip docstrings from the compiled module." )
+set( CYTHON_FLAGS "" CACHE STRING
+  "Extra flags to the cython compiler." )
+mark_as_advanced( CYTHON_ANNOTATE CYTHON_NO_DOCSTRINGS CYTHON_FLAGS )
+
+unset(PYTHONLIBS_FOUND)
+unset(PYTHONINTERP_FOUND)
+unset(CYTHON_FOUND)
+
+if(NOT python_libs_version)
+  message(STATUS "Looking for python dependencies, version: 
${python_libs_version}")
+endif()
+
+find_package(PythonInterp ${python_libs_version} REQUIRED)
+if(PYTHONINTERP_FOUND)
+  message(STATUS "Python ${python_libs_version} executable: 
${PYTHON_EXECUTABLE}")
+  find_package(PythonLibs ${python_libs_version} REQUIRED)
+  if(PYTHONLIBS_FOUND)
+    set(PYTHON_DEBUG_LIBRARY ${PYTHON_LIBRARY})
+    set(PYTHON_DEBUG_LIBRARIES ${PYTHON_DEBUG_LIBRARIES})
+    find_package(Cython ${python_libs_version} REQUIRED)
+    if(CYTHON_FOUND)
+      set(CYTHON${python_libs_version}_FOUND ${python_libs_version})
+      message(STATUS  " CYTHON${python_libs_version}_FOUND: 
${CYTHON${python_libs_version}_FOUND}")
+    else()
+      message(WARNING " Could not find package: Cython")
+    endif()
+  else()
+    message(WARNING " Could not find package: PythonLibs")
+  endif()
+else()
+  message(WARNING " Could not find package: PythonInterp")
+endif()
+
+if(NOT CYTHON${python_libs_version}_FOUND)
+  message(WARNING " Could not find cython and/or dependencies for major 
version ${python_libs_version}")
+  return()
+endif()
+
+message(STATUS "PYTHONLIBS_VERSION_STRING: ${PYTHONLIBS_VERSION_STRING}")
+string(REPLACE "." ";" PYTHON_VERSION_LIST ${PYTHONLIBS_VERSION_STRING})
+list(GET PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
+list(GET PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
+list(GET PYTHON_VERSION_LIST 1 PYTHON_VERSION_PATCH)
+
+if(NOT PYTHON_VERSION_MAJOR EQUAL ${python_libs_version})
+  message(FATAL_ERROR "Scripts found wrong python major version: 
${PYTHON_VERSION_MAJOR} instead of ${python_libs_version}. This is most likely 
due to version ${python_libs_version} not being installed or not found")
+  return()
+endif()
+
+set( CYTHON_CXX_EXTENSION "cxx" )
+set( CYTHON_C_EXTENSION "c" )
+
+# Create a *.c or *.cxx file from a *.pyx file.
+# Input the generated file basename.  The generate file will put into the 
variable
+# placed in the "generated_file" argument. Finally all the *.py and *.pyx 
files.
+function( compile_pyx _name c_cxx_output_subdir generated_file )
+  # Default to assuming all files are C.
+  set( cxx_arg "" )
+  set( extension ${CYTHON_C_EXTENSION} )
+  set( pyx_lang "C" )
+  set( comment "Compiling Cython C source for ${_name}..." )
+
+  set( cython_include_directories "" )
+  set( pxd_dependencies "" )
+  set( pxi_dependencies "" )
+  set( c_header_dependencies "" )
+  set( pyx_locations "" )
+
+  #message(STATUS " compile_pyx( ${_name} ${generated_file} ${ARGN} )")
+
+  foreach( pyx_file ${ARGN} )
+    get_filename_component( pyx_file_basename "${pyx_file}" NAME_WE )
+
+    # Determine if it is a C or C++ file.
+    get_source_file_property( property_is_cxx ${pyx_file} CYTHON_IS_CXX )
+    if( ${property_is_cxx} )
+      set( cxx_arg "--cplus" )
+      set( extension ${CYTHON_CXX_EXTENSION} )
+      set( pyx_lang "CXX" )
+      set( comment "Compiling Cython CXX source for ${_name}..." )
+    endif()
+
+    # Get the include directories.
+    get_source_file_property( pyx_location ${pyx_file} LOCATION )
+
+    get_filename_component( pyx_path ${pyx_location} PATH )
+
+    #get_directory_property( cmake_include_directories DIRECTORY ${pyx_path} 
INCLUDE_DIRECTORIES )
+
+    list( APPEND cython_include_directories ${cmake_include_directories} )
+    list( APPEND pyx_locations "${pyx_location}" )
+
+    # Determine dependencies.
+    # Add the pxd file will the same name as the given pyx file.
+    unset( corresponding_pxd_file CACHE )
+    find_file( corresponding_pxd_file ${pyx_file_basename}.pxd
+      PATHS "${pyx_path}" ${cmake_include_directories}
+      NO_DEFAULT_PATH )
+    if( corresponding_pxd_file )
+      list( APPEND pxd_dependencies "${corresponding_pxd_file}" )
+    endif()
+
+    # Look for included pxi files
+    file(STRINGS "${pyx_file}" include_statements REGEX "include 
+['\"]([^'\"]+).*")
+    foreach(statement ${include_statements})
+      string(REGEX REPLACE "include +['\"]([^'\"]+).*" "\\1" pxi_file 
"${statement}")
+      unset(pxi_location CACHE)
+      find_file(pxi_location ${pxi_file}
+        PATHS "${pyx_path}" ${cmake_include_directories} NO_DEFAULT_PATH)
+      if (pxi_location)
+        list(APPEND pxi_dependencies ${pxi_location})
+        get_filename_component( found_pyi_file_basename "${pxi_file}" NAME_WE )
+        get_filename_component( found_pyi_path ${pxi_location} PATH )
+        unset( found_pyi_pxd_file CACHE )
+        find_file( found_pyi_pxd_file ${found_pyi_file_basename}.pxd
+          PATHS "${found_pyi_path}" ${cmake_include_directories} 
NO_DEFAULT_PATH )
+        if (found_pyi_pxd_file)
+          list( APPEND pxd_dependencies "${found_pyi_pxd_file}" )
+        endif()
+      endif()
+    endforeach() # for each include statement found
+
+    # pxd files to check for additional dependencies.
+    set( pxds_to_check "${pyx_file}" "${pxd_dependencies}" )
+    set( pxds_checked "" )
+    set( number_pxds_to_check 1 )
+    while( ${number_pxds_to_check} GREATER 0 )
+      foreach( pxd ${pxds_to_check} )
+        list( APPEND pxds_checked "${pxd}" )
+        list( REMOVE_ITEM pxds_to_check "${pxd}" )
+
+        # check for C header dependencies
+        file( STRINGS "${pxd}" extern_from_statements
+          REGEX "cdef[ ]+extern[ ]+from.*$" )
+        foreach( statement ${extern_from_statements} )
+          # Had trouble getting the quote in the regex
+          string( REGEX REPLACE "cdef[ ]+extern[ ]+from[ ]+[\"]([^\"]+)[\"].*" 
"\\1" header "${statement}" )
+          unset( header_location CACHE )
+          find_file( header_location ${header} PATHS 
${cmake_include_directories} )
+          if( header_location )
+            list( FIND c_header_dependencies "${header_location}" header_idx )
+            if( ${header_idx} LESS 0 )
+              list( APPEND c_header_dependencies "${header_location}" )
+            endif()
+          endif()
+        endforeach()
+
+        # check for pxd dependencies
+
+        # Look for cimport statements.
+        set( module_dependencies "" )
+        file( STRINGS "${pxd}" cimport_statements REGEX cimport )
+        foreach( statement ${cimport_statements} )
+          if( ${statement} MATCHES from )
+            string( REGEX REPLACE "from[ ]+([^ ]+).*" "\\1" module 
"${statement}" )
+          else()
+            string( REGEX REPLACE "cimport[ ]+([^ ]+).*" "\\1" module 
"${statement}" )
+          endif()
+          list( APPEND module_dependencies ${module} )
+        endforeach()
+        list( REMOVE_DUPLICATES module_dependencies )
+        # Add the module to the files to check, if appropriate.
+        foreach( module ${module_dependencies} )
+          unset( pxd_location CACHE )
+          find_file( pxd_location ${module}.pxd
+            PATHS "${pyx_path}" ${cmake_include_directories} NO_DEFAULT_PATH )
+          if( pxd_location )
+            list( FIND pxds_checked ${pxd_location} pxd_idx )
+            if( ${pxd_idx} LESS 0 )
+              list( FIND pxds_to_check ${pxd_location} pxd_idx )
+              if( ${pxd_idx} LESS 0 )
+                list( APPEND pxds_to_check ${pxd_location} )
+                list( APPEND pxd_dependencies ${pxd_location} )
+              endif() # if it is not already going to be checked
+            endif() # if it has not already been checked
+          endif() # if pxd file can be found
+        endforeach() # for each module dependency discovered
+      endforeach() # for each pxd file to check
+      list( LENGTH pxds_to_check number_pxds_to_check )
+    endwhile()
+
+
+
+  endforeach() # pyx_file
+
+  # Set additional flags.
+  if( CYTHON_ANNOTATE )
+    set( annotate_arg "--annotate" )
+  endif()
+
+  if( CYTHON_NO_DOCSTRINGS )
+    set( no_docstrings_arg "--no-docstrings" )
+  endif()
+
+  if( "${CMAKE_BUILD_TYPE}" STREQUAL "Debug" OR
+    "${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo" )
+    set( cython_debug_arg "--gdb" )
+  endif()
+
+  if( "${PYTHONLIBS_VERSION_STRING}" MATCHES "^2." )
+    set( version_arg "-2" )
+  elseif( "${PYTHONLIBS_VERSION_STRING}" MATCHES "^3." )
+    set( version_arg "-3" )
+  else()
+    set( version_arg )
+  endif()
+
+  # Include directory arguments.
+  list( REMOVE_DUPLICATES cython_include_directories )
+  set( include_directory_arg "" )
+  foreach( _include_dir ${cython_include_directories} )
+    set( include_directory_arg ${include_directory_arg} "-I" "${_include_dir}" 
)
+  endforeach()
+
+  # Determining generated file name.
+  set( _generated_file 
"${CMAKE_CURRENT_BINARY_DIR}/${c_cxx_output_subdir}/${_name}.${extension}" )
+  set_source_files_properties( ${_generated_file} PROPERTIES GENERATED TRUE )
+  set( ${generated_file} ${_generated_file} PARENT_SCOPE )
+
+  list( REMOVE_DUPLICATES pxd_dependencies )
+  list( REMOVE_DUPLICATES c_header_dependencies )
+
+  # Add the command to run the compiler.
+  add_custom_command( OUTPUT ${_generated_file}
+    COMMAND ${CYTHON_EXECUTABLE}
+    ARGS ${cxx_arg} ${include_directory_arg} ${version_arg}
+    ${annotate_arg} ${no_docstrings_arg} ${cython_debug_arg} ${CYTHON_FLAGS}
+    --output-file  ${_generated_file} ${pyx_locations}
+    DEPENDS ${pyx_locations} ${pxd_dependencies} ${pxi_dependencies}
+    IMPLICIT_DEPENDS ${pyx_lang} ${c_header_dependencies}
+    COMMENT ${comment}
+    )
+
+  # Remove their visibility to the user.
+  set( corresponding_pxd_file "" CACHE INTERNAL "" )
+  set( header_location "" CACHE INTERNAL "" )
+  set( pxd_location "" CACHE INTERNAL "" )
+endfunction()
+
+# cython_add_module( <name> src1 src2 ... srcN )
+# Build the Cython Python module.
+function( cython_add_module _name c_cxx_output_subdir)
+  set( pyx_module_sources "" )
+  set( other_module_sources "" )
+  foreach( _file ${ARGN} )
+    if( ${_file} MATCHES ".*\\.py[x]?$" )
+      list( APPEND pyx_module_sources ${_file} )
+    else()
+      list( APPEND other_module_sources ${_file} )
+    endif()
+  endforeach()
+  compile_pyx( ${_name} ${c_cxx_output_subdir} generated_file 
${pyx_module_sources} )
+  include_directories( ${PYTHON_INCLUDE_DIRS} )
+  python_add_module( ${_name} ${generated_file} ${other_module_sources} )
+  if( APPLE )
+    set_target_properties( ${_name} PROPERTIES LINK_FLAGS "-undefined 
dynamic_lookup" )
+  else()
+    target_link_libraries( ${_name} ${PYTHON_LIBRARIES} )
+  endif()
+endfunction()
+
+include( CMakeParseArguments )
+# cython_add_standalone_executable( _name [MAIN_MODULE src3.py] src1 src2 ... 
srcN )
+# Creates a standalone executable the given sources.
+function( cython_add_standalone_executable _name )
+  set( pyx_module_sources "" )
+  set( other_module_sources "" )
+  set( main_module "" )
+  cmake_parse_arguments( cython_arguments "" "MAIN_MODULE" "" ${ARGN} )
+  include_directories( ${PYTHON_INCLUDE_DIRS} )
+  foreach( _file ${cython_arguments_UNPARSED_ARGUMENTS} )
+    if( ${_file} MATCHES ".*\\.py[x]?$" )
+      get_filename_component( _file_we ${_file} NAME_WE )
+      if( "${_file_we}" STREQUAL "${_name}" )
+        set( main_module "${_file}" )
+      elseif( NOT "${_file}" STREQUAL "${cython_arguments_MAIN_MODULE}" )
+        set( PYTHON_MODULE_${_file_we}_static_BUILD_SHARED OFF )
+        compile_pyx( "${_file_we}_static" generated_file "${_file}" )
+        list( APPEND pyx_module_sources "${generated_file}" )
+      endif()
+    else()
+      list( APPEND other_module_sources ${_file} )
+    endif()
+  endforeach()
+
+  if( cython_arguments_MAIN_MODULE )
+    set( main_module ${cython_arguments_MAIN_MODULE} )
+  endif()
+  if( NOT main_module )
+    message( FATAL_ERROR "main module not found." )
+  endif()
+  get_filename_component( main_module_we "${main_module}" NAME_WE )
+  set( CYTHON_FLAGS ${CYTHON_FLAGS} --embed )
+  compile_pyx( "${main_module_we}_static" generated_file ${main_module} )
+  add_executable( ${_name} ${generated_file} ${pyx_module_sources} 
${other_module_sources} )
+  target_link_libraries( ${_name} ${PYTHON_LIBRARIES} ${pyx_module_libs} )
+endfunction()
diff --git a/python/mxnet/cython/__init__.py b/python/mxnet/cython/__init__.py
new file mode 100644
index 00000000000..13a83393a91
--- /dev/null
+++ b/python/mxnet/cython/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/python/mxnet/cython/mxcython.pyx b/python/mxnet/cython/mxcython.pyx
new file mode 100644
index 00000000000..4f0bd1395e0
--- /dev/null
+++ b/python/mxnet/cython/mxcython.pyx
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import absolute_import as _abs
+
+import sys as _sys
+import ctypes as _ctypes
+import numpy as np
+from ..ndarray_doc import _build_doc
+from libc.stdint cimport uint32_t, int64_t
+
+include "./base.pyi"
+
+cdef class CythonTestClass:
+    """Symbol is symbolic graph."""
+    # handle for symbolic operator.
+    cdef int cwritable
+
+    def __init__(self):
+        self.cwritable = 99
+
+    def print_something(self, char *the_string):
+      print('CythonTestClass::print_something( {} )'.format(the_string))
+
+def print_pi(terms):
+    print(float(0.0))
+
diff --git a/python/setup.py b/python/setup.py
index cf94adf982d..320001fc980 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -31,10 +31,13 @@
     kwargs = {'install_requires': ['numpy<=1.13.3,>=1.8.2', 
'requests==2.18.4', 'graphviz==0.8.1'], 'zip_safe': False}
 from setuptools import find_packages
 
-with_cython = False
+with_cython = True
 if '--with-cython' in sys.argv:
     with_cython = True
     sys.argv.remove('--with-cython')
+if '--without-cython' in sys.argv:
+    with_cython = False
+    sys.argv.remove('--without-cython')
 
 # We can not import `mxnet.info.py` in setup.py directly since 
mxnet/__init__.py
 # Will be invoked which introduces dependences
diff --git a/src/cython/cy2/CMakeLists.txt b/src/cython/cy2/CMakeLists.txt
new file mode 100644
index 00000000000..cfc132f950f
--- /dev/null
+++ b/src/cython/cy2/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+cmake_minimum_required(VERSION 3.0.2)
+
+project(cy2 C CXX)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/CythonUtil.cmake)
+
+mxnet_build_cython_module(2)
diff --git a/src/cython/cy3/CMakeLists.txt b/src/cython/cy3/CMakeLists.txt
new file mode 100644
index 00000000000..e353685ae02
--- /dev/null
+++ b/src/cython/cy3/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+cmake_minimum_required(VERSION 3.0.2)
+
+project(cy3 C CXX)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/CythonUtil.cmake)
+
+mxnet_build_cython_module(3)
diff --git a/src/cython/cython_ndarray.cc b/src/cython/cython_ndarray.cc
new file mode 100644
index 00000000000..bd244d07ab4
--- /dev/null
+++ b/src/cython/cython_ndarray.cc
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
diff --git a/tests/python/unittest/test_cython.py 
b/tests/python/unittest/test_cython.py
new file mode 100644
index 00000000000..e53f913bf24
--- /dev/null
+++ b/tests/python/unittest/test_cython.py
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from __future__ import print_function
+import sys
+import mxnet._cy2.mxcython as mxc
+import mxnet._cy2.ndarray as ndc
+import mxnet._cy2.symbol as symc
+
+def test_basic_cython():
+  print('ENTER test_basic_cython')
+  myclass = mxc.CythonTestClass()
+  for terms in 5, 9, 23, 177, 1111, 33333, 555555:
+    sys.stdout.write('{0:10} terms: '.format(terms))
+    mxc.print_pi(terms)
+  myclass.print_something('Something')
+  print('EXIT test_basic_cython')
+
+if __name__ == '__main__':
+  # import nose
+  # nose.runmodule()
+  test_basic_cython()


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to