Add an option for Caffe2 to link with local protobuf. (#2306)

This commit is contained in:
Yangqing Jia 2018-03-19 14:36:53 -07:00 committed by GitHub
parent 56505007a2
commit e426a5dadd
4 changed files with 62 additions and 8 deletions

View file

@ -29,6 +29,9 @@ option(BUILD_DOCS "Build documentation" OFF)
option(BUILD_CUSTOM_PROTOBUF "If set, build Caffe2's own protobuf under third_party" OFF)
option(BUILD_PYTHON "Build Python binaries" ON)
option(BUILD_SHARED_LIBS "Build libcaffe2.so" ON)
cmake_dependent_option(
CAFFE2_LINK_LOCAL_PROTOBUF "If set, build protobuf inside libcaffe2.so." ON
"BUILD_SHARED_LIBS AND BUILD_CUSTOM_PROTOBUF" OFF)
cmake_dependent_option(
CAFFE2_USE_MSVC_STATIC_RUNTIME "Using MSVC static runtime libraries" ON
"NOT BUILD_SHARED_LIBS" OFF)

View file

@ -76,12 +76,38 @@ install(FILES ${PROJECT_BINARY_DIR}/caffe2/core/macros.h
# ---[ List of libraries to link with
add_library(caffe2_protos $<TARGET_OBJECTS:Caffe_PROTO> $<TARGET_OBJECTS:Caffe2_PROTO>)
add_dependencies(caffe2_protos Caffe_PROTO Caffe2_PROTO)
# TODO: enable using lite protobuf.
target_link_libraries(caffe2_protos PUBLIC protobuf::libprotobuf)
# If we are going to link protobuf locally inside caffe2 libraries, what we will do is
# to create a helper static library that always contains libprotobuf source files, and
# link the caffe2 related dependent libraries to it.
target_include_directories(caffe2_protos INTERFACE $<INSTALL_INTERFACE:include>)
# Reason for this public dependency is as follows:
# (1) Strictly speaking, we should not expose any Protobuf related functions. We should
# only use function interfaces wrapped with our own public API, and link protobuf
# locally.
# (2) However, currently across the Caffe2 codebase, we have extensive use of protobuf
# functionalities. For example, not only libcaffe2.so uses it, but also other
# binaries such as python extensions etc. As a result, we will have to have a
# transitive dependency to libprotobuf.
#
# Good thing is that, if we specify CAFFE2_LINK_LOCAL_PROTOBUF, then we do not need to
# separately deploy protobuf binaries - libcaffe2.so will contain all functionalities
# one needs. One can verify this via ldd.
#
# Todo item in the future includes:
# (1) Properly define public API that do not directly depend on protobuf itself.
# (2) expose the libprotobuf.a file for dependent libraries to link to.
# (3) build libprotobuf with -fvisibility=hidden to avoid version conflicts.
#
# What it means for users/developers?
# (1) Users: nothing affecting the users, other than the fact that CAFFE2_LINK_LOCAL_PROTOBUF
# avoids the need to deploy protobuf.
# (2) Developers: if one simply uses core caffe2 functionality without using protobuf,
# nothing changes. If one has a dependent library that uses protobuf, then one needs to
# have the right protobuf version as well as linking to libprotobuf.a.
target_link_libraries(caffe2_protos PUBLIC protobuf::libprotobuf)
install(TARGETS caffe2_protos EXPORT Caffe2Targets DESTINATION lib)
# Compile exposed libraries.

View file

@ -9,16 +9,33 @@ macro(custom_protobuf_find)
# so we turn it off here.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
endif()
# If we are building Caffe2 as shared libs, we will also build protobuf as
# shared libs.
set(protobuf_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
if (${CAFFE2_LINK_LOCAL_PROTOBUF})
# If we are going to link protobuf locally, we will need to turn off
# shared libs build for protobuf.
set(protobuf_BUILD_SHARED_LIBS OFF)
else()
# If we are building Caffe2 as shared libs, we will also build protobuf as
# shared libs.
set(protobuf_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
endif()
# We will make sure that protobuf and caffe2 uses the same msvc runtime.
set(protobuf_MSVC_STATIC_RUNTIME ${CAFFE2_USE_MSVC_STATIC_RUNTIME})
if (MSVC AND BUILD_SHARED_LIBS)
add_definitions(-DPROTOBUF_USE_DLLS)
endif()
if (${CAFFE2_LINK_LOCAL_PROTOBUF})
# We will need to build protobuf with -fPIC.
set(__caffe2_protobuf_cmake_fpic ${CMAKE_POSITION_INDEPENDENT_CODE})
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
endif()
add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/protobuf/cmake)
if (${CAFFE2_LINK_LOCAL_PROTOBUF})
set(CMAKE_POSITION_INDEPENDENT_CODE ${__caffe2_protobuf_cmake_fpic})
endif()
# Protobuf "namespaced" target is only added post protobuf 3.5.1. As a
# result, for older versions, we will manually add alias.
if (NOT TARGET protobuf::libprotobuf)
@ -32,9 +49,13 @@ endmacro()
# coded BUILD_CUSTOM_PROTOBUF, we will hard code the use of custom protobuf
# in the submodule.
if (ANDROID OR IOS)
message(STATUS
"For Android and iOS cross compilation, I am automatically using "
"custom protobuf under third party.")
if (NOT ${BUILD_CUSTOM_PROTOBUF})
message(WARNING
"For Android and iOS cross compilation, I am automatically using "
"custom protobuf under third party. Note that this behavior may "
"change in the future, and you will need to specify "
"-DBUILD_CUSTOM_PROTOBUF=ON explicitly.")
endif()
custom_protobuf_find()
# Unfortunately, new protobuf does not support libprotoc and protoc
# cross-compilation so we will need to exclude it.

View file

@ -20,6 +20,10 @@ function (caffe2_print_configuration_summary)
message(STATUS "")
message(STATUS " BUILD_BINARY : ${BUILD_BINARY}")
message(STATUS " BUILD_CUSTOM_PROTOBUF : ${BUILD_CUSTOM_PROTOBUF}")
if (${CAFFE2_LINK_LOCAL_PROTOBUF})
message(STATUS " CAFFE2_LINK_LOCAL_PROTOBUF : ${CAFFE2_LINK_LOCAL_PROTOBUF}")
endif()
message(STATUS " BUILD_DOCS : ${BUILD_DOCS}")
message(STATUS " BUILD_PYTHON : ${BUILD_PYTHON}")
if (${BUILD_PYTHON})