diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index 6e6bf9a02..20a8da865 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -3,10 +3,55 @@ core functionality, useable by some client software perhaps #]===================================================================] +include(target_protobuf_sources) + file (GLOB_RECURSE rb_headers src/ripple/beast/*.h src/ripple/beast/*.hpp) +# Protocol buffers cannot participate in a unity build, +# because all the generated sources +# define a bunch of `static const` variables with the same names, +# so we just build them as a separate library. +add_library(xrpl.libpb) +target_protobuf_sources(xrpl.libpb ripple/proto + LANGUAGE cpp + IMPORT_DIRS src/ripple/proto + PROTOS src/ripple/proto/ripple.proto +) + +file(GLOB_RECURSE protos "src/ripple/proto/org/*.proto") +target_protobuf_sources(xrpl.libpb ripple/proto + LANGUAGE cpp + IMPORT_DIRS src/ripple/proto + PROTOS "${protos}" +) +target_protobuf_sources(xrpl.libpb ripple/proto + LANGUAGE grpc + IMPORT_DIRS src/ripple/proto + PROTOS "${protos}" + PLUGIN protoc-gen-grpc=$ + GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc +) + +target_compile_options(xrpl.libpb + PUBLIC + $<$:-wd4996> + $<$: + --system-header-prefix="google/protobuf" + -Wno-deprecated-dynamic-exception-spec + > + PRIVATE + $<$:-wd4065> + $<$>:-Wno-deprecated-declarations> +) + +target_link_libraries(xrpl.libpb + PUBLIC + protobuf::libprotobuf + gRPC::grpc++ +) + add_library (xrpl_core ${rb_headers}) ## headers added here for benefit of IDEs if (unity) @@ -27,7 +72,6 @@ add_library(libxrpl INTERFACE) target_link_libraries(libxrpl INTERFACE xrpl_core) add_library(xrpl::libxrpl ALIAS libxrpl) - #[===============================[ beast/legacy FILES: TODO: review these sources for removal or replacement @@ -165,6 +209,7 @@ target_link_libraries (xrpl_core Ripple::syslibs secp256k1::secp256k1 ed25519::ed25519 + xrpl.libpb date::date Ripple::opts xxHash::xxhash) diff --git a/Builds/CMake/RippledInstall.cmake b/Builds/CMake/RippledInstall.cmake index eef90c146..b9dd44cfc 100644 --- a/Builds/CMake/RippledInstall.cmake +++ b/Builds/CMake/RippledInstall.cmake @@ -9,6 +9,7 @@ install ( ripple_syslibs ripple_boost xrpl_core + xrpl.libpb EXPORT RippleExports LIBRARY DESTINATION lib ARCHIVE DESTINATION lib diff --git a/Builds/CMake/target_protobuf_sources.cmake b/Builds/CMake/target_protobuf_sources.cmake new file mode 100644 index 000000000..da2ef6dc9 --- /dev/null +++ b/Builds/CMake/target_protobuf_sources.cmake @@ -0,0 +1,62 @@ +find_package(Protobuf REQUIRED) + +# .proto files import each other like this: +# +# import "path/to/file.proto"; +# +# For the protobuf compiler to find these imports, +# the parent directory of "path" must be in the import path. +# +# When generating C++, +# it turns into an include statement like this: +# +# #include "path/to/file.pb.h" +# +# and the header is generated at a path relative to the output directory +# that matches the given .proto path relative to the source directory +# minus the first matching prefix on the import path. +# +# In other words, a file `include/package/path/to/file.proto` +# with import path [`include/package`, `include`] +# will generate files `output/path/to/file.pb.{h,cc}` +# with includes like `#include "path/to/file.pb.h". +# +# During build, the generated files can find each other if the output +# directory is an include directory, but we want to install that directory +# under our package's include directory (`include/package`), not as a sibling. +# After install, they can find each other if that subdirectory is an include +# directory. + +# Add protocol buffer sources to an existing library target. +# target: +# The name of the library target. +# prefix: +# The install prefix for headers relative to `CMAKE_INSTALL_INCLUDEDIR`. +# This prefix should appear at the start of all your consumer includes. +# ARGN: +# A list of .proto files. +function(target_protobuf_sources target prefix) + set(dir "${CMAKE_CURRENT_BINARY_DIR}/pb-${target}") + file(MAKE_DIRECTORY "${dir}/${prefix}") + + protobuf_generate( + TARGET ${target} + PROTOC_OUT_DIR "${dir}/${prefix}" + "${ARGN}" + ) + target_include_directories(${target} SYSTEM PUBLIC + # Allows #include used by consumer files. + $ + # Allows #include "path/to/file.proto" used by generated files. + $ + # Allows #include used by consumer files. + $ + # Allows #include "path/to/file.proto" used by generated files. + $ + ) + install( + DIRECTORY ${dir}/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING PATTERN "*.h" + ) +endfunction() diff --git a/CMakeLists.txt b/CMakeLists.txt index 13e1798b4..609678c65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,8 +90,9 @@ set_target_properties(OpenSSL::SSL PROPERTIES ) set(SECP256K1_INSTALL TRUE) add_subdirectory(external/secp256k1) -add_subdirectory(external/ed25519-donna) add_library(secp256k1::secp256k1 ALIAS secp256k1) +add_subdirectory(external/ed25519-donna) +find_package(gRPC REQUIRED) find_package(lz4 REQUIRED) # Target names with :: are not allowed in a generator expression. # We need to pull the include directories and imported location properties diff --git a/conanfile.py b/conanfile.py index 00c773a41..d02929843 100644 --- a/conanfile.py +++ b/conanfile.py @@ -32,12 +32,15 @@ class Xrpl(ConanFile): 'lz4/1.9.4', 'nudb/2.0.8', 'openssl/3.6.0', - 'protobuf/3.21.12', 'soci/4.0.3@xahaud/stable', 'xxhash/0.8.2', 'zlib/1.3.1', ] + tool_requires = [ + 'protobuf/3.21.12', + ] + default_options = { 'assertions': False, 'coverage': False, @@ -101,7 +104,6 @@ class Xrpl(ConanFile): def build_requirements(self): # These provide build tools (protoc, grpc plugins) that run during build - self.tool_requires('protobuf/3.21.12') self.tool_requires('grpc/1.50.1') # Explicitly require b2 (e.g. for building from source for glibc compatibility) if self.options.tool_requires_b2: