include (FetchContent) find_program (GIT_EXECUTABLE git) find_program (PATCH_EXECUTABLE patch) set (_default_url "${PROJECT_SOURCE_DIR}/third-party/IntelRDFPMathLib20U2.tar.xz") set (INTEL_DFP_LIBRARY_URL "${_default_url}" CACHE STRING "The URL of an Intel DFP library to use") set (INTEL_DFP_LIBRARY_URL_HASH "SHA256=ac157e69c05556f3fa468ab34caeb1114a3b88ae18241bd41cc57b85a02dd314" CACHE STRING "The hash of the archive that lives at INTEL_DFP_LIBRARY_URL (Spelled: =)") option (INTEL_DFP_LIBRARY_PATCH_ENABLED "Whether to apply patches to the Intel DFP library" ON) set (_hash_arg) if (NOT INTEL_DFP_LIBRARY_URL_SHA256 STREQUAL "no-verify") set (_hash_arg URL_HASH "${INTEL_DFP_LIBRARY_URL_HASH}") endif () # Make the PATCH_COMMAND a no-op if it was disabled set (patch_command) if (NOT INTEL_DFP_LIBRARY_PATCH_ENABLED) set (patch_command "${CMAKE_COMMAND}" -E true) elseif (GIT_EXECUTABLE) set (patch_command "${GIT_EXECUTABLE}" --work-tree= apply) else () set (patch_command "${PATCH_EXECUTABLE}" --dir=) endif () # NOTE: The applying of the patch expects the correct input directly from the # expanded archive. If the patch needs to be reapplied, you may see errors # about trying to update the intel_dfp component. If you are seeing such # errors, delete the `_deps/` subdirectory in the build tree and # re-run CMake the project. FetchContent_Declare ( intel_dfp URL "${_default_url}" ${_hash_arg} PATCH_COMMAND ${patch_command} -p 4 # Strip four path components "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-s390x.patch" "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-MONGOCRYPT-571.patch" "${PROJECT_SOURCE_DIR}/etc/mongo-inteldfp-libmongocrypt-pr-625.patch" --verbose ) FetchContent_GetProperties (intel_dfp) if (NOT intel_dfp_POPULATED) message (STATUS "Obtaining Intel Decimal FP library: ${INTEL_DFP_LIBRARY_URL}") FetchContent_Populate (intel_dfp) endif () # This list of sources matches the ones used within MongoDB server. The # "" prefix is replaced below. # Refer: https://github.com/mongodb/mongo/blob/e9be40f47a77af1931773ad671d4927c0fe6969a/src/third_party/IntelRDFPMathLib20U1/SConscript set (_dfp_sources "/float128/dpml_exception.c" "/float128/dpml_four_over_pi.c" "/float128/dpml_ux_bessel.c" "/float128/dpml_ux_bid.c" "/float128/dpml_ux_cbrt.c" "/float128/dpml_ux_erf.c" "/float128/dpml_ux_exp.c" "/float128/dpml_ux_int.c" "/float128/dpml_ux_inv_hyper.c" "/float128/dpml_ux_inv_trig.c" "/float128/dpml_ux_lgamma.c" "/float128/dpml_ux_log.c" "/float128/dpml_ux_mod.c" "/float128/dpml_ux_ops.c" "/float128/dpml_ux_ops_64.c" "/float128/dpml_ux_pow.c" "/float128/dpml_ux_powi.c" "/float128/dpml_ux_sqrt.c" "/float128/dpml_ux_trig.c" "/float128/sqrt_tab_t.c" "/src/bid128.c" "/src/bid128_2_str_tables.c" "/src/bid128_acos.c" "/src/bid128_acosh.c" "/src/bid128_add.c" "/src/bid128_asin.c" "/src/bid128_asinh.c" "/src/bid128_atan.c" "/src/bid128_atan2.c" "/src/bid128_atanh.c" "/src/bid128_cbrt.c" "/src/bid128_compare.c" "/src/bid128_cos.c" "/src/bid128_cosh.c" "/src/bid128_div.c" "/src/bid128_erf.c" "/src/bid128_erfc.c" "/src/bid128_exp.c" "/src/bid128_exp10.c" "/src/bid128_exp2.c" "/src/bid128_expm1.c" "/src/bid128_fdimd.c" "/src/bid128_fma.c" "/src/bid128_fmod.c" "/src/bid128_frexp.c" "/src/bid128_hypot.c" "/src/bid128_ldexp.c" "/src/bid128_lgamma.c" "/src/bid128_llrintd.c" "/src/bid128_log.c" "/src/bid128_log10.c" "/src/bid128_log1p.c" "/src/bid128_log2.c" "/src/bid128_logb.c" "/src/bid128_logbd.c" "/src/bid128_lrintd.c" "/src/bid128_lround.c" "/src/bid128_minmax.c" "/src/bid128_modf.c" "/src/bid128_mul.c" "/src/bid128_nearbyintd.c" "/src/bid128_next.c" "/src/bid128_nexttowardd.c" "/src/bid128_noncomp.c" "/src/bid128_pow.c" "/src/bid128_quantexpd.c" "/src/bid128_quantize.c" "/src/bid128_rem.c" "/src/bid128_round_integral.c" "/src/bid128_scalb.c" "/src/bid128_scalbl.c" "/src/bid128_sin.c" "/src/bid128_sinh.c" "/src/bid128_sqrt.c" "/src/bid128_string.c" "/src/bid128_tan.c" "/src/bid128_tanh.c" "/src/bid128_tgamma.c" "/src/bid128_to_int16.c" "/src/bid128_to_int32.c" "/src/bid128_to_int64.c" "/src/bid128_to_int8.c" "/src/bid128_to_uint16.c" "/src/bid128_to_uint32.c" "/src/bid128_to_uint64.c" "/src/bid128_to_uint8.c" "/src/bid32_acos.c" "/src/bid32_acosh.c" "/src/bid32_add.c" "/src/bid32_asin.c" "/src/bid32_asinh.c" "/src/bid32_atan.c" "/src/bid32_atan2.c" "/src/bid32_atanh.c" "/src/bid32_cbrt.c" "/src/bid32_compare.c" "/src/bid32_cos.c" "/src/bid32_cosh.c" "/src/bid32_div.c" "/src/bid32_erf.c" "/src/bid32_erfc.c" "/src/bid32_exp.c" "/src/bid32_exp10.c" "/src/bid32_exp2.c" "/src/bid32_expm1.c" "/src/bid32_fdimd.c" "/src/bid32_fma.c" "/src/bid32_fmod.c" "/src/bid32_frexp.c" "/src/bid32_hypot.c" "/src/bid32_ldexp.c" "/src/bid32_lgamma.c" "/src/bid32_llrintd.c" "/src/bid32_log.c" "/src/bid32_log10.c" "/src/bid32_log1p.c" "/src/bid32_log2.c" "/src/bid32_logb.c" "/src/bid32_logbd.c" "/src/bid32_lrintd.c" "/src/bid32_lround.c" "/src/bid32_minmax.c" "/src/bid32_modf.c" "/src/bid32_mul.c" "/src/bid32_nearbyintd.c" "/src/bid32_next.c" "/src/bid32_nexttowardd.c" "/src/bid32_noncomp.c" "/src/bid32_pow.c" "/src/bid32_quantexpd.c" "/src/bid32_quantize.c" "/src/bid32_rem.c" "/src/bid32_round_integral.c" "/src/bid32_scalb.c" "/src/bid32_scalbl.c" "/src/bid32_sin.c" "/src/bid32_sinh.c" "/src/bid32_sqrt.c" "/src/bid32_string.c" "/src/bid32_sub.c" "/src/bid32_tan.c" "/src/bid32_tanh.c" "/src/bid32_tgamma.c" "/src/bid32_to_bid128.c" "/src/bid32_to_bid64.c" "/src/bid32_to_int16.c" "/src/bid32_to_int32.c" "/src/bid32_to_int64.c" "/src/bid32_to_int8.c" "/src/bid32_to_uint16.c" "/src/bid32_to_uint32.c" "/src/bid32_to_uint64.c" "/src/bid32_to_uint8.c" "/src/bid64_acos.c" "/src/bid64_acosh.c" "/src/bid64_add.c" "/src/bid64_asin.c" "/src/bid64_asinh.c" "/src/bid64_atan.c" "/src/bid64_atan2.c" "/src/bid64_atanh.c" "/src/bid64_cbrt.c" "/src/bid64_compare.c" "/src/bid64_cos.c" "/src/bid64_cosh.c" "/src/bid64_div.c" "/src/bid64_erf.c" "/src/bid64_erfc.c" "/src/bid64_exp.c" "/src/bid64_exp10.c" "/src/bid64_exp2.c" "/src/bid64_expm1.c" "/src/bid64_fdimd.c" "/src/bid64_fma.c" "/src/bid64_fmod.c" "/src/bid64_frexp.c" "/src/bid64_hypot.c" "/src/bid64_ldexp.c" "/src/bid64_lgamma.c" "/src/bid64_llrintd.c" "/src/bid64_log.c" "/src/bid64_log10.c" "/src/bid64_log1p.c" "/src/bid64_log2.c" "/src/bid64_logb.c" "/src/bid64_logbd.c" "/src/bid64_lrintd.c" "/src/bid64_lround.c" "/src/bid64_minmax.c" "/src/bid64_modf.c" "/src/bid64_mul.c" "/src/bid64_nearbyintd.c" "/src/bid64_next.c" "/src/bid64_nexttowardd.c" "/src/bid64_noncomp.c" "/src/bid64_pow.c" "/src/bid64_quantexpd.c" "/src/bid64_quantize.c" "/src/bid64_rem.c" "/src/bid64_round_integral.c" "/src/bid64_scalb.c" "/src/bid64_scalbl.c" "/src/bid64_sin.c" "/src/bid64_sinh.c" "/src/bid64_sqrt.c" "/src/bid64_string.c" "/src/bid64_tan.c" "/src/bid64_tanh.c" "/src/bid64_tgamma.c" "/src/bid64_to_bid128.c" "/src/bid64_to_int16.c" "/src/bid64_to_int32.c" "/src/bid64_to_int64.c" "/src/bid64_to_int8.c" "/src/bid64_to_uint16.c" "/src/bid64_to_uint32.c" "/src/bid64_to_uint64.c" "/src/bid64_to_uint8.c" "/src/bid_binarydecimal.c" "/src/bid_convert_data.c" "/src/bid_decimal_data.c" "/src/bid_decimal_globals.c" "/src/bid_dpd.c" "/src/bid_feclearexcept.c" "/src/bid_fegetexceptflag.c" "/src/bid_feraiseexcept.c" "/src/bid_fesetexceptflag.c" "/src/bid_fetestexcept.c" "/src/bid_flag_operations.c" "/src/bid_from_int.c" "/src/bid_round.c" "/src/strtod128.c" "/src/strtod32.c" "/src/strtod64.c" "/src/wcstod128.c" "/src/wcstod32.c" "/src/wcstod64.c" ) # Put in the actual library path: string (REPLACE "" "${intel_dfp_SOURCE_DIR}/LIBRARY" _dfp_sources "${_dfp_sources}") #[[ Intel DFP gives us a very blunt yet powerful hammer to avoid symbol collision, since other library may also want a conflicting DFP version: Just rename everything! All function names are #defined with a `bid` or `binary` prefix, and are aliased to their "actual" names with a `__bid` or `__binary` prefix, respectively. So we can ship our own decimal library without worry, we'll rename those hidden symbols. ]] file (READ "${intel_dfp_SOURCE_DIR}/LIBRARY/src/bid_conf.h" dfp_conf_content) string (REGEX REPLACE #[[ Match every "#define X Y" where X begins with `"bid" or "binary", and Y begins with "__bid" or "__binary". X and Y must be separated by one or more spaces. ]] "#define ((bid|binary)[^ ]+ +)__(bid|binary)([^ +])" # Replace Y with "__mongocrypt_bid" or "__mongocrypt_binary" as the new prefix. "#define \\1 __mongocrypt_\\3\\4" new_content "${dfp_conf_content}" ) if (NOT new_content STREQUAL dfp_conf_content) # Only rewrite the file if we changed anything, otherwise we update build # input timestamps and will trigger a rebuild of DFP. file (WRITE "${intel_dfp_SOURCE_DIR}/LIBRARY/src/bid_conf.h" "${new_content}") endif () # Define the object library add_library (intel_dfp_obj OBJECT ${_dfp_sources}) # Build with -fPIC, since these objects may go into a static OR dynamic library. set_property (TARGET intel_dfp_obj PROPERTY POSITION_INDEPENDENT_CODE TRUE) # DFP needs information about the build target platform. Compute that: set (proc_lower $) set (ia32_list i386 i486 i586 i686 pentium3 pentium4 athlon geode emscripted x86 arm) set (efi2_list aarch64 arm64 x86_64 ppc64le riscv64) set (is_linux $) set (is_windows $) set (is_unix $) # These compiler definitions may seem a bit strange, but the whole DFP library's # config process is strange. These options match those used in MongoDB server. target_compile_definitions (intel_dfp_obj PUBLIC DECIMAL_CALL_BY_REFERENCE=0 DECIMAL_GLOBAL_ROUNDING=0 DECIMAL_GLOBAL_EXCEPTION_FLAGS=0 UNCHANGED_BINARY_STATUS_FLAGS=0 USE_COMPILER_F128_TYPE=0 USE_COMPILER_F80_TYPE=0 USE_NATIVE_QUAD_TYPE=0 $<${is_unix}:LINUX=1> $<$:mach=1> $<$:freebsd=1> $<$:linux=1> $<${is_windows}: WINDOWS=1 WNT=1 winnt=1 > $<$: IA32=1 ia32=1 > $<$: EFI2=1 efi2=1 > $<$: s390x=1 BID_BIG_ENDIAN=1 > ) # Suppress warnings in the Intel library, as it generates a lot that aren't of interest 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) # Notify in-tree consumers that IntelDFP is available: target_compile_definitions (_mongocrypt_intel_dfp INTERFACE $) target_sources (_mongocrypt_intel_dfp #[[ For targets *within this build* that link with mongocrypt::intel_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 will link to libmongocrypt, which will contain the necessary TUs for the library (because they link to this interface library). ]] INTERFACE $> ) target_link_libraries (_mongocrypt_intel_dfp INTERFACE $ # We do want to propagate an interface requirement: Some platforms need a # separate link library to support special math functions. $<$: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)