From 8c221576b1112f3f961f6e980b22abe25330b365 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Wed, 29 Jul 2026 16:53:02 +0200 Subject: [PATCH 1/4] [test] Add a post-install test for RVec. One of the only builtins that ROOT depends on publicly is VDT. When using RVec.h, the VDT headers need to be visible, so this small test tries to invoke a VDT function on an RVec. --- test/PostInstall/CMakeLists.txt | 6 ++++++ test/PostInstall/testRVec.cxx | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 test/PostInstall/testRVec.cxx diff --git a/test/PostInstall/CMakeLists.txt b/test/PostInstall/CMakeLists.txt index 8d4c7bf4c8f77..0a1622ede53b2 100644 --- a/test/PostInstall/CMakeLists.txt +++ b/test/PostInstall/CMakeLists.txt @@ -80,4 +80,10 @@ if(BUILD_TESTING) ) endif() + + if(TARGET ROOT::ROOTVecOps) + add_executable(RVec testRVec.cxx) + target_link_libraries(RVec PUBLIC ROOT::ROOTVecOps) + add_test(NAME RVec COMMAND $) + endif() endif() diff --git a/test/PostInstall/testRVec.cxx b/test/PostInstall/testRVec.cxx new file mode 100644 index 0000000000000..485b22b09e241 --- /dev/null +++ b/test/PostInstall/testRVec.cxx @@ -0,0 +1,34 @@ +/* +RVec can publicly depend on VDT, so here we ensure that the VDT headers are found correctly. +*/ + +#include + +#include + +#define CHECK(ARG) \ + if (!(ARG)) { \ + success = false; \ + std::cerr << #ARG << " failed\n"; \ + } + +int main() +{ + bool success = true; + + ROOT::RVec rv{{1., 2., 3., 4., 5.}, {1., 2., 3., 4., 5.}}; + auto sum = rv[0] + rv[1]; + CHECK(sum.size() == rv[0].size()) + CHECK(sum[3] == 8.) + +#ifdef R__HAS_VDT + ROOT::RVecD rv2{1., 2., 3., 4., 5.}; + auto logs = fast_log(rv2); + CHECK(std::fabs(logs[0]) < 1.E-15) + CHECK(std::fabs(logs[1] - std::log(2.)) < 1.E-15); + if (!success) + std::cout << "logs=" << logs << "\n"; +#endif + + return success ? 0 : 1; +} From fac13c98edda09a338300bcaba21174e169484a5 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 4 Aug 2026 11:20:49 +0200 Subject: [PATCH 2/4] [VecOps] Remove unused includes. --- math/vecops/inc/ROOT/RVec.hxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/math/vecops/inc/ROOT/RVec.hxx b/math/vecops/inc/ROOT/RVec.hxx index 4630b75d74ff6..282160e27311f 100644 --- a/math/vecops/inc/ROOT/RVec.hxx +++ b/math/vecops/inc/ROOT/RVec.hxx @@ -36,9 +36,8 @@ #include // for std::make_move_iterator #include // for numeric_limits #include // uninitialized_value_construct -#include #include // for inner_product -#include +#include #include #include #include From a519dfb8f894a6cc2be8fc20bfcb779099426a49 Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 4 Aug 2026 11:19:08 +0200 Subject: [PATCH 3/4] [VecOps] Outline VDT functions, make VDT a private dependency. By moving all calls to VDT to the .cxx, the interpreter doesn't need to know about it, and ROOT doesn't need to install builtin-vdt's headers. - Outline all vdt-related functions in RVec.cxx - Convert the builtin-vdt library from .so to header only - Move the builtin-vdt artifacts to builtins/vdt/install - Don't install any of VDT's artifacts Fix #9736. --- builtins/vdt/CMakeLists.txt | 27 +++++-------- math/vecops/CMakeLists.txt | 2 +- math/vecops/inc/ROOT/RVec.hxx | 67 +++++++++------------------------ math/vecops/src/RVec.cxx | 51 +++++++++++++++---------- math/vecops/test/CMakeLists.txt | 4 ++ 5 files changed, 63 insertions(+), 88 deletions(-) diff --git a/builtins/vdt/CMakeLists.txt b/builtins/vdt/CMakeLists.txt index a05772b0abaac..b5feb8e6b345d 100644 --- a/builtins/vdt/CMakeLists.txt +++ b/builtins/vdt/CMakeLists.txt @@ -1,11 +1,12 @@ +set(VDT_INSTALL_DIR ${CMAKE_BINARY_DIR}/builtins/vdt/install/) set(ROOT_VDT_VERSION 0.4.6) set(VDT_FOUND True) -set(VDT_LIBRARIES "${CMAKE_BINARY_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}vdt${CMAKE_SHARED_LIBRARY_SUFFIX}") +set(VDT_LIBRARIES "${VDT_INSTALL_DIR}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}vdt${CMAKE_SHARED_LIBRARY_SUFFIX}") ExternalProject_Add( BUILTIN_VDT URL ${lcgpackages}/vdt-${ROOT_VDT_VERSION}.tar.gz URL_HASH SHA256=1820feae446780763ec8bbb60a0dbcf3ae1ee548bdd01415b1fb905fd4f90c54 - INSTALL_DIR ${CMAKE_BINARY_DIR} + INSTALL_DIR ${VDT_INSTALL_DIR} CMAKE_ARGS -DCMAKE_POLICY_VERSION_MINIMUM=3.5 -DSSE=OFF # breaks on ARM without this @@ -19,24 +20,14 @@ ExternalProject_Add( BUILD_BYPRODUCTS ${VDT_LIBRARIES} TIMEOUT 600 ) -ExternalProject_Add_Step( - BUILTIN_VDT copy2externals - COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/include/vdt ${CMAKE_BINARY_DIR}/ginclude/vdt - DEPENDEES install -) -set(VDT_INCLUDE_DIR ${CMAKE_BINARY_DIR}/ginclude) -set(VDT_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/ginclude) +set(VDT_INCLUDE_DIR ${VDT_INSTALL_DIR}/include) +set(VDT_INCLUDE_DIRS ${VDT_INSTALL_DIR}/include) -add_library(VDT::VDT SHARED IMPORTED GLOBAL) +file(MAKE_DIRECTORY ${VDT_INCLUDE_DIR}) +# Try to use VDT header only, and only PRIVATE. This will simplify installing it +add_library(VDT::VDT INTERFACE IMPORTED GLOBAL) add_dependencies(VDT::VDT BUILTIN_VDT) -set_target_properties(VDT::VDT PROPERTIES IMPORTED_LOCATION ${VDT_LIBRARIES}) -target_include_directories(VDT::VDT INTERFACE $ $) - -install(FILES ${VDT_LIBRARIES} - DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries) -install(DIRECTORY ${CMAKE_BINARY_DIR}/include/vdt - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} COMPONENT extra-headers) -set_property(GLOBAL APPEND PROPERTY ROOT_BUILTIN_TARGETS VDT::VDT) +target_include_directories(VDT::VDT INTERFACE $) set(VDT_VERSION ${ROOT_VDT_VERSION} PARENT_SCOPE) set(VDT_FOUND ${VDT_FOUND} PARENT_SCOPE) diff --git a/math/vecops/CMakeLists.txt b/math/vecops/CMakeLists.txt index d5745865745ce..f9623f1ea0be7 100644 --- a/math/vecops/CMakeLists.txt +++ b/math/vecops/CMakeLists.txt @@ -20,7 +20,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTVecOps ) if(builtin_vdt OR vdt) - target_link_libraries(ROOTVecOps PUBLIC VDT::VDT) + target_link_libraries(ROOTVecOps PRIVATE VDT::VDT) endif() include(CheckCXXSymbolExists) diff --git a/math/vecops/inc/ROOT/RVec.hxx b/math/vecops/inc/ROOT/RVec.hxx index 282160e27311f..eb50279bd2f30 100644 --- a/math/vecops/inc/ROOT/RVec.hxx +++ b/math/vecops/inc/ROOT/RVec.hxx @@ -45,11 +45,6 @@ #include #include -#ifdef R__HAS_VDT -#include -#endif - - namespace ROOT { namespace VecOps { @@ -1866,26 +1861,24 @@ RVEC_STD_UNARY_FUNCTION(tgamma) ///@{ #ifdef R__HAS_VDT -#define RVEC_VDT_UNARY_FUNCTION(F) RVEC_UNARY_FUNCTION(F, vdt::F) - -RVEC_VDT_UNARY_FUNCTION(fast_expf) -RVEC_VDT_UNARY_FUNCTION(fast_logf) -RVEC_VDT_UNARY_FUNCTION(fast_sinf) -RVEC_VDT_UNARY_FUNCTION(fast_cosf) -RVEC_VDT_UNARY_FUNCTION(fast_tanf) -RVEC_VDT_UNARY_FUNCTION(fast_asinf) -RVEC_VDT_UNARY_FUNCTION(fast_acosf) -RVEC_VDT_UNARY_FUNCTION(fast_atanf) - -RVEC_VDT_UNARY_FUNCTION(fast_exp) -RVEC_VDT_UNARY_FUNCTION(fast_log) -RVEC_VDT_UNARY_FUNCTION(fast_sin) -RVEC_VDT_UNARY_FUNCTION(fast_cos) -RVEC_VDT_UNARY_FUNCTION(fast_tan) -RVEC_VDT_UNARY_FUNCTION(fast_asin) -RVEC_VDT_UNARY_FUNCTION(fast_acos) -RVEC_VDT_UNARY_FUNCTION(fast_atan) -#undef RVEC_VDT_UNARY_FUNCTION + +RVec fast_expf(const RVec &v); +RVec fast_logf(const RVec &v); +RVec fast_sinf(const RVec &v); +RVec fast_cosf(const RVec &v); +RVec fast_tanf(const RVec &v); +RVec fast_asinf(const RVec &v); +RVec fast_acosf(const RVec &v); +RVec fast_atanf(const RVec &v); + +RVec fast_exp(const RVec &v); +RVec fast_log(const RVec &v); +RVec fast_sin(const RVec &v); +RVec fast_cos(const RVec &v); +RVec fast_tan(const RVec &v); +RVec fast_asin(const RVec &v); +RVec fast_acos(const RVec &v); +RVec fast_atan(const RVec &v); #endif // R__HAS_VDT @@ -3741,30 +3734,6 @@ RVEC_EXTERN_STD_FUNCTIONS(double) #undef RVEC_EXTERN_STD_BINARY_FUNCTION #undef RVEC_EXTERN_STD_UNARY_FUNCTIONS -#ifdef R__HAS_VDT - -#define RVEC_EXTERN_VDT_UNARY_FUNCTION(T, F) RVEC_EXTERN_UNARY_FUNCTION(T, F, vdt::F) - -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_expf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_logf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_sinf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_cosf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_tanf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_asinf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_acosf) -RVEC_EXTERN_VDT_UNARY_FUNCTION(float, fast_atanf) - -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_exp) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_log) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_sin) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_cos) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_tan) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_asin) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_acos) -RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_atan) - -#endif // R__HAS_VDT - #endif // _VECOPS_USE_EXTERN_TEMPLATES /** @} */ // end of Doxygen group vecops diff --git a/math/vecops/src/RVec.cxx b/math/vecops/src/RVec.cxx index 6f54578478ecb..6dee0f204199b 100644 --- a/math/vecops/src/RVec.cxx +++ b/math/vecops/src/RVec.cxx @@ -13,6 +13,10 @@ #include "ROOT/RVec.hxx" using namespace ROOT::VecOps; +#ifdef R__HAS_VDT +#include "vdt/vdtMath.h" +#endif + // Check that no bytes are wasted and everything is well-aligned. namespace { struct Struct16B { @@ -236,26 +240,33 @@ RVEC_DECLARE_STD_FUNCTIONS(double) #ifdef R__HAS_VDT -#define RVEC_DECLARE_VDT_UNARY_FUNCTION(T, F) \ - RVEC_DECLARE_UNARY_FUNCTION(T, F, vdt::F) - -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_expf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_logf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_sinf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_cosf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_tanf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_asinf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_acosf) -RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_atanf) - -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_exp) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_log) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_sin) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_cos) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_tan) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_asin) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_acos) -RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_atan) +#define RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(FP, FUNC) \ + RVec FUNC(RVec const &in) \ + { \ + RVec out(in.size()); \ + for (unsigned int i = 0; i < in.size(); ++i) { \ + out[i] = vdt::FUNC(in[i]); \ + } \ + return out; \ + } + +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_expf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_logf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_sinf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_cosf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_tanf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_asinf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_acosf) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_atanf) + +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_exp) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_log) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_sin) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_cos) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_tan) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_asin) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_acos) +RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_atan) #endif // R__HAS_VDT diff --git a/math/vecops/test/CMakeLists.txt b/math/vecops/test/CMakeLists.txt index a99e84dc9922f..f344d27ee7fd2 100644 --- a/math/vecops/test/CMakeLists.txt +++ b/math/vecops/test/CMakeLists.txt @@ -5,3 +5,7 @@ # For the list of contributors see $ROOTSYS/README/CREDITS. ROOT_ADD_GTEST(vecops_rvec vecops_rvec.cxx LIBRARIES Physics ROOTVecOps GenVector RIO Tree) + +if(TARGET VDT::VDT) + target_link_libraries(vecops_rvec PRIVATE VDT::VDT) +endif() From 75a613fa82fa46dd7c74c91773bd256f6d8752ed Mon Sep 17 00:00:00 2001 From: Stephan Hageboeck Date: Tue, 4 Aug 2026 13:29:37 +0200 Subject: [PATCH 4/4] [CMake] Stop searching for VDT when ROOT is installed. Now that the VDT dependency is private, an installed ROOT does not anymore require VDT. --- CMakeLists.txt | 3 --- cmake/scripts/ROOTConfig.cmake.in | 12 ------------ 2 files changed, 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 23f6b90b10453..43418679c479c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -659,9 +659,6 @@ if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_INSTALL_PREFIX) cmake/modules/RootMacros.cmake cmake/modules/RootTestDriver.cmake DESTINATION ${CMAKE_INSTALL_CMAKEDIR}) - install(FILES - "cmake/modules/FindVdt.cmake" - DESTINATION "${CMAKE_INSTALL_CMAKEDIR}/modules") endif() #---Add configuration files for kernel and jupyter---------------------------------------------- diff --git a/cmake/scripts/ROOTConfig.cmake.in b/cmake/scripts/ROOTConfig.cmake.in index cf6b139a5d467..4ae2c2d371afa 100644 --- a/cmake/scripts/ROOTConfig.cmake.in +++ b/cmake/scripts/ROOTConfig.cmake.in @@ -129,18 +129,6 @@ if(ROOT_minuit2_omp_FOUND) find_dependency(OpenMP) find_dependency(Threads) endif() -if(ROOT_vdt_FOUND AND NOT TARGET VDT::VDT) - if(ROOT_builtin_vdt_FOUND) - function(find_builtin_vdt) - # the function is to create a scope (could use block() but requires CMake>=3.25) - set(CMAKE_PREFIX_PATH ${ROOT_INCLUDE_DIRS} ${ROOT_LIBRARY_DIR}) - find_dependency(Vdt) - endfunction() - find_builtin_vdt() - else() - find_dependency(Vdt) - endif() -endif() #---------------------------------------------------------------------------- # Now set them to ROOT_LIBRARIES