blob: 22a7c7d0f441a036b183189bb3518e57d716a19b [file] [log] [blame]
#
# 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.
#
# This following function is taken from
# https://github.com/Kitware/CMake/blob/master/Modules/FindProtobuf.cmake
# and modified to our compilation.
function(PROTOBUF_GENERATE_PYTHON OUTPUT)
if(NOT ARGN)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called
without any proto files")
return()
endif(NOT ARGN)
set(${OUTPUT})
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
get_filename_component(PATH ${FIL} PATH)
list(APPEND ${OUTPUT} "${CMAKE_BINARY_DIR}/python/singa/proto/${FIL_WE}_pb2.py")
add_custom_command(
OUTPUT "${CMAKE_BINARY_DIR}/python/singa/proto/${FIL_WE}_pb2.py"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --python_out ${CMAKE_BINARY_DIR}/python/singa/proto
--proto_path ${PATH} ${ABS_FIL}
DEPENDS ${ABS_FIL}
COMMENT "Running Python protocol buffer compiler on ${FIL}" VERBATIM)
endforeach()
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
set(${OUTPUT} ${${OUTPUT}} PARENT_SCOPE)
endfunction()
function (create_symlinks)
# Do nothing if building in-source
if (${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR})
return()
endif()
foreach (path_file ${ARGN})
get_filename_component(folder ${path_file} PATH)
# Create REAL folder
#file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/${folder}")
# Delete symlink if it exists
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/${path_file}")
# Get OS dependent path to use in `execute_process`
file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${path_file}" link)
file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${path_file}" target)
if (UNIX)
set(command ln -s ${target} ${link})
else()
set(command cmd.exe /c mklink ${link} ${target})
endif()
execute_process(COMMAND ${command}
RESULT_VARIABLE result
ERROR_VARIABLE output)
if (NOT ${result} EQUAL 0)
message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
endif()
endforeach(path_file)
endfunction(create_symlinks)
# generate protobuf sources
FILE(GLOB proto_files ${CMAKE_SOURCE_DIR}/src/proto/*.proto)
PROTOBUF_GENERATE_PYTHON(proto_pys ${proto_files})
#MESSAGE(STATUS "proto pys: ${proto_pys}")
# generate cxx and wrap.py
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python/singa/proto)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python/rafiki)
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/src/api)
IF(USE_PYTHON3)
SET(SWIG_PYTHON3 "-py3")
ELSE()
SET(SWIG_PYTHON3 "")
ENDIF()
execute_process(
COMMAND swig -c++ -python ${SWIG_PYTHON3} -I${CMAKE_SOURCE_DIR}/include
-outdir ${CMAKE_BINARY_DIR}/python/singa
-o ${CMAKE_BINARY_DIR}/src/api/singa_wrap.cxx
${CMAKE_SOURCE_DIR}/src/api/singa.i)
set(python_srcs "${CMAKE_BINARY_DIR}/src/api/singa_wrap.cxx")
#Create symlinks for all python source files Do not omit !!!RELATIVE!!!
file(GLOB_RECURSE python_source_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.py)
create_symlinks(${python_source_files})
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "from __future__ import print_function; import numpy; print(numpy.get_include())"
OUTPUT_VARIABLE NUMPY_INCLUDE_DIR)
#message(status "numpy path ${NUMPY_INCLUDE_DIR}")
IF(USE_CUDA)
# remain this custom command to avoid cuda objs can't find
ADD_CUSTOM_COMMAND(
OUTPUT ${global_cuda_objs}
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/"
)
ENDIF(USE_CUDA)
ADD_LIBRARY(_singa_wrap SHARED $<TARGET_OBJECTS:singa_objects> ${python_srcs} ${proto_pys} ${global_cuda_objs})
# For MacOS Python3.6 is already linked into python executable, hence no need to link python3.6 into Singa.
IF(APPLE)
TARGET_LINK_LIBRARIES(_singa_wrap ${SINGA_LINKER_LIBS})
SET_TARGET_PROPERTIES(_singa_wrap PROPERTIES PREFIX ""
LINK_FLAGS "-undefined dynamic_lookup"
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python/singa)
ELSE()
TARGET_LINK_LIBRARIES(_singa_wrap ${SINGA_LINKER_LIBS} ${PYTHON_LIBRARIES})
SET_TARGET_PROPERTIES(_singa_wrap PROPERTIES PREFIX "" LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python/singa)
ENDIF()
TARGET_INCLUDE_DIRECTORIES(_singa_wrap PRIVATE ${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIR})
# substitute ${var} in setup.py.in to generate setup.py
SET(SETUP_PY_IN "setup.py.in")
SET(SETUP_PY "${CMAKE_BINARY_DIR}/python/setup.py")
CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY})
#create python/singa/proto/__init__.py
FILE(WRITE ${CMAKE_BINARY_DIR}/python/singa/proto/__init__.py "")
IF(APPLE)
ADD_CUSTOM_TARGET(
change_suffix ALL
COMMAND ${CMAKE_COMMAND} -E rename "${CMAKE_BINARY_DIR}/python/singa/_singa_wrap.dylib" "${CMAKE_BINARY_DIR}/python/singa/_singa_wrap.so"
COMMENT "change .dylib to .so in mac system"
)
ADD_DEPENDENCIES(change_suffix _singa_wrap)
ENDIF(APPLE)