protobuf.cmake 10.1 KB
Newer Older
L
liaogang 已提交
1
# Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve.
2
#
L
liaogang 已提交
3 4 5
# 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
6
#
L
liaogang 已提交
7
# http://www.apache.org/licenses/LICENSE-2.0
8
#
L
liaogang 已提交
9 10 11 12 13 14 15
# 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.

INCLUDE(ExternalProject)
Y
Yu Yang 已提交
16 17 18 19
# Always invoke `FIND_PACKAGE(Protobuf)` for importing function protobuf_generate_cpp
FIND_PACKAGE(Protobuf QUIET)
SET(PROTOBUF_FOUND "OFF")

20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
if(NOT COMMAND protobuf_generate_python)  # before cmake 3.4, protobuf_genrerate_python is not defined.
    function(protobuf_generate_python SRCS)
        # shameless copy from https://github.com/Kitware/CMake/blob/master/Modules/FindProtobuf.cmake
        if(NOT ARGN)
            message(SEND_ERROR "Error: PROTOBUF_GENERATE_PYTHON() called without any proto files")
            return()
        endif()

        if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
            # Create an include path for each file specified
            foreach(FIL ${ARGN})
                get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
                get_filename_component(ABS_PATH ${ABS_FIL} PATH)
                list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
                if(${_contains_already} EQUAL -1)
                    list(APPEND _protobuf_include_path -I ${ABS_PATH})
                endif()
            endforeach()
        else()
            set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
        endif()

        if(DEFINED PROTOBUF_IMPORT_DIRS AND NOT DEFINED Protobuf_IMPORT_DIRS)
            set(Protobuf_IMPORT_DIRS "${PROTOBUF_IMPORT_DIRS}")
        endif()

        if(DEFINED Protobuf_IMPORT_DIRS)
            foreach(DIR ${Protobuf_IMPORT_DIRS})
                get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
                list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
                if(${_contains_already} EQUAL -1)
                    list(APPEND _protobuf_include_path -I ${ABS_PATH})
                endif()
            endforeach()
        endif()

        set(${SRCS})
        foreach(FIL ${ARGN})
            get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
            get_filename_component(FIL_WE ${FIL} NAME_WE)
            if(NOT PROTOBUF_GENERATE_CPP_APPEND_PATH)
                get_filename_component(FIL_DIR ${FIL} DIRECTORY)
                if(FIL_DIR)
                    set(FIL_WE "${FIL_DIR}/${FIL_WE}")
                endif()
            endif()

            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} --python_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
                    DEPENDS ${ABS_FIL} ${Protobuf_PROTOC_EXECUTABLE}
                    COMMENT "Running Python protocol buffer compiler on ${FIL}"
                    VERBATIM )
        endforeach()

        set(${SRCS} ${${SRCS}} PARENT_SCOPE)
    endfunction()
endif()
L
liaogang 已提交
79

80 81
# Print and set the protobuf library information,
# finish this cmake process and exit from this file.
Y
Yu Yang 已提交
82
macro(PROMPT_PROTOBUF_LIB)
83 84
    SET(protobuf_DEPS ${ARGN})

Y
Yu Yang 已提交
85 86
    MESSAGE(STATUS "Protobuf protoc executable: ${PROTOBUF_PROTOC_EXECUTABLE}")
    MESSAGE(STATUS "Protobuf library: ${PROTOBUF_LIBRARY}")
87
    MESSAGE(STATUS "Protobuf version: ${PROTOBUF_VERSION}")
Y
Yu Yang 已提交
88
    INCLUDE_DIRECTORIES(${PROTOBUF_INCLUDE_DIR})
89 90

    # Assuming that all the protobuf libraries are of the same type.
91
    IF(${PROTOBUF_LIBRARY} MATCHES "${CMAKE_STATIC_LIBRARY_SUFFIX}$")
92
        SET(protobuf_LIBTYPE STATIC)
93
    ELSEIF(${PROTOBUF_LIBRARY} MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$")
94 95 96 97 98 99 100 101 102 103 104
        SET(protobuf_LIBTYPE SHARED)
    ELSE()
        MESSAGE(FATAL_ERROR "Unknown library type: ${PROTOBUF_LIBRARY}")
    ENDIF()

    ADD_LIBRARY(protobuf ${protobuf_LIBTYPE} IMPORTED GLOBAL)
    SET_PROPERTY(TARGET protobuf PROPERTY IMPORTED_LOCATION ${PROTOBUF_LIBRARY})

    ADD_LIBRARY(protobuf_lite ${protobuf_LIBTYPE} IMPORTED GLOBAL)
    SET_PROPERTY(TARGET protobuf_lite PROPERTY IMPORTED_LOCATION ${PROTOBUF_LITE_LIBRARY})

Y
Yu Yang 已提交
105 106 107 108 109
    ADD_LIBRARY(libprotoc ${protobuf_LIBTYPE} IMPORTED GLOBAL)
    SET_PROPERTY(TARGET libprotoc PROPERTY IMPORTED_LOCATION ${PROTOC_LIBRARY})

    ADD_EXECUTABLE(protoc IMPORTED GLOBAL)
    SET_PROPERTY(TARGET protoc PROPERTY IMPORTED_LOCATION ${PROTOBUF_PROTOC_EXECUTABLE})
Y
Yu Yang 已提交
110 111 112
    # FIND_Protobuf.cmake uses `Protobuf_PROTOC_EXECUTABLE`.
    # make `protobuf_generate_cpp` happy.
    SET(Protobuf_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE})
113 114 115 116

    FOREACH(dep ${protobuf_DEPS})
        ADD_DEPENDENCIES(protobuf ${dep})
        ADD_DEPENDENCIES(protobuf_lite ${dep})
Y
Yu Yang 已提交
117
        ADD_DEPENDENCIES(libprotoc ${dep})
118 119 120 121
        ADD_DEPENDENCIES(protoc ${dep})
    ENDFOREACH()

    LIST(APPEND external_project_dependencies protobuf)
Y
Yu Yang 已提交
122 123
    RETURN()
endmacro()
124 125 126 127
macro(SET_PROTOBUF_VERSION)
    EXEC_PROGRAM(${PROTOBUF_PROTOC_EXECUTABLE} ARGS --version OUTPUT_VARIABLE PROTOBUF_VERSION)
    STRING(REGEX MATCH "[0-9]+.[0-9]+" PROTOBUF_VERSION "${PROTOBUF_VERSION}")
endmacro()
Y
Yu Yang 已提交
128 129 130 131 132 133 134 135

set(PROTOBUF_ROOT "" CACHE PATH "Folder contains protobuf")
if (NOT "${PROTOBUF_ROOT}" STREQUAL "")
    find_path(PROTOBUF_INCLUDE_DIR google/protobuf/message.h PATHS ${PROTOBUF_ROOT}/include)
    find_library(PROTOBUF_LIBRARY protobuf PATHS ${PROTOBUF_ROOT}/lib)
    find_library(PROTOBUF_LITE_LIBRARY protobuf-lite PATHS ${PROTOBUF_ROOT}/lib)
    find_library(PROTOBUF_PROTOC_LIBRARY protoc PATHS ${PROTOBUF_ROOT}/lib)
    find_program(PROTOBUF_PROTOC_EXECUTABLE protoc PATHS ${PROTOBUF_ROOT}/bin)
Y
Yu Yang 已提交
136
    if (PROTOBUF_INCLUDE_DIR AND PROTOBUF_LIBRARY AND PROTOBUF_LITE_LIBRARY AND PROTOBUF_PROTOC_LIBRARY AND PROTOBUF_PROTOC_EXECUTABLE)
Y
Yu Yang 已提交
137
        message(STATUS "Using custom protobuf library in ${PROTOBUF_ROOT}.")
138
        SET_PROTOBUF_VERSION()
Y
Yu Yang 已提交
139 140 141 142 143 144
        PROMPT_PROTOBUF_LIB()
    else()
        message(WARNING "Cannot find protobuf library in ${PROTOBUF_ROOT}.")
    endif()
endif()

145
FUNCTION(build_protobuf TARGET_NAME BUILD_FOR_HOST)
146 147 148
    STRING(REPLACE "extern_" "" TARGET_DIR_NAME "${TARGET_NAME}")
    SET(PROTOBUF_SOURCES_DIR ${THIRD_PARTY_PATH}/${TARGET_DIR_NAME})
    SET(PROTOBUF_INSTALL_DIR ${THIRD_PARTY_PATH}/install/${TARGET_DIR_NAME})
L
liaogang 已提交
149

150
    SET(${TARGET_NAME}_INCLUDE_DIR "${PROTOBUF_INSTALL_DIR}/include" PARENT_SCOPE)
151
    SET(PROTOBUF_INCLUDE_DIR "${PROTOBUF_INSTALL_DIR}/include" PARENT_SCOPE)
152
    SET(${TARGET_NAME}_LITE_LIBRARY
153
        "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf-lite${CMAKE_STATIC_LIBRARY_SUFFIX}"
154 155
         PARENT_SCOPE)
    SET(${TARGET_NAME}_LIBRARY
156
        "${PROTOBUF_INSTALL_DIR}/lib/libprotobuf${CMAKE_STATIC_LIBRARY_SUFFIX}"
157 158
         PARENT_SCOPE)
    SET(${TARGET_NAME}_PROTOC_LIBRARY
159
        "${PROTOBUF_INSTALL_DIR}/lib/libprotoc${CMAKE_STATIC_LIBRARY_SUFFIX}"
160 161
         PARENT_SCOPE)
    SET(${TARGET_NAME}_PROTOC_EXECUTABLE
162
        "${PROTOBUF_INSTALL_DIR}/bin/protoc${CMAKE_EXECUTABLE_SUFFIX}"
163
         PARENT_SCOPE)
164

165 166 167 168 169 170 171 172 173 174 175
    SET(OPTIONAL_CACHE_ARGS "")
    SET(OPTIONAL_ARGS "")
    IF(BUILD_FOR_HOST)
        SET(OPTIONAL_ARGS "-Dprotobuf_WITH_ZLIB=OFF")
    ELSE()
        SET(OPTIONAL_ARGS
            "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
            "-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
            "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}"
            "-DCMAKE_C_FLAGS=${CMAKE_C_FLAGS}"
            "-Dprotobuf_WITH_ZLIB=ON"
176 177
            "-DZLIB_ROOT:FILEPATH=${ZLIB_ROOT}"
            ${EXTERNAL_OPTIONAL_ARGS})
178 179
        SET(OPTIONAL_CACHE_ARGS "-DZLIB_ROOT:STRING=${ZLIB_ROOT}")
    ENDIF()
L
liaogang 已提交
180

181
    ExternalProject_Add(
182
        ${TARGET_NAME}
183 184 185 186 187 188 189
        ${EXTERNAL_PROJECT_LOG_ARGS}
        PREFIX          ${PROTOBUF_SOURCES_DIR}
        UPDATE_COMMAND  ""
        DEPENDS         zlib
        GIT_REPOSITORY  "https://github.com/google/protobuf.git"
        GIT_TAG         "9f75c5aa851cd877fb0d93ccc31b8567a6706546"
        CONFIGURE_COMMAND
190 191
        ${CMAKE_COMMAND} ${PROTOBUF_SOURCES_DIR}/src/${TARGET_NAME}/cmake
            ${OPTIONAL_ARGS}
L
liaogang 已提交
192 193
            -Dprotobuf_BUILD_TESTS=OFF
            -DCMAKE_POSITION_INDEPENDENT_CODE=ON
194
            -DCMAKE_BUILD_TYPE=${THIRD_PARTY_BUILD_TYPE}
L
liaogang 已提交
195 196 197
            -DCMAKE_INSTALL_PREFIX=${PROTOBUF_INSTALL_DIR}
            -DCMAKE_INSTALL_LIBDIR=lib
        CMAKE_CACHE_ARGS
L
liaogang 已提交
198
            -DCMAKE_INSTALL_PREFIX:PATH=${PROTOBUF_INSTALL_DIR}
199
            -DCMAKE_BUILD_TYPE:STRING=${THIRD_PARTY_BUILD_TYPE}
L
liaogang 已提交
200 201
            -DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF
            -DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
202
            ${OPTIONAL_CACHE_ARGS}
203
    )
204 205
ENDFUNCTION()

206
SET(PROTOBUF_VERSION 3.1)
207
IF(CMAKE_CROSSCOMPILING)
208
    build_protobuf(protobuf_host TRUE)
209 210
    LIST(APPEND external_project_dependencies protobuf_host)

211 212 213 214 215
    SET(PROTOBUF_PROTOC_EXECUTABLE ${protobuf_host_PROTOC_EXECUTABLE}
        CACHE FILEPATH "protobuf executable." FORCE)
ENDIF()

IF(NOT PROTOBUF_FOUND)
216
    build_protobuf(extern_protobuf FALSE)
217

218
    SET(PROTOBUF_INCLUDE_DIR ${extern_protobuf_INCLUDE_DIR}
219
        CACHE PATH "protobuf include directory." FORCE)
220 221 222 223 224 225 226
    SET(PROTOBUF_LITE_LIBRARY ${extern_protobuf_LITE_LIBRARY}
        CACHE FILEPATH "protobuf lite library." FORCE)
    SET(PROTOBUF_LIBRARY ${extern_protobuf_LIBRARY}
        CACHE FILEPATH "protobuf library." FORCE)
    SET(PROTOBUF_PROTOC_LIBRARY ${extern_protobuf_PROTOC_LIBRARY}
        CACHE FILEPATH "protoc library." FORCE)

227 228 229 230 231 232 233 234 235
    IF(WITH_C_API)
        INSTALL(DIRECTORY ${PROTOBUF_INCLUDE_DIR} DESTINATION third_party/protobuf)
        IF(ANDROID)
            INSTALL(FILES ${PROTOBUF_LIBRARY} DESTINATION third_party/protobuf/lib/${ANDROID_ABI})
        ELSE()
            INSTALL(FILES ${PROTOBUF_LIBRARY} DESTINATION third_party/protobuf/lib)
        ENDIF()
    ENDIF()

236 237 238 239
    IF(CMAKE_CROSSCOMPILING)
        PROMPT_PROTOBUF_LIB(protobuf_host extern_protobuf)
    ELSE()
        SET(PROTOBUF_PROTOC_EXECUTABLE ${extern_protobuf_PROTOC_EXECUTABLE}
240
            CACHE FILEPATH "protobuf executable." FORCE)
241
        PROMPT_PROTOBUF_LIB(extern_protobuf)
242
    ENDIF()
243
ENDIF(NOT PROTOBUF_FOUND)