From 9af0ca76cdb6b45be3a39feca441e9ca169f0d30 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Tue, 15 Sep 2026 11:57:29 +0200 Subject: [PATCH 1/8] [ci] Add Debian testing It's like Debian13, but tests the new libcivetweb-dev package, so builtin_civetweb can be OFF. [ci] disable pyspark on Debiantesting CMake Error at cmake/modules/FindPySpark.cmake:34 (message): Currently, there are no Spark versions that support Java version greater than 21. Found Java version 25.0.4.1. Call Stack (most recent call first): cmake/modules/SearchInstalledSoftware.cmake:1259 (find_package) CMakeLists.txt:131 (include) --- .github/workflows/root-ci-config/buildconfig/debiantesting.txt | 2 ++ .github/workflows/root-ci.yml | 1 + 2 files changed, 3 insertions(+) create mode 100644 .github/workflows/root-ci-config/buildconfig/debiantesting.txt diff --git a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt new file mode 100644 index 0000000000000..425074e32fc19 --- /dev/null +++ b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt @@ -0,0 +1,2 @@ +CMAKE_CXX_STANDARD=23 +test_distrdf_pyspark=OFF diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index c3dbb65dfac62..e4ccda30c4a96 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -409,6 +409,7 @@ jobs: - image: ubuntu2610 - image: debian13 overrides: ["dev=ON", "CMAKE_CXX_FLAGS=-Wsuggest-override"] + - image: debiantesting # Special builds - image: alma9 platform_config: alma9-modules_off From e6b085e15d414f78d9695641dadb747e93249299 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Tue, 15 Sep 2026 17:09:23 +0200 Subject: [PATCH 2/8] [ci] debiantesting: test builtin_llvm=OFF --- .github/workflows/root-ci-config/buildconfig/debiantesting.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt index 425074e32fc19..da54647e3f3a6 100644 --- a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt +++ b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt @@ -1,2 +1,3 @@ CMAKE_CXX_STANDARD=23 +builtin_llvm=OFF test_distrdf_pyspark=OFF From f98c0e9cd4187755d68895dddddac5c35dd70d29 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Tue, 22 Sep 2026 12:45:18 +0200 Subject: [PATCH 3/8] g++16 workaround for lost operator == issue in ROOT rror: /github/home/ROOT-CI/src/roottest/root/tree/selectorreader/runCollections.C:169:37: error: invalid operands to binary expression ('iterator' (aka '__gnu_cxx::__normal_iterator, std::allocator > *, vector, std::allocator >, std::allocator, std::allocator > > > >') and 'iterator') for (std::string const &treeName : trees) ^ /github/home/ROOT-CI/build/include/TString.h:56:9: note: candidate function not viable: no known conversion from 'iterator' (aka '__gnu_cxx::__normal_iterator, std::allocator > *, vector, std::allocator >, std::allocator, std::allocator > > > >') to 'const TString' for 1st argument Bool_t operator==(const TString &s1, const char *s2); ^ ~~~~~~~~~~~~~~~~~ --- roottest/root/meta/genreflex/TClass/TClassUtils.h | 9 +++++---- roottest/root/tree/selectorreader/runClasses.C | 4 ++-- roottest/root/tree/selectorreader/runCollections.C | 4 ++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/roottest/root/meta/genreflex/TClass/TClassUtils.h b/roottest/root/meta/genreflex/TClass/TClassUtils.h index a0571313a8912..1d05f802cc2a0 100644 --- a/roottest/root/meta/genreflex/TClass/TClassUtils.h +++ b/roottest/root/meta/genreflex/TClass/TClassUtils.h @@ -51,10 +51,11 @@ void printMemberNames(const std::string& className, const std::string indent="", std::cout << std::endl; if (mbProp.count(dmName)!=0){ TDictAttributeMap* attrMap = dm->GetAttributeMap(); - for (propertiesNames::iterator prop=mbProp[dmName].begin(); - prop!=mbProp[dmName].end();prop++){ - const char* propVals = attrMap->GetPropertyAsString(prop->c_str()); - std::cout << " - " << *prop << ": " << propVals << std::endl; + propertiesNames &props = mbProp[dmName]; + for (size_t i = 0; i < props.size(); ++i) { + const std::string &prop = props[i]; + const char* propVals = attrMap->GetPropertyAsString(prop.c_str()); + std::cout << " - " << prop << ": " << propVals << std::endl; } } } diff --git a/roottest/root/tree/selectorreader/runClasses.C b/roottest/root/tree/selectorreader/runClasses.C index 912dc429736fc..741c1e58e4b7f 100644 --- a/roottest/root/tree/selectorreader/runClasses.C +++ b/roottest/root/tree/selectorreader/runClasses.C @@ -124,8 +124,8 @@ void runClasses(const std::string &srcdir = ".") { "TreeEventTreeSimple2", "TreeDuplicateName" }; - for (std::string const &treeName : trees) - { + for (size_t i = 0; i < trees.size(); ++i) { + std::string const &treeName = trees[i]; fprintf(stderr, "Testing tree %s\n", treeName.c_str()); TFile f((srcdir + "/trees/" + treeName + ".root").c_str()); // Load file diff --git a/roottest/root/tree/selectorreader/runCollections.C b/roottest/root/tree/selectorreader/runCollections.C index bbe96c09a727c..21956ecc60600 100644 --- a/roottest/root/tree/selectorreader/runCollections.C +++ b/roottest/root/tree/selectorreader/runCollections.C @@ -166,8 +166,8 @@ void runCollections(const std::string &srcdir = ".") //"TreeTClonesArray0", // Known failure "TreeTClonesArray2" }; - for (std::string const &treeName : trees) - { + for (size_t i = 0; i < trees.size(); ++i) { + std::string const &treeName = trees[i]; fprintf(stderr, "Testing tree %s\n", treeName.c_str()); TFile f((srcdir + "/trees/" + treeName + ".root").c_str()); // Load file From c02fc8a2770b5354c2da937a4fccd90ca1b3a1c0 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Tue, 29 Sep 2026 15:56:44 +0200 Subject: [PATCH 4/8] use system mathtext --- .github/workflows/root-ci-config/buildconfig/debiantesting.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt index da54647e3f3a6..896845d08f734 100644 --- a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt +++ b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt @@ -1,3 +1,4 @@ CMAKE_CXX_STANDARD=23 builtin_llvm=OFF +builtin_mathtext=OFF test_distrdf_pyspark=OFF From c052baba75e17a45671777f35a0ad57d3af47d02 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 30 Sep 2026 15:00:57 +0200 Subject: [PATCH 5/8] cherry-pick 23546 from guitargeek --- core/dictgen/src/rootcling_impl.cxx | 96 ++++++++++++++++------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/core/dictgen/src/rootcling_impl.cxx b/core/dictgen/src/rootcling_impl.cxx index e2352b8fe4337..0fe7d172dcf39 100644 --- a/core/dictgen/src/rootcling_impl.cxx +++ b/core/dictgen/src/rootcling_impl.cxx @@ -144,6 +144,10 @@ namespace genreflex { //////////////////////////////////////////////////////////////////////////////// static llvm::cl::OptionCategory gRootclingOptions("rootcling common options"); +// rootcling's options are registered in their own subcommand instead of the top-level one, where LLVM registers its +// options. Otherwise, when linking against a shared libLLVM, names that exist in both (like -W) abort at startup with +// "Option 'W' registered more than once!". RootClingMain selects this subcommand before parsing the command line. +static llvm::cl::SubCommand gRootclingSubcommand("rootcling", "Generate a dictionary."); //////////////////////////////////////////////////////////////////////////////// @@ -3386,17 +3390,17 @@ class TRootClingCallbacks : public cling::InterpreterCallbacks { static llvm::cl::opt gOptSystemModuleByproducts("mSystemByproducts", llvm::cl::Hidden, llvm::cl::desc("Allow implicit build of system modules."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptModuleByproducts("mByproduct", llvm::cl::ZeroOrMore, llvm::cl::Hidden, llvm::cl::desc("The list of the expected implicit modules build as part of building the current module."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); // Really llvm::cl::Required, will be changed in RootClingMain below. static llvm::cl::opt gOptDictionaryFileName(llvm::cl::Positional, llvm::cl::desc(""), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); //////////////////////////////////////////////////////////////////////////////// /// Custom diag client for clang that verifies that each implicitly build module @@ -3533,10 +3537,10 @@ static void MaybeSuppressWin32CrashDialogs() { } static llvm::cl::opt gOptForce("f", llvm::cl::desc("Overwrite s."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptRootBuild("rootbuild", llvm::cl::desc("If we are building ROOT."), llvm::cl::Hidden, - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); enum VerboseLevel { v = ROOT::TMetaUtils::kError, v0 = ROOT::TMetaUtils::kFatal, @@ -3554,96 +3558,96 @@ gOptVerboseLevel(llvm::cl::desc("Choose verbosity level:"), clEnumVal(v3, "Show notes."), clEnumVal(v4, "Show information.")), llvm::cl::init(v2), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptCint("cint", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptReflex("reflex", llvm::cl::desc("Behave internally like genreflex."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptGccXml("gccxml", llvm::cl::desc("Deprecated, legacy flag which is ignored."), llvm::cl::Hidden, - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptLibListPrefix("lib-list-prefix", llvm::cl::desc("An ACLiC feature which exports the list of dependent libraries."), llvm::cl::Hidden, - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptGeneratePCH("generate-pch", llvm::cl::desc("Generates a pch file from a predefined set of headers. See makepch.py."), llvm::cl::Hidden, - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptC("c", llvm::cl::desc("Deprecated, legacy flag which is ignored."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptP("p", llvm::cl::desc("Deprecated, legacy flag which is ignored."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptRootmapLibNames("rml", llvm::cl::ZeroOrMore, llvm::cl::desc("Generate rootmap file."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptRootMapFileName("rmf", llvm::cl::desc("Generate a rootmap file with the specified name."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptCxxModule("cxxmodule", llvm::cl::desc("Generate a C++ module."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptModuleMapFiles("moduleMapFile", llvm::cl::desc("Specify a C++ modulemap file."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); // FIXME: Figure out how to combine the code of -umbrellaHeader and inlineInputHeader static llvm::cl::opt gOptUmbrellaInput("umbrellaHeader", llvm::cl::desc("A single header including all headers instead of specifying them on the command line."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptMultiDict("multiDict", llvm::cl::desc("If this library has multiple separate LinkDef files."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptNoGlobalUsingStd("noGlobalUsingStd", llvm::cl::desc("Do not declare {using namespace std} in dictionary global scope."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptInterpreterOnly("interpreteronly", llvm::cl::desc("Generate minimal dictionary for interactivity (without IO information)."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptSplit("split", llvm::cl::desc("Split the dictionary into two parts: one containing the IO (ClassDef)\ information and another the interactivity support."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptNoDictSelection("noDictSelection", llvm::cl::Hidden, llvm::cl::desc("Do not run the selection rules. Useful when in -onepcm mode."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptSharedLibFileName("s", llvm::cl::desc("The path to the library of the built dictionary."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptModuleDependencies("m", llvm::cl::desc("The list of dependent modules of the dictionary."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptExcludePaths("excludePath", llvm::cl::ZeroOrMore, llvm::cl::desc("Do not store the in the dictionary."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); // FIXME: This does not seem to work. We have one use of -inlineInputHeader in // ROOT and it does not produce the expected result. static llvm::cl::opt gOptInlineInput("inlineInputHeader", llvm::cl::desc("Does not generate #include
but expands the header content."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); // FIXME: This is totally the wrong concept. We should not expose an interface // to be able to tell which component is in the pch and which needs extra // scaffolding for interactive use. Moreover, some of the ROOT components are @@ -3654,61 +3658,61 @@ static llvm::cl::opt gOptWriteEmptyRootPCM("writeEmptyRootPCM", llvm::cl::Hidden, llvm::cl::desc("Does not include the header files as it assumes they exist in the pch."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptCheckSelectionSyntax("selSyntaxOnly", llvm::cl::desc("Check the selection syntax only."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptFailOnWarnings("failOnWarnings", llvm::cl::desc("Fail if there are warnings."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptNoIncludePaths("noIncludePaths", llvm::cl::desc("Do not store include paths but rely on the env variable ROOT_INCLUDE_PATH."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptISysRoot("isysroot", llvm::cl::Prefix, llvm::cl::Hidden, llvm::cl::desc("Specify an isysroot."), - llvm::cl::cat(gRootclingOptions), + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand), llvm::cl::init("-")); static llvm::cl::list gOptIncludePaths("I", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify an include path."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptCompDefaultIncludePaths("compilerI", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a compiler default include path, to suppress unneeded `-isystem` arguments."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptSysIncludePaths("isystem", llvm::cl::ZeroOrMore, llvm::cl::desc("Specify a system include path."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptPPDefines("D", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify defined macros."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptPPUndefines("U", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify undefined macros."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptWDiags("W", llvm::cl::Prefix, llvm::cl::ZeroOrMore, llvm::cl::desc("Specify compiler diagnostics options."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::opt gOptDepFile("MF", llvm::cl::desc("Write dependency output to the specified file."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); // Really OneOrMore, will be changed in RootClingMain below. static llvm::cl::list gOptDictionaryHeaderFiles(llvm::cl::Positional, llvm::cl::ZeroOrMore, llvm::cl::desc(" "), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::list gOptSink(llvm::cl::ZeroOrMore, llvm::cl::Sink, llvm::cl::desc("Consumes all unrecognized options."), - llvm::cl::cat(gRootclingOptions)); + llvm::cl::cat(gRootclingOptions), llvm::cl::sub(gRootclingSubcommand)); static llvm::cl::SubCommand gBareClingSubcommand("bare-cling", "Call directly cling and exit."); @@ -3905,10 +3909,10 @@ int RootClingMain(int argc, #endif // Hide options from llvm which we got from static initialization of libCling. - llvm::cl::HideUnrelatedOptions(/*keep*/gRootclingOptions); + llvm::cl::HideUnrelatedOptions(/*keep*/gRootclingOptions, gRootclingSubcommand); // Define Options aliasses - auto &opts = llvm::cl::getRegisteredOptions(); + auto &opts = llvm::cl::getRegisteredOptions(gRootclingSubcommand); llvm::cl::Option* optHelp = opts["help"]; llvm::cl::alias optHelpAlias1("h", llvm::cl::desc("Alias for -help"), @@ -3917,7 +3921,11 @@ int RootClingMain(int argc, llvm::cl::desc("Alias for -help"), llvm::cl::aliasopt(*optHelp)); - llvm::cl::ParseCommandLineOptions(argc, argv, "rootcling"); + // llvm::cl selects a subcommand by the first argument, so name ours unless bare-cling was asked for. + std::vector clArgs(argv, argv + argc); + if (argc < 2 || gBareClingSubcommand.getName() != argv[1]) + clArgs.insert(clArgs.begin() + 1, gRootclingSubcommand.getName().data()); + llvm::cl::ParseCommandLineOptions(clArgs.size(), clArgs.data(), "rootcling"); const char *etcDir = gDriverConfig->fTROOT__GetEtcDir(); std::string llvmResourceDir = etcDir ? std::string(etcDir) + "/cling" : ""; From 244996055f79a8c470d92d9a11640b6f91930d47 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 30 Sep 2026 15:15:56 +0200 Subject: [PATCH 6/8] new honor dylib flag respect honor variable --- interpreter/CMakeLists.txt | 31 ++++++++++++++++--------------- interpreter/cling/CMakeLists.txt | 8 ++++++-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/interpreter/CMakeLists.txt b/interpreter/CMakeLists.txt index fe0a4b4f36a4f..60b129587f42e 100644 --- a/interpreter/CMakeLists.txt +++ b/interpreter/CMakeLists.txt @@ -21,6 +21,7 @@ set(LLVM_ENABLE_FFI OFF CACHE BOOL "") set(LLVM_ENABLE_OCAMLDOC OFF CACHE BOOL "") set(LLVM_ENABLE_Z3_SOLVER OFF CACHE BOOL "") set(LLVM_ENABLE_WARNINGS OFF CACHE BOOL "") +set(HONOR_EXTERNAL_LLVM_LINK_LLVM_DYLIB OFF CACHE BOOL "Setting this to ON could break ROOT and is not officially supported. If disabled, it force-overwrites all LLVM_LINK_LLVM_DYLIB to OFF. It enabled with builtin_llvm, it follows whatever find_package sets this variable to.") # When ROOT provides zlib as a builtin, disable it in the bundled LLVM so it # cannot discover and link the *system* copy (mixing two versions in one @@ -391,21 +392,21 @@ else() # install-clang-cpp target defined by LLVM's cmake module set(CLANG_LINKS_TO_CREATE clang++ clang-cl) - # Disable linking against shared LLVM - set(LLVM_LINK_LLVM_DYLIB OFF) - # To ensure this override stays constant, we need to avoid subdirectories calling find_package(LLVM), - # which would set it to ON again if system was compiled that way - # Define a macro with a toggle flag to override find_package, that will only be visible in this scope, not in parent one. - # TEMPORARY: remove this workaround once ROOT can link against the shared - # libLLVM.so for builtin_llvm=OFF - macro(find_package _package_name) - if(ROOT_SKIP_FIND_LLVM_WITHIN_CLANG AND "${_package_name}" STREQUAL "LLVM") - message(STATUS "[ROOT] Suppressed find_package(LLVM) at ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}" - " to keep LLVM_LINK_LLVM_DYLIB=OFF.") - else() - _find_package(${_package_name} ${ARGN}) - endif() - endmacro() + if (NOT HONOR_EXTERNAL_LLVM_LINK_LLVM_DYLIB) + set(LLVM_LINK_LLVM_DYLIB OFF) + # Disable linking against shared LLVM in case system-version has shared libs, forces static choice of ROOT + # To ensure this override stays constant, we need to avoid subdirectories calling find_package(LLVM), + # which would set it to ON again if system was compiled that way + # Define a macro with a toggle flag to override find_package, that will only be visible in this scope, not in parent one. + macro(find_package _package_name) + if(ROOT_SKIP_FIND_LLVM_WITHIN_CLANG AND "${_package_name}" STREQUAL "LLVM") + message(STATUS "[ROOT] Suppressed find_package(LLVM) at ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE}" + " to keep LLVM_LINK_LLVM_DYLIB=OFF.") + else() + _find_package(${_package_name} ${ARGN}) + endif() + endmacro() + endif() # Always build LLVM with C++17. It is not necessary to compile with the same # C++ standard as the rest of ROOT and sometimes it doesn't even work. diff --git a/interpreter/cling/CMakeLists.txt b/interpreter/cling/CMakeLists.txt index 4bc38aef6d694..d418493140a0e 100644 --- a/interpreter/cling/CMakeLists.txt +++ b/interpreter/cling/CMakeLists.txt @@ -342,8 +342,12 @@ macro(add_cling_library name) endif() endif() - # Set DISABLE_LLVM_LINK_LLVM_DYLIB to disable linking against shared LLVM - llvm_add_library(${name} ${ARG_ENABLE_SHARED} DISABLE_LLVM_LINK_LLVM_DYLIB ${ARG_UNPARSED_ARGUMENTS} ${srcs}) + set(conditional_llvm_link_flags) + if(NOT HONOR_EXTERNAL_LLVM_LINK_LLVM_DYLIB) + # Set DISABLE_LLVM_LINK_LLVM_DYLIB to disable linking against shared LLVM + set(conditional_llvm_link_flags DISABLE_LLVM_LINK_LLVM_DYLIB) + endif() + llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${conditional_llvm_link_flags} ${ARG_UNPARSED_ARGUMENTS} ${srcs}) if (MSVC AND cling_ex_file_match) # /EHs because cling_runtime_internal_throwIfInvalidPointer is extern ā€œCā€ From 1f0ba08211799573e5adf6b9cce4d013337eb98c Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Wed, 30 Sep 2026 15:27:58 +0200 Subject: [PATCH 7/8] test enable honor dylib link for shared lib llvm rather than static --- .github/workflows/root-ci-config/buildconfig/debiantesting.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt index 896845d08f734..6ced57718cb0f 100644 --- a/.github/workflows/root-ci-config/buildconfig/debiantesting.txt +++ b/.github/workflows/root-ci-config/buildconfig/debiantesting.txt @@ -1,4 +1,5 @@ CMAKE_CXX_STANDARD=23 +HONOR_EXTERNAL_LLVM_LINK_LLVM_DYLIB=ON builtin_llvm=OFF builtin_mathtext=OFF test_distrdf_pyspark=OFF From 106385b5f791cff4049b3207653542c500649297 Mon Sep 17 00:00:00 2001 From: ferdymercury Date: Tue, 22 Sep 2026 14:39:32 +0200 Subject: [PATCH 8/8] [ci] debiantesting with Release do not use debug build type TODO: proper fix would be to skip adding this flag into Cling based on ifdef buildtype Unknown command line argument '-optimize-regalloc=0'. Try: 'cling (LLVM option parsing) --help'2026-09-30T15:00:08.7528489Z cling (LLVM option parsing): Did you mean '--vp-static-alloc=0'? --- .github/workflows/root-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index e4ccda30c4a96..03b4b7d62ce20 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -410,6 +410,7 @@ jobs: - image: debian13 overrides: ["dev=ON", "CMAKE_CXX_FLAGS=-Wsuggest-override"] - image: debiantesting + overrides: ["CMAKE_BUILD_TYPE=Release"] # Special builds - image: alma9 platform_config: alma9-modules_off