1# Minimum CMake required. If available, accept the policy-controlled behavior up 2# to 3.26. 3cmake_minimum_required(VERSION 3.10...3.26) 4 5# Revert to old behavior for MSVC debug symbols. 6if(POLICY CMP0141) 7 cmake_policy(SET CMP0141 OLD) 8endif() 9 10if(protobuf_VERBOSE) 11 message(STATUS "Protocol Buffers Configuring...") 12endif() 13 14# Project 15project(protobuf C CXX) 16 17if(protobuf_DEPRECATED_CMAKE_SUBDIRECTORY_USAGE) 18 if(CMAKE_PROJECT_NAME STREQUAL "protobuf") 19 get_filename_component(CMAKE_SOURCE_DIR ${CMAKE_SOURCE_DIR} DIRECTORY) 20 endif() 21 get_filename_component(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) 22 get_filename_component(PROJECT_SOURCE_DIR ${PROJECT_SOURCE_DIR} DIRECTORY) 23 get_filename_component(protobuf_SOURCE_DIR ${protobuf_SOURCE_DIR} DIRECTORY) 24endif() 25 26# Options 27option(protobuf_INSTALL "Install protobuf binaries and files" ON) 28option(protobuf_BUILD_TESTS "Build tests" ON) 29option(protobuf_BUILD_CONFORMANCE "Build conformance tests" OFF) 30option(protobuf_BUILD_EXAMPLES "Build examples" OFF) 31option(protobuf_BUILD_PROTOBUF_BINARIES "Build protobuf libraries and protoc compiler" ON) 32option(protobuf_BUILD_PROTOC_BINARIES "Build libprotoc and protoc compiler" ON) 33option(protobuf_BUILD_LIBPROTOC "Build libprotoc" OFF) 34option(protobuf_BUILD_LIBUPB "Build libupb" ON) 35option(protobuf_DISABLE_RTTI "Remove runtime type information in the binaries" OFF) 36option(protobuf_TEST_XML_OUTDIR "Output directory for XML logs from tests." "") 37option(protobuf_ALLOW_CCACHE "Adjust build flags to allow for ccache support." OFF) 38 39# We support Unity (Jumbo) builds best-effort. 40option(protobuf_USE_UNITY_BUILD "Enable Unity (Jumbo) build for" OFF) 41if (BUILD_SHARED_LIBS) 42 set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON) 43else (BUILD_SHARED_LIBS) 44 set(protobuf_BUILD_SHARED_LIBS_DEFAULT OFF) 45endif (BUILD_SHARED_LIBS) 46option(protobuf_BUILD_SHARED_LIBS "Build Shared Libraries" ${protobuf_BUILD_SHARED_LIBS_DEFAULT}) 47include(CMakeDependentOption) 48cmake_dependent_option(protobuf_MSVC_STATIC_RUNTIME "Link static runtime libraries" ON 49 "NOT protobuf_BUILD_SHARED_LIBS" OFF) 50set(protobuf_WITH_ZLIB_DEFAULT ON) 51option(protobuf_WITH_ZLIB "Build with zlib support" ${protobuf_WITH_ZLIB_DEFAULT}) 52set(protobuf_DEBUG_POSTFIX "d" 53 CACHE STRING "Default debug postfix") 54mark_as_advanced(protobuf_DEBUG_POSTFIX) 55 56if(WITH_PROTOC) 57 set(protobuf_PROTOC_EXE protoc) 58 set(protobuf_BUILD_PROTOC_BINARIES OFF) 59 add_executable(protoc IMPORTED GLOBAL) 60 add_executable(protobuf::protoc ALIAS protoc) 61 set_property(TARGET protoc PROPERTY IMPORTED_LOCATION ${WITH_PROTOC}) 62endif() 63 64# User options 65include(${protobuf_SOURCE_DIR}/cmake/protobuf-options.cmake) 66 67if (protobuf_BUILD_SHARED_LIBS) 68 # This is necessary for linking in Abseil. 69 set(CMAKE_POSITION_INDEPENDENT_CODE ON) 70 71 # Build Abseil as shared libraries to avoid ODR violations. 72 set(BUILD_SHARED_LIBS ON) 73 74 # Output directory is correct by default for most build setups. However, when 75 # building Protobuf as a DLL, it is important to have the DLL in the same 76 # directory as the executable using it. Thus, we put all binaries in a single 77 # /bin directory. 78 if (MSVC) 79 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 80 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 81 set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 82 set(CMAKE_PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 83 endif () 84endif () 85 86# Version metadata 87set(protobuf_VERSION_STRING "5.29.4") 88set(protobuf_DESCRIPTION "Protocol Buffers") 89set(protobuf_CONTACT "protobuf@googlegroups.com") 90 91# Overrides for option dependencies 92if (protobuf_BUILD_PROTOC_BINARIES OR protobuf_BUILD_TESTS) 93 set(protobuf_BUILD_LIBPROTOC ON) 94endif () 95if (NOT protobuf_BUILD_PROTOBUF_BINARIES) 96 set(protobuf_INSTALL OFF) 97endif() 98# Parse version tweaks 99set(protobuf_VERSION_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+)([-]rc[-]|\\.)?([0-9]*)$") 100string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\1" 101 protobuf_VERSION_MAJOR "${protobuf_VERSION_STRING}") 102string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\2" 103 protobuf_VERSION_MINOR "${protobuf_VERSION_STRING}") 104string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\3" 105 protobuf_VERSION_PATCH "${protobuf_VERSION_STRING}") 106string(REGEX REPLACE "${protobuf_VERSION_REGEX}" "\\5" 107 protobuf_VERSION_PRERELEASE "${protobuf_VERSION_STRING}") 108 109message(STATUS "${protobuf_VERSION_PRERELEASE}") 110 111# Package version 112set(protobuf_VERSION 113 "${protobuf_VERSION_MINOR}.${protobuf_VERSION_PATCH}") 114 115if(protobuf_VERSION_PRERELEASE) 116 set(protobuf_VERSION "${protobuf_VERSION}.${protobuf_VERSION_PRERELEASE}") 117else() 118 set(protobuf_VERSION "${protobuf_VERSION}.0") 119endif() 120message(STATUS "${protobuf_VERSION}") 121 122if(protobuf_VERBOSE) 123 message(STATUS "Configuration script parsing status [") 124 message(STATUS " Description : ${protobuf_DESCRIPTION}") 125 message(STATUS " Version : ${protobuf_VERSION} (${protobuf_VERSION_STRING})") 126 message(STATUS " Contact : ${protobuf_CONTACT}") 127 message(STATUS "]") 128endif() 129 130file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/cmaketest.map 131"{ 132 global: 133 main; 134 local: 135 *; 136};") 137# CheckLinkerFlag module available in CMake >=3.18. 138if(${CMAKE_VERSION} VERSION_GREATER 3.18 OR ${CMAKE_VERSION} VERSION_EQUAL 3.18) 139 include(CheckLinkerFlag) 140 check_linker_flag(CXX -Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/cmaketest.map protobuf_HAVE_LD_VERSION_SCRIPT) 141else() 142 include(CheckCXXSourceCompiles) 143 set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) 144 set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/cmaketest.map) 145 check_cxx_source_compiles(" 146 int main() { 147 return 0; 148 } 149 " protobuf_HAVE_LD_VERSION_SCRIPT) 150 set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) 151endif() 152file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/cmaketest.map) 153 154find_package(Threads REQUIRED) 155 156# We can install dependencies from submodules if we're running 157# CMake v3.13 or newer. 158if(CMAKE_VERSION VERSION_LESS 3.13) 159 set(_protobuf_INSTALL_SUPPORTED_FROM_MODULE OFF) 160else() 161 set(_protobuf_INSTALL_SUPPORTED_FROM_MODULE ON) 162endif() 163 164set(_protobuf_FIND_ZLIB) 165if (protobuf_WITH_ZLIB) 166 find_package(ZLIB) 167 if (ZLIB_FOUND) 168 set(HAVE_ZLIB 1) 169 # FindZLIB module define ZLIB_INCLUDE_DIRS variable 170 # Set ZLIB_INCLUDE_DIRECTORIES for compatible 171 set(ZLIB_INCLUDE_DIRECTORIES ${ZLIB_INCLUDE_DIRECTORIES} ${ZLIB_INCLUDE_DIRS}) 172 # Using imported target if exists 173 if (TARGET ZLIB::ZLIB) 174 set(ZLIB_LIBRARIES ZLIB::ZLIB) 175 set(_protobuf_FIND_ZLIB "if(NOT ZLIB_FOUND)\n find_package(ZLIB)\nendif()") 176 endif (TARGET ZLIB::ZLIB) 177 else (ZLIB_FOUND) 178 set(HAVE_ZLIB 0) 179 # Explicitly set these to empty (override NOT_FOUND) so cmake doesn't 180 # complain when we use them later. 181 set(ZLIB_INCLUDE_DIRECTORIES) 182 set(ZLIB_LIBRARIES) 183 endif (ZLIB_FOUND) 184endif (protobuf_WITH_ZLIB) 185 186# We need to link with libatomic on systems that do not have builtin atomics, or 187# don't have builtin support for 8 byte atomics 188set(protobuf_LINK_LIBATOMIC false) 189if (NOT MSVC) 190 include(CheckCXXSourceCompiles) 191 set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) 192 set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -std=c++14) 193 check_cxx_source_compiles(" 194 #include <atomic> 195 int main() { 196 return static_cast<int>(std::atomic<int64_t>{}); 197 } 198 " protobuf_HAVE_BUILTIN_ATOMICS) 199 if (NOT protobuf_HAVE_BUILTIN_ATOMICS) 200 set(protobuf_LINK_LIBATOMIC true) 201 endif (NOT protobuf_HAVE_BUILTIN_ATOMICS) 202 set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) 203endif (NOT MSVC) 204 205if (protobuf_BUILD_SHARED_LIBS) 206 set(protobuf_SHARED_OR_STATIC "SHARED") 207else (protobuf_BUILD_SHARED_LIBS) 208 set(protobuf_SHARED_OR_STATIC "STATIC") 209 # The CMAKE_<LANG>_FLAGS(_<BUILD_TYPE>)? is meant to be user controlled. 210 # Prior to CMake 3.15, the MSVC runtime library was pushed into the same flags 211 # making programmatic control difficult. Prefer the functionality in newer 212 # CMake versions when available. 213 if(${CMAKE_VERSION} VERSION_GREATER 3.15 OR ${CMAKE_VERSION} VERSION_EQUAL 3.15) 214 if (protobuf_MSVC_STATIC_RUNTIME) 215 set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>) 216 else() 217 set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded$<$<CONFIG:Debug>:Debug>DLL) 218 endif() 219 else() 220 # In case we are building static libraries, link also the runtime library statically 221 # so that MSVCR*.DLL is not required at runtime. 222 # https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx 223 # This is achieved by replacing msvc option /MD with /MT and /MDd with /MTd 224 # http://www.cmake.org/Wiki/CMake_FAQ#How_can_I_build_my_MSVC_application_with_a_static_runtime.3F 225 if (MSVC AND protobuf_MSVC_STATIC_RUNTIME) 226 foreach(flag_var 227 CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 228 CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) 229 if(${flag_var} MATCHES "/MD") 230 string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") 231 endif(${flag_var} MATCHES "/MD") 232 endforeach(flag_var) 233 endif (MSVC AND protobuf_MSVC_STATIC_RUNTIME) 234 endif() 235endif (protobuf_BUILD_SHARED_LIBS) 236 237# Export all symbols on Windows when building shared libraries 238SET(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) 239 240if (MSVC) 241 string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR}) 242 string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR}) 243 string(REPLACE "." "," protobuf_RC_FILEVERSION "${protobuf_VERSION}") 244 245 if (protobuf_ALLOW_CCACHE) 246 # In order to support ccache, we need to remove the /Zi option because it 247 # puts debug symbols into separate pdb files (which in incompatible with 248 # ccache). This can be replaced with /Z7 to preserve debug symbols, which 249 # embeds debug symbols into the object files instead of creating a separate 250 # pdb file, which isn't currently supported by ccache. However, this bloats 251 # the ccache size by about a factor of 2x, making it very expensive in CI. 252 # Instead, we strip debug symbols to reduce this overhead. 253 foreach(v 254 CMAKE_C_FLAGS_DEBUG 255 CMAKE_CXX_FLAGS_DEBUG 256 CMAKE_C_FLAGS_RELWITHDEBINFO 257 CMAKE_CXX_FLAGS_RELWITHDEBINFO 258 ) 259 string(REGEX REPLACE "[-/]Z[iI7]" "/DEBUG:NONE" ${v} "${${v}}") 260 endforeach() 261 endif() 262 263 # Suppress linker warnings about files with no symbols defined. 264 string(APPEND CMAKE_STATIC_LINKER_FLAGS " /ignore:4221") 265 266 # use English language (0x409) in resource compiler 267 string(APPEND CMAKE_RC_FLAGS " -l0x409") 268 269 # Generate the version.rc file used elsewhere. 270 configure_file(${protobuf_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) 271 set(protobuf_version_rc_file ${CMAKE_CURRENT_BINARY_DIR}/version.rc) 272 273 # Add the "lib" prefix for generated .lib outputs. 274 set(LIB_PREFIX lib) 275else (MSVC) 276 # No version.rc file. 277 set(protobuf_version_rc_file) 278 279 # When building with "make", "lib" prefix will be added automatically by 280 # the build tool. 281 set(LIB_PREFIX) 282endif (MSVC) 283 284include_directories( 285 ${ZLIB_INCLUDE_DIRECTORIES} 286 ${protobuf_BINARY_DIR} 287 # Support #include-ing other top-level directories, i.e. upb_generator. 288 ${protobuf_SOURCE_DIR} 289 ${protobuf_BINARY_DIR}/src 290 ${protobuf_SOURCE_DIR}/src) 291 292set(protobuf_ABSL_PROVIDER "module" CACHE STRING "Provider of absl library") 293set_property(CACHE protobuf_ABSL_PROVIDER PROPERTY STRINGS "module" "package") 294 295set(protobuf_JSONCPP_PROVIDER "module" CACHE STRING "Provider of jsoncpp library") 296set_property(CACHE protobuf_JSONCPP_PROVIDER PROPERTY STRINGS "module" "package") 297 298if (protobuf_BUILD_TESTS) 299 include(${protobuf_SOURCE_DIR}/cmake/gtest.cmake) 300endif (protobuf_BUILD_TESTS) 301 302include(${protobuf_SOURCE_DIR}/cmake/abseil-cpp.cmake) 303 304if (protobuf_BUILD_PROTOBUF_BINARIES) 305 include(${protobuf_SOURCE_DIR}/cmake/utf8_range.cmake) 306 include(${protobuf_SOURCE_DIR}/cmake/libprotobuf-lite.cmake) 307 if (NOT DEFINED protobuf_LIB_PROTOBUF_LITE) 308 set(protobuf_LIB_PROTOBUF_LITE libprotobuf-lite) 309 endif () 310 include(${protobuf_SOURCE_DIR}/cmake/libprotobuf.cmake) 311 if (NOT DEFINED protobuf_LIB_PROTOBUF) 312 set(protobuf_LIB_PROTOBUF libprotobuf) 313 endif () 314 if (protobuf_BUILD_LIBPROTOC) 315 include(${protobuf_SOURCE_DIR}/cmake/libprotoc.cmake) 316 if (NOT DEFINED protobuf_LIB_PROTOC) 317 set(protobuf_LIB_PROTOC libprotoc) 318 endif () 319 endif () 320 if (protobuf_BUILD_LIBUPB) 321 include(${protobuf_SOURCE_DIR}/cmake/libupb.cmake) 322 if (NOT DEFINED protobuf_LIB_UPB) 323 set(protobuf_LIB_UPB libupb) 324 endif () 325 include(${protobuf_SOURCE_DIR}/cmake/upb_generators.cmake) 326 endif () 327 if (protobuf_BUILD_PROTOC_BINARIES) 328 include(${protobuf_SOURCE_DIR}/cmake/protoc.cmake) 329 if (NOT DEFINED protobuf_PROTOC_EXE) 330 set(protobuf_PROTOC_EXE protoc) 331 endif () 332 endif () 333else () 334 find_package(Protobuf NO_MODULE) 335 if (Protobuf_FOUND) 336 set(protobuf_PROTOC_EXE protobuf::protoc) 337 set(protobuf_LIB_PROTOC protobuf::libprotoc) 338 set(protobuf_LIB_PROTOBUF protobuf::libprotobuf) 339 set(protobuf_LIB_PROTOBUF_LITE protobuf::libprotobuf-lite) 340 set(protobuf_LIB_UPB protobuf::libupb) 341 message(STATUS "CMake installation of Protobuf found.") 342 endif () 343endif () 344 345# Ensure we have a protoc executable and protobuf libraries if we need one 346if (protobuf_BUILD_TESTS OR protobuf_BUILD_CONFORMANCE OR protobuf_BUILD_EXAMPLES) 347 if (NOT DEFINED protobuf_PROTOC_EXE) 348 find_program(protobuf_PROTOC_EXE protoc REQUIRED) 349 message(STATUS "Found system ${protobuf_PROTOC_EXE}.") 350 endif () 351 if(protobuf_VERBOSE) 352 message(STATUS "Using protoc : ${protobuf_PROTOC_EXE}") 353 message(STATUS "Using libprotobuf : ${protobuf_LIB_PROTOBUF}") 354 message(STATUS "Using libprotobuf-lite : ${protobuf_LIB_PROTOBUF_LITE}") 355 message(STATUS "Using libprotoc : ${protobuf_LIB_PROTOC}") 356 message(STATUS "Using libupb : ${protobuf_LIB_UPB}") 357 endif(protobuf_VERBOSE) 358endif () 359 360if (protobuf_BUILD_TESTS) 361 enable_testing() 362 include(${protobuf_SOURCE_DIR}/cmake/tests.cmake) 363endif (protobuf_BUILD_TESTS) 364 365if (protobuf_BUILD_CONFORMANCE) 366 include(${protobuf_SOURCE_DIR}/cmake/conformance.cmake) 367endif (protobuf_BUILD_CONFORMANCE) 368 369if (protobuf_INSTALL) 370 include(${protobuf_SOURCE_DIR}/cmake/install.cmake) 371endif (protobuf_INSTALL) 372 373if (protobuf_BUILD_EXAMPLES) 374 include(${protobuf_SOURCE_DIR}/cmake/examples.cmake) 375endif (protobuf_BUILD_EXAMPLES) 376 377if(protobuf_VERBOSE) 378 message(STATUS "Protocol Buffers Configuring done") 379endif(protobuf_VERBOSE) 380