Fix CMake build of pycaffe
authormax argus <argus.max@gmail.com>
Sat, 4 Oct 2014 11:46:38 +0000 (11:46 +0000)
committermax argus <argus.max@gmail.com>
Wed, 8 Oct 2014 22:44:28 +0000 (22:44 +0000)
- generate right shared library name
- fix CMake linking with the new layer factory
- find numpy

Fix finding protobuf.

CMakeScripts/FindNumPy.cmake [new file with mode: 0644]
CMakeScripts/FindProtobuf.cmake [new file with mode: 0644]
python/CMakeLists.txt
src/caffe/proto/CMakeLists.txt

diff --git a/CMakeScripts/FindNumPy.cmake b/CMakeScripts/FindNumPy.cmake
new file mode 100644 (file)
index 0000000..baf2154
--- /dev/null
@@ -0,0 +1,103 @@
+# - Find the NumPy libraries
+# This module finds if NumPy is installed, and sets the following variables
+# indicating where it is.
+#
+# TODO: Update to provide the libraries and paths for linking npymath lib.
+#
+#  NUMPY_FOUND               - was NumPy found
+#  NUMPY_VERSION             - the version of NumPy found as a string
+#  NUMPY_VERSION_MAJOR       - the major version number of NumPy
+#  NUMPY_VERSION_MINOR       - the minor version number of NumPy
+#  NUMPY_VERSION_PATCH       - the patch version number of NumPy
+#  NUMPY_VERSION_DECIMAL     - e.g. version 1.6.1 is 10601
+#  NUMPY_INCLUDE_DIRS        - path to the NumPy include files
+
+#============================================================================
+# Copyright 2012 Continuum Analytics, Inc.
+#
+# MIT License
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#============================================================================
+
+# Finding NumPy involves calling the Python interpreter
+if(NumPy_FIND_REQUIRED)
+    find_package(PythonInterp REQUIRED)
+else()
+    find_package(PythonInterp)
+endif()
+
+if(NOT PYTHONINTERP_FOUND)
+    set(NUMPY_FOUND FALSE)
+    return()
+endif()
+
+execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
+    "import numpy as n; print(n.__version__); print(n.get_include());"
+    RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS
+    OUTPUT_VARIABLE _NUMPY_VALUES_OUTPUT
+    ERROR_VARIABLE _NUMPY_ERROR_VALUE
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0)
+    if(NumPy_FIND_REQUIRED)
+        message(FATAL_ERROR
+            "NumPy import failure:\n${_NUMPY_ERROR_VALUE}")
+    endif()
+    set(NUMPY_FOUND FALSE)
+    return()
+endif()
+
+# Convert the process output into a list
+string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES_OUTPUT})
+string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES})
+# Just in case there is unexpected output from the Python command.
+list(GET _NUMPY_VALUES -2 NUMPY_VERSION)
+list(GET _NUMPY_VALUES -1 NUMPY_INCLUDE_DIRS)
+
+string(REGEX MATCH "^[0-9]+\\.[0-9]+\\.[0-9]+" _VER_CHECK "${NUMPY_VERSION}")
+if("${_VER_CHECK}" STREQUAL "")
+    # The output from Python was unexpected. Raise an error always
+    # here, because we found NumPy, but it appears to be corrupted somehow.
+    message(FATAL_ERROR
+        "Requested version and include path from NumPy, got instead:\n${_NUMPY_VALUES_OUTPUT}\n")
+    return()
+endif()
+
+# Make sure all directory separators are '/'
+string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS})
+
+# Get the major and minor version numbers
+string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION})
+list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR)
+list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR)
+list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH)
+string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH})
+math(EXPR NUMPY_VERSION_DECIMAL
+    "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}")
+
+find_package_message(NUMPY
+    "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}"
+    "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}")
+
+set(NUMPY_FOUND TRUE)
+
+
diff --git a/CMakeScripts/FindProtobuf.cmake b/CMakeScripts/FindProtobuf.cmake
new file mode 100644 (file)
index 0000000..0f94f49
--- /dev/null
@@ -0,0 +1,152 @@
+# Locate and configure the Google Protocol Buffers library.
+# Defines the following variables:
+#
+#   PROTOBUF_FOUND - Found the Google Protocol Buffers library
+#   PROTOBUF_INCLUDE_DIRS - Include directories for Google Protocol Buffers
+#   PROTOBUF_LIBRARIES - The protobuf library
+#
+# The following cache variables are also defined:
+#   PROTOBUF_LIBRARY - The protobuf library
+#   PROTOBUF_PROTOC_LIBRARY   - The protoc library
+#   PROTOBUF_INCLUDE_DIR - The include directory for protocol buffers
+#   PROTOBUF_PROTOC_EXECUTABLE - The protoc compiler
+#
+#  ====================================================================
+#  Example:
+#
+#   find_package(Protobuf REQUIRED)
+#   include_directories(${PROTOBUF_INCLUDE_DIRS})
+#
+#   include_directories(${CMAKE_CURRENT_BINARY_DIR})
+#   PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS foo.proto)
+#   add_executable(bar bar.cc ${PROTO_SRCS} ${PROTO_HDRS})
+#   target_link_libraries(bar ${PROTOBUF_LIBRARY})
+#
+# NOTE: You may need to link against pthreads, depending
+# on the platform.
+#  ====================================================================
+#
+# PROTOBUF_GENERATE_CPP (public function)
+#   SRCS = Variable to define with autogenerated
+#          source files
+#   HDRS = Variable to define with autogenerated
+#          header files
+#   ARGN = proto files
+#
+#  ====================================================================
+
+
+#=============================================================================
+# Copyright 2009 Kitware, Inc.
+# Copyright 2009 Philip Lowman <philip@yhbt.com>
+# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distributed this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+function(PROTOBUF_GENERATE_PYTHON SRCS)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
+    return()
+  endif(NOT ARGN)
+
+  set(${SRCS})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+    
+    
+    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py")
+
+    add_custom_command(
+      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}_pb2.py"
+      COMMAND  ${PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS --python_out  ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} 
+${ABS_FIL}
+      DEPENDS ${ABS_FIL}
+      COMMENT "Running Python protocol buffer compiler on ${FIL}"
+      VERBATIM )
+  endforeach()
+
+
+  set_source_files_properties(${${SRCS}} PROPERTIES GENERATED TRUE)
+  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+endfunction()
+
+
+function(PROTOBUF_GENERATE_CPP SRCS HDRS)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
+    return()
+  endif(NOT ARGN)
+
+  set(${SRCS})
+  set(${HDRS})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+    
+    list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
+    list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
+
+    add_custom_command(
+      OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
+             "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
+      COMMAND  ${PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} 
+${ABS_FIL}
+      DEPENDS ${ABS_FIL}
+      COMMENT "Running C++ protocol buffer compiler on ${FIL}"
+      VERBATIM )
+  endforeach()
+
+  set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
+  set(${SRCS} ${${SRCS}} PARENT_SCOPE)
+  set(${HDRS} ${${HDRS}} PARENT_SCOPE)
+endfunction()
+
+
+find_path(PROTOBUF_INCLUDE_DIR google/protobuf/service.h)
+
+# Google's provided vcproj files generate libraries with a "lib"
+# prefix on Windows
+if(WIN32)
+    set(PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES "${CMAKE_FIND_LIBRARY_PREFIXES}")
+    set(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
+endif()
+
+find_library(PROTOBUF_LIBRARY NAMES protobuf
+             DOC "The Google Protocol Buffers Library"
+)
+find_library(PROTOBUF_PROTOC_LIBRARY NAMES protoc
+             DOC "The Google Protocol Buffers Compiler Library"
+)
+find_program(PROTOBUF_PROTOC_EXECUTABLE NAMES protoc
+             DOC "The Google Protocol Buffers Compiler"
+)
+
+mark_as_advanced(PROTOBUF_INCLUDE_DIR
+                 PROTOBUF_LIBRARY
+                 PROTOBUF_PROTOC_LIBRARY
+                 PROTOBUF_PROTOC_EXECUTABLE)
+
+# Restore original find library prefixes
+if(WIN32)
+    set(CMAKE_FIND_LIBRARY_PREFIXES "${PROTOBUF_ORIG_FIND_LIBRARY_PREFIXES}")
+endif()
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(PROTOBUF DEFAULT_MSG
+    PROTOBUF_LIBRARY PROTOBUF_INCLUDE_DIR)
+
+if(PROTOBUF_FOUND)
+    set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIR})
+    set(PROTOBUF_LIBRARIES    ${PROTOBUF_LIBRARY})
+endif()
index 343c863..6470517 100644 (file)
@@ -1,20 +1,58 @@
 project( Python )
 
 #    Python
-find_package(PythonLibs REQUIRED)
-include_directories(${PYTHON_INCLUDE_DIRS})
+find_package(PythonLibs 2.7 REQUIRED)
+
+#   Numpy
+find_package(NumPy REQUIRED)
 
 #    Boost.Python
 find_package(Boost 1.46 COMPONENTS python REQUIRED)
-include_directories(${Boost_INCLUDE_DIRS})
+
+
+
+#In case you have both python2 and python3 installed the quickest way to
+#compile pycaffe with cmake is to replace the following hardcoded paths.
+#Althernativley the Find* scripts could be rewritten to support choice of
+#of python version.
+#if(${PYTHONLIBS_VERSION_STRING} MATCHES "^[3-9]+\\.[0-9]+(\\.[0-9]+.*)?$") 
+#    
+#    set( PYTHON_INCLUDE_DIRS "/usr/include/python2.7")
+#    set( PYTHON_LIBRARIES    "/usr/lib64/libpython2.7.so")
+#    set( NUMPY_INCLUDE_DIRS  "/usr/lib64/python2.7/site-packages/numpy/core/include/")
+#    set( PYTHON_LIBRARIES    "/usr/lib64/python2.7/site-packages/numpy/lib/")
+#    set(Boost_LIBRARIES      "/usr/lib64/libboost_python-2.7-mt.so")
+#
+#    message( "Warning: cmake found python3 by default, switching to hardcoded paths")
+#
+#    message( "PYTHON_INCLUDE_DIRS =/usr/include/python2.7")
+#    message( "PYTHON_LIBRARIES    =/usr/lib64/libpython2.7.so")
+#    message( "NUMPY_INCLUDE_DIRS  =/usr/lib64/python2.7/site-packages/numpy/core/include/")
+#    message( "PYTHON_LIBRARIES    =/usr/lib64/python2.7/site-packages/numpy/lib/")
+#    message( "Boost_LIBRARIES     =/usr/lib64/libboost_python-2.7-mt.so")
+#endif()
+
+
+include_directories(${PYTHON_INCLUDE_DIRS} ${NUMPY_INCLUDE_DIRS}
+    ${Boost_INCLUDE_DIRS})
 
 file(GLOB_RECURSE Python_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
 
 add_library(pycaffe SHARED ${Python_SOURCES})
-target_link_libraries(pycaffe caffe ${PYTHON_LIBRARIES} ${Boost_LIBRARIES})
 
-###    Install    #################################################################################
+add_dependencies(pycaffe protoPy)
+
+target_link_libraries(pycaffe ${CAFFE_STATIC_LINK} ${PYTHON_LIBRARIES} ${Boost_LIBRARIES})
+
+set_target_properties(pycaffe PROPERTIES PREFIX "")
+set_target_properties(pycaffe PROPERTIES OUTPUT_NAME "_caffe")
+
+###    Install    #############################################################
 
 install(DIRECTORY caffe DESTINATION python)
 install(FILES requirements.txt DESTINATION python)
+
+#This installs a library named "libpycaffe.so"
 install(TARGETS pycaffe DESTINATION python/caffe)
+
+
index 186a856..12e7ce0 100644 (file)
@@ -14,11 +14,15 @@ endif()
 include_directories(${PROTOBUF_INCLUDE_DIR})
 file(GLOB ProtoFiles "${CMAKE_CURRENT_SOURCE_DIR}/*.proto")
 PROTOBUF_GENERATE_CPP(ProtoSources ProtoHeaders ${ProtoFiles})
+PROTOBUF_GENERATE_PYTHON(ProtoSourcesPy ${ProtoFiles})
+
+add_custom_target(protoPy DEPENDS ${ProtoSourcesPy})
 
 add_library(proto
         ${ProtoSources}
         ${ProtoHeaders}
-)
+        )
+   
 
 target_link_libraries(proto ${PROTOBUF_LIBRARIES})
 
@@ -35,3 +39,8 @@ foreach(header ${ProtoHeaders})
 )
 
 endforeach(header)
+
+file(WRITE __init__.py)
+install(PROGRAMS __init__.py       DESTINATION python/caffe/proto)
+install(PROGRAMS ${ProtoSourcesPy} DESTINATION python/caffe/proto)
+