blob: ac13f3d0601bafba1d4d044acc0aab0937dcbc2f [file]
# 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.
cmake_minimum_required(VERSION 3.16...3.28)
project(benchmark_fb LANGUAGES CXX)
set(BRPC_ROOT "" CACHE PATH "FlatBuffers-enabled brpc output or install prefix")
set(BRPC_EXTRA_LIBRARIES "" CACHE STRING "Extra dependencies of this libbrpc, as a CMake list")
option(LINK_SO "Link the shared brpc library instead of libbrpc.a" OFF)
if(NOT BRPC_ROOT)
message(FATAL_ERROR "Set BRPC_ROOT to an existing WITH_FLATBUFFERS=ON output/install prefix")
endif()
get_filename_component(BRPC_ROOT "${BRPC_ROOT}" ABSOLUTE)
set(BRPC_INCLUDE_DIR "${BRPC_ROOT}/include")
if(NOT EXISTS "${BRPC_INCLUDE_DIR}/brpc/channel.h" OR
NOT EXISTS "${BRPC_INCLUDE_DIR}/butil/config.h")
message(FATAL_ERROR "BRPC_ROOT must contain include/brpc/channel.h and include/butil/config.h")
endif()
file(STRINGS "${BRPC_INCLUDE_DIR}/butil/config.h" _fb_enabled
REGEX "^#[ \t]*define[ \t]+BRPC_WITH_FLATBUFFERS[ \t]+1([ \t]|$)")
if(NOT _fb_enabled)
message(FATAL_ERROR
"BRPC_ROOT is not FlatBuffers-enabled. Rebuild brpc with WITH_FLATBUFFERS=ON; do not force BRPC_WITH_FLATBUFFERS with -D.")
endif()
# Re-resolve when BRPC_ROOT or LINK_SO changes; never select another installed brpc.
unset(_BRPC_LIBRARY CACHE)
if(LINK_SO)
set(_brpc_names "${CMAKE_SHARED_LIBRARY_PREFIX}brpc${CMAKE_SHARED_LIBRARY_SUFFIX}")
else()
set(_brpc_names libbrpc.a)
endif()
find_library(_BRPC_LIBRARY NAMES ${_brpc_names}
PATHS "${BRPC_ROOT}/lib" "${BRPC_ROOT}/lib64" NO_DEFAULT_PATH)
if(NOT _BRPC_LIBRARY)
message(FATAL_ERROR "The requested brpc library was not found under BRPC_ROOT/lib or lib64")
endif()
find_path(FLATBUFFERS_INCLUDE_DIR NAMES flatbuffers/flatbuffers.h)
find_program(FLATC_EXECUTABLE NAMES flatc)
find_program(BRPC_FLATC_EXECUTABLE NAMES brpc_flatc HINTS "${BRPC_ROOT}/bin")
if(NOT FLATBUFFERS_INCLUDE_DIR OR NOT FLATC_EXECUTABLE OR NOT BRPC_FLATC_EXECUTABLE)
message(FATAL_ERROR "Set FLATBUFFERS_INCLUDE_DIR, FLATC_EXECUTABLE and BRPC_FLATC_EXECUTABLE")
endif()
if(NOT EXISTS "${FLATBUFFERS_INCLUDE_DIR}/flatbuffers/base.h")
message(FATAL_ERROR "FLATBUFFERS_INCLUDE_DIR must contain flatbuffers/base.h")
endif()
foreach(_part MAJOR MINOR REVISION)
file(STRINGS "${FLATBUFFERS_INCLUDE_DIR}/flatbuffers/base.h" _version_line
REGEX "^#define[ \t]+FLATBUFFERS_VERSION_${_part}[ \t]+[0-9]+")
if(NOT _version_line MATCHES "FLATBUFFERS_VERSION_${_part}[ \t]+([0-9]+)")
message(FATAL_ERROR "Cannot read FlatBuffers ${_part} version from base.h")
endif()
set(_fb_${_part} "${CMAKE_MATCH_1}")
endforeach()
set(_headers_version "${_fb_MAJOR}.${_fb_MINOR}.${_fb_REVISION}")
execute_process(COMMAND "${FLATC_EXECUTABLE}" --version
RESULT_VARIABLE _flatc_result OUTPUT_VARIABLE _flatc_version
ERROR_VARIABLE _flatc_error OUTPUT_STRIP_TRAILING_WHITESPACE TIMEOUT 5)
if(NOT _flatc_result STREQUAL "0" OR
NOT _flatc_version MATCHES "flatc version ([0-9]+\\.[0-9]+\\.[0-9]+)")
message(FATAL_ERROR "Cannot execute official flatc --version: ${_flatc_error}")
endif()
set(_compiler_version "${CMAKE_MATCH_1}")
if(NOT _compiler_version VERSION_EQUAL _headers_version)
message(FATAL_ERROR
"FlatBuffers headers ${_headers_version} do not match flatc ${_compiler_version}")
endif()
execute_process(COMMAND "${BRPC_FLATC_EXECUTABLE}" --help
RESULT_VARIABLE _brpc_flatc_result OUTPUT_QUIET ERROR_VARIABLE _brpc_flatc_error TIMEOUT 5)
if(NOT _brpc_flatc_result STREQUAL "0")
message(FATAL_ERROR "Cannot execute BRPC_FLATC_EXECUTABLE: ${_brpc_flatc_error}")
endif()
find_package(Threads REQUIRED)
find_package(Protobuf CONFIG QUIET)
set(_protobuf_config ${Protobuf_FOUND})
if(NOT Protobuf_FOUND)
find_package(Protobuf REQUIRED)
endif()
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
find_path(GFLAGS_INCLUDE_DIR NAMES gflags/gflags.h)
find_library(GFLAGS_LIBRARY NAMES gflags)
find_library(LEVELDB_LIBRARY NAMES leveldb)
if(NOT GFLAGS_INCLUDE_DIR OR NOT GFLAGS_LIBRARY OR NOT LEVELDB_LIBRARY)
message(FATAL_ERROR "Install gflags and leveldb, or set CMAKE_PREFIX_PATH to the runtime dependency prefix")
endif()
# FlatBuffers support requires C++17.
set(_cxx_standard 17)
if(Protobuf_VERSION VERSION_GREATER 4.21)
if(NOT _protobuf_config)
message(FATAL_ERROR "Protobuf 5+ needs its CMake config package to export transitive Abseil dependencies")
endif()
endif()
add_library(benchmark_fb_dependencies INTERFACE)
# Keep the actual runtime configuration ahead of dependency include directories,
# and the selected Protobuf ahead of shared prefixes such as the gflags one,
# which may hold another Protobuf (e.g. /opt/homebrew/include).
set(_protobuf_include_dirs ${Protobuf_INCLUDE_DIRS})
get_target_property(_protobuf_target_include_dirs protobuf::libprotobuf
INTERFACE_INCLUDE_DIRECTORIES)
if(_protobuf_target_include_dirs)
list(APPEND _protobuf_include_dirs ${_protobuf_target_include_dirs})
endif()
target_include_directories(benchmark_fb_dependencies INTERFACE
"${BRPC_INCLUDE_DIR}" "${FLATBUFFERS_INCLUDE_DIR}" ${_protobuf_include_dirs}
"${GFLAGS_INCLUDE_DIR}")
target_compile_features(benchmark_fb_dependencies INTERFACE cxx_std_${_cxx_standard})
target_link_libraries(benchmark_fb_dependencies INTERFACE
"${_BRPC_LIBRARY}" protobuf::libprotobuf "${GFLAGS_LIBRARY}" "${LEVELDB_LIBRARY}"
OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB Threads::Threads ${CMAKE_DL_LIBS}
${BRPC_EXTRA_LIBRARIES})
file(STRINGS "${BRPC_INCLUDE_DIR}/butil/config.h" _glog_enabled
REGEX "^#[ \t]*define[ \t]+BRPC_WITH_GLOG[ \t]+1([ \t]|$)")
if(_glog_enabled)
find_package(glog CONFIG REQUIRED)
target_link_libraries(benchmark_fb_dependencies INTERFACE glog::glog)
endif()
if(APPLE)
target_link_libraries(benchmark_fb_dependencies INTERFACE
"-framework CoreFoundation" "-framework CoreGraphics" "-framework CoreData"
"-framework CoreText" "-framework Security" "-framework Foundation")
target_link_options(benchmark_fb_dependencies INTERFACE
"LINKER:-U,_MallocExtension_ReleaseFreeMemory" "LINKER:-U,_ProfilerStart"
"LINKER:-U,_ProfilerStop" "LINKER:-U,__Z13GetStackTracePPvii"
"LINKER:-U,_mallctl" "LINKER:-U,_malloc_stats_print")
endif()
set(_generated "${CMAKE_CURRENT_BINARY_DIR}/generated")
set(_schema "${CMAKE_CURRENT_SOURCE_DIR}/echo.fbs")
set(_generated_files "${_generated}/echo_generated.h"
"${_generated}/echo.brpc.fb.h" "${_generated}/echo.brpc.fb.cpp")
add_custom_command(OUTPUT ${_generated_files}
COMMAND "${CMAKE_COMMAND}" -E make_directory "${_generated}"
COMMAND "${FLATC_EXECUTABLE}" --cpp -o "${_generated}" "${_schema}"
COMMAND "${BRPC_FLATC_EXECUTABLE}" -o "${_generated}" "${_schema}"
DEPENDS "${_schema}" "${FLATC_EXECUTABLE}" "${BRPC_FLATC_EXECUTABLE}"
VERBATIM)
add_custom_target(benchmark_fb_codegen DEPENDS ${_generated_files})
# Protobuf control schema used for the baidu_std comparison.
if(TARGET protobuf::protoc)
set(_protoc "$<TARGET_FILE:protobuf::protoc>")
elseif(Protobuf_PROTOC_EXECUTABLE)
set(_protoc "${Protobuf_PROTOC_EXECUTABLE}")
else()
message(FATAL_ERROR "Set Protobuf_PROTOC_EXECUTABLE to the protoc matching libprotobuf")
endif()
add_custom_command(OUTPUT "${_generated}/echo_pb.pb.h" "${_generated}/echo_pb.pb.cc"
COMMAND "${CMAKE_COMMAND}" -E make_directory "${_generated}"
COMMAND "${_protoc}" "--cpp_out=${_generated}" -I "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/echo_pb.proto"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/echo_pb.proto"
VERBATIM)
add_custom_target(benchmark_fb_pb_codegen DEPENDS
"${_generated}/echo_pb.pb.h" "${_generated}/echo_pb.pb.cc")
add_dependencies(benchmark_fb_codegen benchmark_fb_pb_codegen)
add_library(benchmark_fb_schema STATIC "${_generated}/echo.brpc.fb.cpp"
"${_generated}/echo_pb.pb.cc")
add_dependencies(benchmark_fb_schema benchmark_fb_codegen)
target_include_directories(benchmark_fb_schema PUBLIC "${_generated}")
target_link_libraries(benchmark_fb_schema PUBLIC benchmark_fb_dependencies)
foreach(_program client server)
add_executable(benchmark_fb_${_program} "${_program}.cpp")
add_dependencies(benchmark_fb_${_program} benchmark_fb_codegen)
target_link_libraries(benchmark_fb_${_program} PRIVATE benchmark_fb_schema)
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(benchmark_fb_${_program} PRIVATE -Wall -Wextra)
endif()
endforeach()
include(CTest)
if(BUILD_TESTING)
find_package(Python3 COMPONENTS Interpreter REQUIRED)
add_test(NAME benchmark_fb_smoke
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/smoke.py"
--server "$<TARGET_FILE:benchmark_fb_server>"
--client "$<TARGET_FILE:benchmark_fb_client>")
set_tests_properties(benchmark_fb_smoke PROPERTIES TIMEOUT 50 LABELS "flatbuffers;smoke")
endif()
message(STATUS "benchmark_fb: brpc=${_BRPC_LIBRARY}, FlatBuffers=${_headers_version}")