| # |
| # 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) |