Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MONGOCRYPT-535 Support libdfp as a Decimal128 abstraction #566

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
19 changes: 8 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ set (MONGOCRYPT_SOURCES
src/crypto/libcrypto.c
src/crypto/none.c
src/mc-array.c
src/mc-dec128.c
src/mc-efc.c
src/mc-fle2-find-range-payload.c
src/mc-fle2-insert-update-payload.c
Expand Down Expand Up @@ -282,7 +283,7 @@ target_link_libraries (
kms_message_static
$<BUILD_INTERFACE:mongo::mlib>
PUBLIC
mongocrypt::intel_dfp
mongocrypt::dfp
${CMAKE_DL_LIBS}
)

Expand Down Expand Up @@ -340,7 +341,7 @@ target_link_libraries (
kms_message_static
$<BUILD_INTERFACE:mongo::mlib>
PUBLIC
mongocrypt::intel_dfp
mongocrypt::dfp
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS}
)
Expand All @@ -360,7 +361,7 @@ if (ENABLE_BUILD_FOR_PPA)
set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} -pthread")
endif ()
if (MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM")
get_property (SYSTEM_DFP_LOC TARGET intel_dfp PROPERTY IMPORTED_LOCATION)
get_property (SYSTEM_DFP_LOC TARGET _mongocrypt::system-dfp PROPERTY IMPORTED_LOCATION)
set (PKG_CONFIG_STATIC_LIBS "${PKG_CONFIG_STATIC_LIBS} ${SYSTEM_DFP_LOC}")
endif ()

Expand Down Expand Up @@ -521,7 +522,7 @@ add_test (

foreach (test IN ITEMS path str)
add_executable (mlib.${test}.test src/mlib/${test}.test.c)
add_test (mlib.${test} mlib.${test}.test)
add_test (NAME mlib.${test} COMMAND mlib.${test}.test)
target_link_libraries (mlib.${test}.test PRIVATE mongo::mlib)
endforeach ()

Expand All @@ -539,13 +540,13 @@ if ("cxx_relaxed_constexpr" IN_LIST CMAKE_CXX_COMPILE_FEATURES)
add_executable ("${exe_name}" "${file}")
target_compile_features ("${exe_name}" PRIVATE cxx_relaxed_constexpr)
target_link_libraries ("${exe_name}" PRIVATE
mongocrypt
mongocrypt_static
mongo::mlib
mongocrypt::intel_dfp
mongocrypt::dfp
Threads::Threads
_mongocrypt::libbson_for_static
)
add_test ("${test_name}" "${exe_name}")
add_test (NAME "${test_name}" COMMAND "${exe_name}")
endforeach ()
endif ()

Expand Down Expand Up @@ -636,10 +637,6 @@ if (ENABLE_BUILD_FOR_PPA)
endif ()
set (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} -pthread")
endif ()
if (MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM")
get_property (SYSTEM_DFP_LOC TARGET intel_dfp PROPERTY IMPORTED_LOCATION)
set (PKG_CONFIG_LIBS "${PKG_CONFIG_LIBS} ${SYSTEM_DFP_LOC}")
endif ()
set (PKG_CONFIG_CFLAGS "-I\${includedir}")
set (PKG_CONFIG_STATIC_CFLAGS "${PKG_CONFIG_CFLAGS} -DMONGOCRYPT_STATIC_DEFINE -DKMS_MSG_STATIC")
configure_file (
Expand Down
4 changes: 2 additions & 2 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ rpm-build:
GIT CLONE https://src.fedoraproject.org/rpms/libmongocrypt.git /R
# Install the packages listed by "BuildRequires" and rpm-build:
RUN __install $(awk '/^BuildRequires:/ { print $2 }' /R/libmongocrypt.spec) \
rpm-build
rpm-build libdfp-devel
DO +COPY_SOURCE
RUN cp -r /s/libmongocrypt/. /R
RUN awk -f /R/etc/rpm/tweak.awk < /R/libmongocrypt.spec > /R/libmongocrypt.2.spec
Expand Down Expand Up @@ -300,7 +300,7 @@ deb-build:
ARG env=deb-unstable
FROM +env.$env
RUN __install git-buildpackage fakeroot debhelper cmake libbson-dev \
libintelrdfpmath-dev
libdfp-dev quilt
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can drop quilt from here. It is no longer necessary after the Debian packaging changes included in #567 .

DO +COPY_SOURCE
WORKDIR /s/libmongocrypt
RUN git clean -fdx && git reset --hard
Expand Down
107 changes: 72 additions & 35 deletions cmake/ImportDFP.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,104 @@
This file handles importing the DFP (decimal floating point) library for decimal128 support. It
is patterned after ImportBSON in this same directory.

Initially, the only supported DFP implementation is Intel DFP. However, this module will allow
for the future addition of support for libdfp.

This file defines, exports, and installs one INTERFACE target: mongocrypt::intel_dfp.
This file defines, exports, and installs one INTERFACE target: _mongocrypt::dfp.

The target(s) from this file are used to link the DFP library correctly for the build
configuration of libmongocrypt. At find_package() time, we can resolve these interface targets
to link to the DFP library based on the build configurations of libmongocrypt.

In the initial implementation both mongo::mongocrypt and mongo::mongocrypt_static must link to
mongocrypt::intel_dfp (this is because if we link to the Intel DFP which is vendored with
_mongocrypt::dfp (this is because if we link to the Intel DFP which is vendored with
libmongocrypt then we will link the object files directly and if we use the system Intel DFP then
we will be linking with .a static library archives).

The default behavior is to use the Intel DFP which is vendored in this repository. By setting
MONGOCRYPT_DFP_DIR=USE-SYSTEM the build will assume that an appropriate Intel DFP implementation
MONGOCRYPT_DFP_DIR=USE-SYSTEM the build will assume that an appropriate DFP implementation
can be found in a location where it has been installed system-wide (most likely under /usr or
/usr/local).
/usr/local). It will search for an installation of IntelDFP or of libdfp.
]]

if (DEFINED MONGOCRYPT_DFP_DIR AND NOT MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM")
message (FATAL_ERROR "The only valid value for MONGOCRYPT_DFP_DIR is USE-SYSTEM")
endif ()

function (_import_dfp)
find_library (_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC "${CMAKE_STATIC_LIBRARY_PREFIX}bidgcc000${CMAKE_STATIC_LIBRARY_SUFFIX}")
find_path (_MONGOCRYPT_SYSTEM_INTEL_DFP_INCLUDE_DIR bid_conf.h)
add_library (intel_dfp STATIC IMPORTED)
set_target_properties (intel_dfp PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_MONGOCRYPT_SYSTEM_INTEL_DFP_INCLUDE_DIR}"
)
set_property (TARGET intel_dfp PROPERTY IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC}")
set_property (
CACHE _MONGOCRYPT_SYSTEM_INTEL_DFP_INCLUDE_DIR
PROPERTY ADVANCED
TRUE
if (NOT _MONGOCRYPT_SYSTEM_DFP_LIB OR NOT _MONGOCRYPT_SYSTEM_DFP_INCLUDE_DIR)
message (CHECK_START "Searching for a decimal floating-point library")
# Clear prior settings if either one may have been unset:
unset (_MONGOCRYPT_SYSTEM_DFP_LIB CACHE)
unset (_MONGOCRYPT_SYSTEM_DFP_INCLUDE_DIR CACHE)
# Search for the IntelDFP library:
find_library (
_inteldfp_lib
NAMES bidgcc000 "${CMAKE_STATIC_LIBRARY_PREFIX}bidgcc000${CMAKE_STATIC_LIBRARY_SUFFIX}"
NO_CACHE
)
# Search for the libdfp library:
find_library (
_libdfp_lib
NAMES dfp "${CMAKE_STATIC_LIBRARY_PREFIX}dfp${CMAKE_STATIC_LIBRARY_SUFFIX}"
NO_CACHE
)

# Search for the include-path for IntelDFP:
find_path (_inteldfp_bid_conf_h_dir bid_conf.h NO_CACHE)
# Search for math.h contained in libdfp:
find_file (_libdfp_dfp_math_h "dfp/math.h" NO_CACHE)

set (_lib NOTFOUND)
set (_inc_dir NOTFOUND)
if (_inteldfp_lib AND _inteldfp_bid_conf_h_dir)
# Use libdfp:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Use libdfp:
# Use IntelDFP:

message (CHECK_PASS "Using IntelDFP: ${_inteldfp_lib}")
set (_lib "${_inteldfp_lib}")
set (_inc_dir "${_inteldfp_bid_conf_h_dir}")
elseif (_libdfp_lib AND _libdfp_dfp_math_h)
# Use libdfp:
message (CHECK_PASS "Using libdfp: ${_libdfp_lib}")
set (_lib "${_libdfp_lib}")
# We want to add the 'dfp/' directory as an include-dir, so it intercepts
# the default stdlib headers:
get_filename_component (_inc_dir "${_libdfp_dfp_math_h}" DIRECTORY)
else ()
# Nope:
message (CHECK_FAIL "No decimal floating-point library was found.")
message (SEND_ERROR "Failed to import a decimal floating-point library from the system")
endif ()

set (_MONGOCRYPT_SYSTEM_DFP_LIB "${_lib}" CACHE PATH "System DFP library to use")
set (_MONGOCRYPT_SYSTEM_DFP_INCLUDE_DIR "${_inc_dir}" CACHE PATH "include-search-dir for the system DFP library")
mark_as_advanced (_MONGOCRYPT_SYSTEM_DFP_LIB _MONGOCRYPT_SYSTEM_DFP_INCLUDE_DIR)
endif ()

add_library (_mongocrypt::system-dfp UNKNOWN IMPORTED)
set_target_properties (
_mongocrypt::system-dfp PROPERTIES
IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_DFP_LIB}"
INTERFACE_INCLUDE_DIRECTORIES "${_MONGOCRYPT_SYSTEM_DFP_INCLUDE_DIR}"
)
endfunction ()

# This library is used to pivot the used DFP library at configure/find_package time:
add_library (_mongocrypt-dfp INTERFACE)
add_library (mongocrypt::dfp ALIAS _mongocrypt-dfp)
install (TARGETS _mongocrypt-dfp EXPORT mongocrypt_targets)

if (NOT DEFINED MONGOCRYPT_DFP_DIR)
# The user did not provide a MONGOCRYPT_DFP_DIR, so we'll set one up
include (IntelDFP)
elseif (MONGOCRYPT_DFP_DIR STREQUAL "USE-SYSTEM")
message (STATUS "NOTE: Using system-wide Intel DFP library. This is intended only for package maintainers.")
set (USE_SYSTEM_INTEL_DFP "ON")
message (STATUS "NOTE: Using system-wide DFP library. This is intended only for package maintainers.")

# Do the import in a function to isolate variable scope
_import_dfp ()

# Define interface targets to be used to control the DFP used at both build and import time.
# Refer to mongocrypt-config.cmake to see how these targets are used by consumers
add_library (_mongocrypt-intel_dfp INTERFACE)
add_library (mongocrypt::intel_dfp ALIAS _mongocrypt-intel_dfp)
install (
TARGETS _mongocrypt-intel_dfp
EXPORT mongocrypt_targets
)

# Link to Intel DFP, only exporting that usage for the local build tree.
# The mongocrypt-config file will later add the appropriate link library for downstream
# users during find_package()
target_link_libraries (_mongocrypt-intel_dfp INTERFACE $<BUILD_INTERFACE:intel_dfp>)

# Link to the import target for the system's DFP library.
# mongocrypt-config.cmake will later add a matching IMPORTED target
# for downstream users during find_package()
target_link_libraries (_mongocrypt-dfp INTERFACE _mongocrypt::system-dfp)
# Hints for mongocrypt-config.cmake:
set (USE_SYSTEM_DFP "ON")
get_target_property (_loc _mongocrypt::system-dfp IMPORTED_LOCATION)
get_filename_component (SYSTEM_DFP_FILENAME "${_loc}" NAME)
endif ()

17 changes: 5 additions & 12 deletions cmake/IntelDFP.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -376,30 +376,23 @@ target_compile_definitions (intel_dfp_obj PUBLIC
target_compile_options (intel_dfp_obj PRIVATE -w)
target_include_directories(intel_dfp_obj PUBLIC ${intel_dfp_SOURCE_DIR}/LIBRARY/src)

# Define an interface library that attaches the built TUs to the consumer
add_library (_mongocrypt_intel_dfp INTERFACE)
add_library (mongocrypt::intel_dfp ALIAS _mongocrypt_intel_dfp)

target_sources (_mongocrypt_intel_dfp
target_sources (_mongocrypt-dfp
#[[
For targets *within this build* that link with mongocrypt::intel_dfp,
For targets *within this build* that link with mongocrypt::dfp,
inject the generated TUs (object files) from the intel_dfp_obj library.

This will be stripped out of the interface library when it is installed,
since we don't want to ship the DFP object separately. Instead, users
since we don't want to ship the DFP objects separately. Instead, users
will link to libmongocrypt, which will contain the necessary TUs for
the library (because they link to this interface library).
]]
INTERFACE $<BUILD_INTERFACE:$<TARGET_OBJECTS:intel_dfp_obj>>
)
target_link_libraries (_mongocrypt_intel_dfp
target_link_libraries (_mongocrypt-dfp
INTERFACE
# IntelDFP requires that we set certain definitions just to consume its headers:
$<BUILD_INTERFACE:intel_dfp_obj>
# We do want to propagate an interface requirement: Some platforms need a
# separate link library to support special math functions.
$<$<PLATFORM_ID:Linux>:m>
)

# Give the installed target a name to indicate its hidden-ness
set_property (TARGET _mongocrypt_intel_dfp PROPERTY EXPORT_NAME private::intel_dfp_interface)
install (TARGETS _mongocrypt_intel_dfp EXPORT mongocrypt_targets)
39 changes: 32 additions & 7 deletions cmake/mongocrypt-config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,37 @@ if (_using_shared_libbson AND DEFINED MONGOCRYPT_LIBBSON_SHARED_USE)
)
endif ()

set (_using_system_intel_dfp "@USE_SYSTEM_INTEL_DFP@")
#[[ BOOL:
Whether the packaged libmongocrypt expects to use the system's DFP library. Like with
libbson noted above, the default configuration embeds the TUs for IntelDFP within libmongocrypt
itself. These TUs are defined with special names and won't collide with other DFP libraries
that might be used by a final application.

if (_using_system_intel_dfp)
find_library (_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC "${CMAKE_STATIC_LIBRARY_PREFIX}bidgcc000${CMAKE_STATIC_LIBRARY_SUFFIX}")
set_property (
TARGET mongo::_mongocrypt-intel_dfp
PROPERTY IMPORTED_LOCATION "${_MONGOCRYPT_SYSTEM_INTEL_DFP_STATIC}"
)
If we were built against a system DFP, libmongocrypt will have a transitive usage of
_mongocrypt::system-dfp. We will need to define this IMPORTED target.
]]
set (_using_system_dfp "@USE_SYSTEM_DFP@")
#[[ Filename:
If this libmongocrypt was built with the system's DFP, this is the filename of the
library that was used during the find build. This gives us sufficient information to know
resolve the appropriate library for transitive users.
]]
set (_system_dfp_filename "@SYSTEM_DFP_FILENAME@")

if (_using_system_dfp)
# Find the library on the system that matches the name of the library that we used when
# building libmongocrypt. If we found a 'libdfp.so' library, we also want to check for 'libdfp.so.1',
# since that is the preferred binary name.
find_library (MONGOCRYPT_SYSTEM_DFP_LIB NAMES "${_system_dfp_filename}" "${_system_dfp_filename}.1")
if (NOT MONGOCRYPT_SYSTEM_DFP_LIB)
message (WARNING
"Unable to find the '${_system_dfp_filename}' decimal floating-point library that is expected by libmongocrypt. "
"Application linking will likely fail. Set MONGOCRYPT_SYSTEM_DFP_LIB to a library path to use.")
else ()
add_library (_mongocrypt::system-dfp UNKNOWN IMPORTED)
set_property (
TARGET _mongocrypt::system-dfp
PROPERTY IMPORTED_LOCATION "${MONGOCRYPT_SYSTEM_DFP_LIB}"
)
endif ()
endif ()
3 changes: 1 addition & 2 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Build-Depends: debhelper (>= 10),
quilt,
libssl-dev,
pkg-config,
libintelrdfpmath-dev (>= 2.0u2-6),
libdfp-dev (>= 1.0.16-1),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
libdfp-dev (>= 1.0.16-1),
libdfp-dev,

Let's drop the version, as it's not strictly necessary for libdfp-dev and including it will make backporting libmongocrypt more difficult.

libbson-dev
Standards-Version: 4.6.2
Section: libs
Expand All @@ -21,7 +21,6 @@ Architecture: any
Multi-Arch: same
Depends: libbson-dev,
libmongocrypt0 (= ${binary:Version}),
libintelrdfpmath-dev (>= 2.0u2-6),
${misc:Depends}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
${misc:Depends}
libdfp-dev,
${misc:Depends}

We should specify libdfp-dev here, as things like headers, static libraries, and configure scripts could be needed by consumers of libmongocrypt.

Description: client-side field level encryption library - dev files
libmongocrypt facilitates the client-side encryption and decryption,
Expand Down
14 changes: 14 additions & 0 deletions etc/rpm/tweak.awk
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@
# Drop the source. We're bringing our own
/Source0/ { next }

/%package devel/ {
# Insert a dep on 'libdfp-devel'
print
print "BuildRequires: libdfp-devel"
print "Requires: libdfp"
next
}

/-DMONGOCRYPT_MONGOC_DIR:STRING=USE-SYSTEM/ {
print
print " -DMONGOCRYPT_DFP_DIR=USE-SYSTEM \\"
next
}

# Replace the autosetup with one that copies the source tree into place
/%autosetup/ {
print "cp -rf %{_sourcedir}/. %{_builddir}/\n" \
Expand Down
Loading