diff --git a/.github/workflows/root-ci-config/buildconfig/opensuse15-march_native.txt b/.github/workflows/root-ci-config/buildconfig/opensuse15-march_native.txt index 92db1d48e403f..81d4de41b6568 100644 --- a/.github/workflows/root-ci-config/buildconfig/opensuse15-march_native.txt +++ b/.github/workflows/root-ci-config/buildconfig/opensuse15-march_native.txt @@ -1,14 +1,15 @@ CMAKE_CXX_FLAGS=-march=native -CMAKE_C_FLAGS=-march=native CMAKE_CXX_STANDARD=20 +CMAKE_C_FLAGS=-march=native +builtin_nlohmannjson=ON builtin_tbb=ON +builtin_unuran=ON builtin_vdt=ON builtin_xrootd=ON -builtin_unuran=ON -builtin_nlohmannjson=ON +gnuinstall=ON +pythia8=OFF +r=OFF test_distrdf_dask=OFF test_distrdf_pyspark=OFF tmva-pymva=ON tmva-sofie=ON -pythia8=OFF -r=OFF diff --git a/.github/workflows/root-ci.yml b/.github/workflows/root-ci.yml index fda8d764cae10..ce71bbe4e96d8 100644 --- a/.github/workflows/root-ci.yml +++ b/.github/workflows/root-ci.yml @@ -130,6 +130,11 @@ jobs: - platform: mac-beta is_special: true arch: ARM64 + # For the PR and incremental builds, we set gnuinstall=ON to check + # if CMake can deal with the different structure of the install and + # build tree at build and test time. We don't care how the install + # actually looks like. + overrides: ["gnuinstall=ON"] runs-on: - self-hosted diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b092fe9f969b..55ad8a1486780 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -507,7 +507,7 @@ else() ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/cmake/unix/makepchinput.py ${CMAKE_SOURCE_DIR} . ${pyroot_legacy} ${__cling_pch} COMMAND - ${CMAKE_COMMAND} -E env ROOTIGNOREPREFIX=1 ${Python3_EXECUTABLE} + ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/etc/dictpch/makepch.py etc/allDict.cxx.pch ${__allIncludes} -I${CMAKE_BINARY_DIR}/include -I${CMAKE_SOURCE_DIR}/core DEPENDS @@ -541,10 +541,10 @@ if(runtime_cxxmodules) get_property(modules_idx_deps GLOBAL PROPERTY modules_idx_deps_property) if(WIN32) set(modules_idx_cmd COMMAND ${CMAKE_COMMAND} -E env PATH="${library_output_dir}\\\;%PATH%" - ROOTIGNOREPREFIX=1 ROOT_HIST=0 $ -l -q -b) + ROOT_HIST=0 $ -l -q -b) else() set(modules_idx_cmd COMMAND ROOT_INCLUDE_PATH=${DEFAULT_ROOT_INCLUDE_PATH} - ROOTIGNOREPREFIX=1 ROOT_HIST=0 $ -l -q -b) + ROOT_HIST=0 $ -l -q -b) endif() add_custom_command(OUTPUT ${library_output_dir}/modules.idx COMMAND ${CMAKE_COMMAND} -E remove -f modules.idx modules.timestamp @@ -570,7 +570,6 @@ if(NOT CMAKE_CROSSCOMPILING) COMMAND ${CMAKE_COMMAND} -E env ROOT_INCLUDE_PATH=${DEFAULT_ROOT_INCLUDE_PATH} - ROOTIGNOREPREFIX=1 ROOT_HIST=0 $ -q -b -n -e ".L ${CMAKE_SOURCE_DIR}/tutorials/hsimple.C" diff --git a/cmake/modules/CheckCompiler.cmake b/cmake/modules/CheckCompiler.cmake index 62e9f0ce9c402..a2e1772967ccf 100644 --- a/cmake/modules/CheckCompiler.cmake +++ b/cmake/modules/CheckCompiler.cmake @@ -254,10 +254,6 @@ if(gcctoolchain) endif() endif() -if(gnuinstall) - set(R__HAVE_CONFIG 1) -endif() - #---Check if we use the new libstdc++ CXX11 ABI----------------------------------------------------- # Necessary to compile check_cxx_source_compiles this early include(CheckCXXSourceCompiles) diff --git a/cmake/modules/RootMacros.cmake b/cmake/modules/RootMacros.cmake index 9e1dfce102fef..067b6e1fdbc54 100644 --- a/cmake/modules/RootMacros.cmake +++ b/cmake/modules/RootMacros.cmake @@ -651,12 +651,12 @@ function(ROOT_GENERATE_DICTIONARY dictionary) else() if(CMAKE_PROJECT_NAME STREQUAL ROOT) if(MSVC AND CMAKE_ROOTTEST_DICT) - set(command ${CMAKE_COMMAND} -E env "ROOTIGNOREPREFIX=1" ${CMAKE_BINARY_DIR}/bin/rootcling.exe -rootbuild) + set(command ${CMAKE_BINARY_DIR}/bin/rootcling.exe -rootbuild) else() if(APPLE) - set(command ${CMAKE_COMMAND} -E env "ROOTIGNOREPREFIX=1" SDKROOT=${CMAKE_OSX_SYSROOT} $ -rootbuild) + set(command ${CMAKE_COMMAND} -E env SDKROOT=${CMAKE_OSX_SYSROOT} $ -rootbuild) else() - set(command ${CMAKE_COMMAND} -E env "ROOTIGNOREPREFIX=1" $ -rootbuild) + set(command $ -rootbuild) endif() # Modules need RConfigure.h copied into include/. set(ROOTCLINGDEP rootcling rconfigure) @@ -1817,9 +1817,6 @@ function(ROOT_ADD_TEST test) set_property(TEST ${test} PROPERTY ENVIRONMENT ROOT_DIR=${CMAKE_BINARY_DIR}) else() add_test(NAME ${test} COMMAND ${_command}) - if (gnuinstall) - set_property(TEST ${test} PROPERTY ENVIRONMENT ROOTIGNOREPREFIX=1) - endif() endif() #- provided fixtures and resource lock are set here diff --git a/cmake/scripts/compiledata.win32.in b/cmake/scripts/compiledata.win32.in index 15bb379bbf89c..e2d9d2218193a 100644 --- a/cmake/scripts/compiledata.win32.in +++ b/cmake/scripts/compiledata.win32.in @@ -1,15 +1,14 @@ -/* This file is automatically generated */ #define BUILD_ARCH "@ROOT_ARCHITECTURE@" #define BUILD_NODE "@BuildNodeInfo@" #define CXX "@CMAKE_CXX_COMPILER@" #define COMPILER "@CMAKE_CXX_COMPILER@" #define COMPILERVERS "@CMAKE_CXX_COMPILER_ID@ @CMAKE_CXX_COMPILER_VERSION@" #define COMPILERVERSSTR "@CMAKE_CXX_COMPILER_ID@ @CMAKE_CXX_COMPILER_VERSION@" -#define MAKESHAREDLIB "cl $Opt -nologo -TP -c @CMAKE_CXX_FLAGS@ @BLDCXXFLAGS@ $IncludePath $SourceFiles -Fo$ObjectFiles && bindexplib $LibName $ObjectFiles > $BuildDir\\$LibName.def && lib -nologo -MACHINE:@MACHINE_ARCH@ -out:$BuildDir\\$LibName.lib $ObjectFiles -def:$BuildDir\\$LibName.def && link -nologo $ObjectFiles -DLL -out:$BuildDir\\$LibName.dll $BuildDir\\$LibName.exp -LIBPATH:%ROOTSYS%\\lib $LinkedLibs libCore.lib kernel32.lib advapi32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib && if EXIST \"$BuildDir\\$LibName.dll.manifest\" ( mt -nologo -manifest \"$BuildDir\\$LibName.dll.manifest\" \"-outputresource:$BuildDir\\$LibName.dll;2\" && del \"$BuildDir\\$LibName.dll.manifest\" )" +#define MAKESHAREDLIB "cl $Opt -nologo -TP -c @CMAKE_CXX_FLAGS@ @BLDCXXFLAGS@ $IncludePath $SourceFiles -Fo$ObjectFiles && $BinDir\\bindexplib $LibName $ObjectFiles > $BuildDir\\$LibName.def && lib -nologo -MACHINE:@MACHINE_ARCH@ -out:$BuildDir\\$LibName.lib $ObjectFiles -def:$BuildDir\\$LibName.def && link -nologo $ObjectFiles -DLL -out:$BuildDir\\$LibName.dll $BuildDir\\$LibName.exp -LIBPATH:$LibDir $LinkedLibs libCore.lib kernel32.lib advapi32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib && if EXIST \"$BuildDir\\$LibName.dll.manifest\" ( mt -nologo -manifest \"$BuildDir\\$LibName.dll.manifest\" \"-outputresource:$BuildDir\\$LibName.dll;2\" && del \"$BuildDir\\$LibName.dll.manifest\" )" #define MAKEEXE "cl -nologo -TP -Iinclude -I..\\include -c $Opt @CMAKE_CXX_FLAGS@ @BLDCXXFLAGS@ $IncludePath $SourceFiles && link -opt:ref @CMAKE_EXE_FLAGS@ $ObjectFiles $LinkedLibs advapi32.lib -out:$ExeName && if EXIST \"$ExeName.exe.manifest\" ( mt -nologo -manifest \"$ExeName.exe.manifest\" \"-outputresource:$ExeName.exe;1\" && del \"$ExeName.exe.manifest\" )" #define CXXOPT "@CMAKE_CXX_FLAGS_RELEASE@ @BLDCXXFLAGS@" #define CXXDEBUG "@CMAKE_CXX_FLAGS_DEBUG@ @BLDCXXFLAGS@" #define ROOTBUILD "release" -#define LINKEDLIBS "-LIBPATH:%ROOTSYS%\\lib libCore.lib " +#define LINKEDLIBS "-LIBPATH:$LibDir libCore.lib " #define OBJEXT "obj" #define SOEXT "dll" diff --git a/config/RConfigure.in b/config/RConfigure.in index 7c81b9dd28025..8aa843e1c47c6 100644 --- a/config/RConfigure.in +++ b/config/RConfigure.in @@ -3,22 +3,6 @@ /* Configurations file for @architecture@ */ -#cmakedefine R__HAVE_CONFIG - -#ifdef R__HAVE_CONFIG -#define ROOTPREFIX "@prefix@" -#define ROOTBINDIR "@bindir@" -#define ROOTLIBDIR "@libdir@" -#define ROOTETCDIR "@etcdir@" -#define ROOTDATADIR "@datadir@" -#define ROOTDOCDIR "@docdir@" -#define ROOTMACRODIR "@macrodir@" -#define ROOTTUTDIR "@tutdir@" -#define ROOTSRCDIR "@srcdir@" -#define ROOTICONPATH "@iconpath@" -#define TTFFONTDIR "@ttffontdir@" -#endif - #define EXTRAICONPATH "@extraiconpath@" #define ROOT__cplusplus @__cplusplus@ diff --git a/core/base/CMakeLists.txt b/core/base/CMakeLists.txt index 0ce55d1ff4a27..902677e79901e 100644 --- a/core/base/CMakeLists.txt +++ b/core/base/CMakeLists.txt @@ -240,20 +240,49 @@ endif() # Absolue CMAKE_INSTALL_ paths are discouraged in CMake, but some # packagers use them anyway. So we support it. -if(IS_ABSOLUTE ${CMAKE_INSTALL_INCLUDEDIR}) - set(install_lib_to_include "${CMAKE_INSTALL_INCLUDEDIR}") -else() - if(IS_ABSOLUTE ${CMAKE_INSTALL_LIBDIR}) - set(libdir "${CMAKE_INSTALL_LIBDIR}") + +function(install_path_from_libdir out_var install_dir) + if(IS_ABSOLUTE "${install_dir}") + set(install_dir_absolute "${install_dir}") else() - set(libdir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") + set(install_dir_absolute "${CMAKE_INSTALL_PREFIX}/${install_dir}") endif() - file(RELATIVE_PATH install_lib_to_include "${libdir}" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") - unset(libdir) + file(RELATIVE_PATH _rel "${libdir}" "${install_dir_absolute}") + set("${out_var}" "${_rel}" PARENT_SCOPE) +endfunction() + +if(IS_ABSOLUTE "${CMAKE_INSTALL_LIBDIR}") + set(libdir "${CMAKE_INSTALL_LIBDIR}") +else() + set(libdir "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") endif() +install_path_from_libdir(install_lib_to_bin "${CMAKE_INSTALL_BINDIR}") +install_path_from_libdir(install_lib_to_data "${CMAKE_INSTALL_DATADIR}") +install_path_from_libdir(install_lib_to_docs "${CMAKE_INSTALL_DOCDIR}") +install_path_from_libdir(install_lib_to_etc "${CMAKE_INSTALL_SYSCONFDIR}") +install_path_from_libdir(install_lib_to_fonts "${CMAKE_INSTALL_FONTDIR}") +install_path_from_libdir(install_lib_to_icons "${CMAKE_INSTALL_ICONDIR}") +install_path_from_libdir(install_lib_to_include "${CMAKE_INSTALL_INCLUDEDIR}") +install_path_from_libdir(install_lib_to_macros "${CMAKE_INSTALL_MACRODIR}") +install_path_from_libdir(install_lib_to_rootsys "${CMAKE_INSTALL_PREFIX}") +install_path_from_libdir(install_lib_to_src "${CMAKE_INSTALL_SRCDIR}") +install_path_from_libdir(install_lib_to_tutorials "${CMAKE_INSTALL_TUTDIR}") + +unset(libdir) + target_compile_options(Core PRIVATE -DLIB_CORE_NAME=${full_core_filename} + -DINSTALL_LIB_TO_BIN="${install_lib_to_bin}" + -DINSTALL_LIB_TO_DATA="${install_lib_to_data}" + -DINSTALL_LIB_TO_DOCS="${install_lib_to_docs}" + -DINSTALL_LIB_TO_ETC="${install_lib_to_etc}" + -DINSTALL_LIB_TO_FONTS="${install_lib_to_fonts}" + -DINSTALL_LIB_TO_ICONS="${install_lib_to_icons}" -DINSTALL_LIB_TO_INCLUDE="${install_lib_to_include}" + -DINSTALL_LIB_TO_MACROS="${install_lib_to_macros}" + -DINSTALL_LIB_TO_ROOTSYS="${install_lib_to_rootsys}" + -DINSTALL_LIB_TO_SRC="${install_lib_to_src}" + -DINSTALL_LIB_TO_TUTORIALS="${install_lib_to_tutorials}" ) add_dependencies(Core ensure_build_tree_marker) diff --git a/core/base/inc/TROOT.h b/core/base/inc/TROOT.h index f7692a5db7da2..d5436ad2ac802 100644 --- a/core/base/inc/TROOT.h +++ b/core/base/inc/TROOT.h @@ -394,6 +394,23 @@ namespace ROOT { inline Bool_t RequiresCleanup(TObject &obj) { return obj.TestBit(kIsReferenced) && obj.GetUniqueID() == 0; } + + struct ResourceDirs { + bool initialized = false; + TString bin; + TString data; + TString docs; + TString etc; + TString fonts; + TString icons; + TString include; + TString macros; + TString rootsys; + TString src; + TString tutorials; + }; + + ResourceDirs const &GetResourceDirs(); } /// \brief call RecursiveRemove for obj if gROOT is valid diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index 700e01f15ce09..2a813818fca1e 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -633,6 +633,40 @@ Int_t gDebug; TROOT::TROOT() : TDirectory() {} +namespace { + +void WarnIfInconsistentRootSys() +{ + namespace fs = std::filesystem; + + const char *envRootSys = std::getenv("ROOTSYS"); + if (!envRootSys) { + return; + } + bool isConsistent = false; + // Should never throw because it's a valid path + fs::path detected = fs::canonical(TROOT::GetRootSys().Data()); + try { + fs::path fromEnv = fs::canonical(envRootSys); + if (detected == fromEnv) { + isConsistent = true; + } + } catch (const fs::filesystem_error &) { + // Tappens if the path in ROOTSYS fails to canonicalize, e.g. because the + // directory doesn't exist. In that case, we also print the warning. + } + if (isConsistent) + return; + Warning("TROOT", + "ROOTSYS is set but inconsistent with detected ROOT installation:\n" + " ROOTSYS=%s\n" + " Detected=%s\n" + "ROOT will use the detected installation.", + envRootSys, detected.string().c_str()); +} + +} // namespace + //////////////////////////////////////////////////////////////////////////////// /// Initialize the ROOT system. The creation of the TROOT object initializes /// the ROOT system. It must be the first ROOT related action that is @@ -689,6 +723,10 @@ TROOT::TROOT(const char *name, const char *title, VoidFuncPtr_t *initfunc) : TDi GetIconPath(); GetTTFFontDir(); + // Warn if ROOTSYS is in the environment, but it's inconsistent with what + // TROOT has figured out. + WarnIfInconsistentRootSys(); + gRootDir = GetRootSys().Data(); TDirectory::BuildDirectory(nullptr, nullptr); @@ -2980,42 +3018,68 @@ const char**& TROOT::GetExtraInterpreterArgs() { //////////////////////////////////////////////////////////////////////////////// -#ifdef ROOTPREFIX -static Bool_t IgnorePrefix() { - static Bool_t ignorePrefix = gSystem->Getenv("ROOTIGNOREPREFIX"); - return ignorePrefix; +namespace { + +std::string GetRelativeToSharedLibDir(const char *buildTreePath, const char *installTreePath) +{ + namespace fs = std::filesystem; + + // The shared library directory can be found automatically, because the + // libCore is loaded by definition when using TROOT. It's used as the anchor + // to resolve other resource directories, using the correct relative path + // for either the build or install tree. + fs::path libPath = TROOT::GetSharedLibDir().Data(); + + // Check if we are in the build tree using the build tree marker file + static const bool isBuildTree = fs::exists(libPath / "root-build-tree-marker"); + + fs::path outputPath = libPath / (isBuildTree ? buildTreePath : installTreePath); + + // Normalize to get rid of the "../" in relative paths + return outputPath.lexically_normal().string(); +} + +} // namespace + +ROOT::Internal::ResourceDirs const &ROOT::Internal::GetResourceDirs() +{ + static ResourceDirs dirs; + + if (dirs.initialized) + return dirs; + + // Initialize resource directories with the correct relative paths for the + // build tree or the install tree. + dirs.bin = GetRelativeToSharedLibDir("../bin", INSTALL_LIB_TO_BIN); + dirs.data = GetRelativeToSharedLibDir("..", INSTALL_LIB_TO_DATA); + dirs.docs = GetRelativeToSharedLibDir("..", INSTALL_LIB_TO_DOCS); + dirs.etc = GetRelativeToSharedLibDir("../etc", INSTALL_LIB_TO_ETC); + dirs.fonts = GetRelativeToSharedLibDir("../fonts", INSTALL_LIB_TO_FONTS); + dirs.icons = GetRelativeToSharedLibDir("../icons", INSTALL_LIB_TO_ICONS); + dirs.include = GetRelativeToSharedLibDir("../include", INSTALL_LIB_TO_INCLUDE); + dirs.macros = GetRelativeToSharedLibDir("../macros", INSTALL_LIB_TO_MACROS); + dirs.rootsys = GetRelativeToSharedLibDir("..", INSTALL_LIB_TO_ROOTSYS); + dirs.src = GetRelativeToSharedLibDir("../src", INSTALL_LIB_TO_SRC); + dirs.tutorials = GetRelativeToSharedLibDir("../tutorials", INSTALL_LIB_TO_TUTORIALS); + + dirs.initialized = true; + + return dirs; } -#endif //////////////////////////////////////////////////////////////////////////////// /// Get the rootsys directory in the installation. Static utility function. const TString& TROOT::GetRootSys() { - // Avoid returning a reference to a temporary because of the conversion - // between std::string and TString. - const static TString rootsys = ROOT::FoundationUtils::GetRootSys(); - return rootsys; + return ROOT::Internal::GetResourceDirs().rootsys; } //////////////////////////////////////////////////////////////////////////////// /// Get the binary directory in the installation. Static utility function. -const TString& TROOT::GetBinDir() { -#ifdef ROOTBINDIR - if (IgnorePrefix()) { -#endif - static TString rootbindir; - if (rootbindir.IsNull()) { - rootbindir = "bin"; - gSystem->PrependPathName(GetRootSys(), rootbindir); - } - return rootbindir; -#ifdef ROOTBINDIR - } else { - const static TString rootbindir = ROOTBINDIR; - return rootbindir; - } -#endif +const TString &TROOT::GetBinDir() +{ + return ROOT::Internal::GetResourceDirs().bin; } //////////////////////////////////////////////////////////////////////////////// @@ -3191,6 +3255,9 @@ const TString &TROOT::GetSharedLibDir() #endif + // Normalize to get rid of the "../" in relative paths + rootlibdir = fs::path{rootlibdir.Data()}.lexically_normal().string().c_str(); + return rootlibdir; } @@ -3199,117 +3266,46 @@ const TString &TROOT::GetSharedLibDir() const TString &TROOT::GetIncludeDir() { - static TString rootincdir; - - if (!rootincdir.IsNull()) - return rootincdir; - - namespace fs = std::filesystem; - - // The shared library directory can be found automatically, because the - // libCore is loaded by definition when using TROOT. It's used as the anchor - // to resolve the ROOT include directory, using the correct relative path - // for either the build or install tree. - fs::path libPath = GetSharedLibDir().Data(); - - // Check if we are in the build tree using the build tree marker file - const bool isBuildTree = fs::exists(libPath / "root-build-tree-marker"); - - fs::path includePath = isBuildTree ? "../include" : INSTALL_LIB_TO_INCLUDE; - - // The INSTALL_LIB_TO_INCLUDE might already be absolute - if (!includePath.is_absolute()) { - includePath = libPath / includePath; - } - - // Normalize to get rid of the "../" in relative paths - rootincdir = includePath.lexically_normal().string(); - - return rootincdir; + return ROOT::Internal::GetResourceDirs().include; } //////////////////////////////////////////////////////////////////////////////// /// Get the sysconfig directory in the installation. Static utility function. -const TString& TROOT::GetEtcDir() { - // Avoid returning a reference to a temporary because of the conversion - // between std::string and TString. - const static TString etcdir = ROOT::FoundationUtils::GetEtcDir(); - return etcdir; +const TString &TROOT::GetEtcDir() +{ + return ROOT::Internal::GetResourceDirs().etc; } //////////////////////////////////////////////////////////////////////////////// /// Get the data directory in the installation. Static utility function. const TString& TROOT::GetDataDir() { -#ifdef ROOTDATADIR - if (IgnorePrefix()) { -#endif - return GetRootSys(); -#ifdef ROOTDATADIR - } else { - const static TString rootdatadir = ROOTDATADIR; - return rootdatadir; - } -#endif + return ROOT::Internal::GetResourceDirs().data; } //////////////////////////////////////////////////////////////////////////////// /// Get the documentation directory in the installation. Static utility function. -const TString& TROOT::GetDocDir() { -#ifdef ROOTDOCDIR - if (IgnorePrefix()) { -#endif - return GetRootSys(); -#ifdef ROOTDOCDIR - } else { - const static TString rootdocdir = ROOTDOCDIR; - return rootdocdir; - } -#endif +const TString &TROOT::GetDocDir() +{ + return ROOT::Internal::GetResourceDirs().docs; } //////////////////////////////////////////////////////////////////////////////// /// Get the macro directory in the installation. Static utility function. -const TString& TROOT::GetMacroDir() { -#ifdef ROOTMACRODIR - if (IgnorePrefix()) { -#endif - static TString rootmacrodir; - if (rootmacrodir.IsNull()) { - rootmacrodir = "macros"; - gSystem->PrependPathName(GetRootSys(), rootmacrodir); - } - return rootmacrodir; -#ifdef ROOTMACRODIR - } else { - const static TString rootmacrodir = ROOTMACRODIR; - return rootmacrodir; - } -#endif +const TString &TROOT::GetMacroDir() +{ + return ROOT::Internal::GetResourceDirs().macros; } //////////////////////////////////////////////////////////////////////////////// /// Get the tutorials directory in the installation. Static utility function. -const TString& TROOT::GetTutorialDir() { -#ifdef ROOTTUTDIR - if (IgnorePrefix()) { -#endif - static TString roottutdir; - if (roottutdir.IsNull()) { - roottutdir = "tutorials"; - gSystem->PrependPathName(GetRootSys(), roottutdir); - } - return roottutdir; -#ifdef ROOTTUTDIR - } else { - const static TString roottutdir = ROOTTUTDIR; - return roottutdir; - } -#endif +const TString &TROOT::GetTutorialDir() +{ + return ROOT::Internal::GetResourceDirs().tutorials; } //////////////////////////////////////////////////////////////////////////////// @@ -3326,64 +3322,25 @@ void TROOT::ShutDown() //////////////////////////////////////////////////////////////////////////////// /// Get the source directory in the installation. Static utility function. -const TString& TROOT::GetSourceDir() { -#ifdef ROOTSRCDIR - if (IgnorePrefix()) { -#endif - static TString rootsrcdir; - if (rootsrcdir.IsNull()) { - rootsrcdir = "src"; - gSystem->PrependPathName(GetRootSys(), rootsrcdir); - } - return rootsrcdir; -#ifdef ROOTSRCDIR - } else { - const static TString rootsrcdir = ROOTSRCDIR; - return rootsrcdir; - } -#endif +const TString &TROOT::GetSourceDir() +{ + return ROOT::Internal::GetResourceDirs().src; } //////////////////////////////////////////////////////////////////////////////// /// Get the icon path in the installation. Static utility function. -const TString& TROOT::GetIconPath() { -#ifdef ROOTICONPATH - if (IgnorePrefix()) { -#endif - static TString rooticonpath; - if (rooticonpath.IsNull()) { - rooticonpath = "icons"; - gSystem->PrependPathName(GetRootSys(), rooticonpath); - } - return rooticonpath; -#ifdef ROOTICONPATH - } else { - const static TString rooticonpath = ROOTICONPATH; - return rooticonpath; - } -#endif +const TString &TROOT::GetIconPath() +{ + return ROOT::Internal::GetResourceDirs().icons; } //////////////////////////////////////////////////////////////////////////////// /// Get the fonts directory in the installation. Static utility function. -const TString& TROOT::GetTTFFontDir() { -#ifdef TTFFONTDIR - if (IgnorePrefix()) { -#endif - static TString ttffontdir; - if (ttffontdir.IsNull()) { - ttffontdir = "fonts"; - gSystem->PrependPathName(GetRootSys(), ttffontdir); - } - return ttffontdir; -#ifdef TTFFONTDIR - } else { - const static TString ttffontdir = TTFFONTDIR; - return ttffontdir; - } -#endif +const TString &TROOT::GetTTFFontDir() +{ + return ROOT::Internal::GetResourceDirs().fonts; } //////////////////////////////////////////////////////////////////////////////// diff --git a/core/base/src/TSystem.cxx b/core/base/src/TSystem.cxx index 2585dd507270d..196432e16aa69 100644 --- a/core/base/src/TSystem.cxx +++ b/core/base/src/TSystem.cxx @@ -3730,6 +3730,7 @@ int TSystem::CompileMacro(const char *filename, Option_t *opt, #ifdef _MSC_VER linkLibraries.Prepend(linkLibrariesNoQuotes); + std::cout << "linkLibraries : " << linkLibraries << std::endl; #else linkLibraries.Prepend(librariesWithQuotes); #endif @@ -3763,6 +3764,10 @@ int TSystem::CompileMacro(const char *filename, Option_t *opt, // libraries via ACLiC in the same session and have them depend on each other without // the need to set further environment variables. cmd.ReplaceAll("$RPath", "-Wl,-rpath," + gROOT->GetSharedLibDir() + " -Wl,-rpath," + build_loc); + // $BinDir and $LibDir are not mentioned in the docs, but used internally to + // build the absolute paths to ROOTs directories + cmd.ReplaceAll("$BinDir", gROOT->GetBinDir()); + cmd.ReplaceAll("$LibDir", gROOT->GetLibDir()); TString optdebFlags; if (mode & kDebug) optdebFlags = fFlagsDebug + " "; diff --git a/core/base/test/IncludePathTest.cxx b/core/base/test/IncludePathTest.cxx index b5f0fbadb0fd2..0cf8d952e0458 100644 --- a/core/base/test/IncludePathTest.cxx +++ b/core/base/test/IncludePathTest.cxx @@ -8,7 +8,6 @@ TEST(TSystem, IncludePath) ASSERT_TRUE(gSystem); gSystem->AddIncludePath("-I /some/path/with-xin-it -I ./some/relative-path"); - gSystem->AddIncludePath("-I %ROOTSYS%\\include -I ${ROOTSYS}/include"); #ifdef WIN32 gSystem->AddIncludePath( "-I \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\include\""); diff --git a/core/foundation/res/ROOT/FoundationUtils.hxx b/core/foundation/res/ROOT/FoundationUtils.hxx index c4ba65cfe093c..1e69f3b43a3da 100644 --- a/core/foundation/res/ROOT/FoundationUtils.hxx +++ b/core/foundation/res/ROOT/FoundationUtils.hxx @@ -60,16 +60,6 @@ namespace FoundationUtils { return gEnvPathSeparator; } - ///\returns the fallback directory in the installation (eg. /usr/local/root/). - const std::string& GetFallbackRootSys(); - - ///\returns the rootsys directory in the installation. - /// - const std::string& GetRootSys(); - - ///\returns the sysconfig directory in the installation. - const std::string& GetEtcDir(); - ///\returns true if lowercase \c value is 1, on, true, 0, off, false bool CanConvertEnvValueToBool(const std::string& value); diff --git a/core/foundation/src/FoundationUtils.cxx b/core/foundation/src/FoundationUtils.cxx index b1b73b2d47fe6..a099f0c0eab14 100644 --- a/core/foundation/src/FoundationUtils.cxx +++ b/core/foundation/src/FoundationUtils.cxx @@ -109,89 +109,6 @@ void ConvertToUnixPath(std::string& Path) { std::replace(Path.begin(), Path.end(), '\\', '/'); } -const std::string& GetFallbackRootSys() { - static std::string fallback; - if (!fallback.empty()) - return fallback; - -#if defined(WIN32) || defined(__FreeBSD__) - auto parent_path = [](std::string path) { - return path.substr(0, path.find_last_of("/\\")); - }; -#endif - -#ifdef WIN32 - static char lpFilename[_MAX_PATH]; - if (::GetModuleFileNameA( - NULL, // handle to module to find filename for - lpFilename, // pointer to buffer to receive module path - sizeof(lpFilename))) { // size of buffer, in characters - fallback = parent_path(parent_path(lpFilename)); - } -#elif defined __FreeBSD__ - procstat* ps = procstat_open_sysctl(); // - kinfo_proc* kp = kinfo_getproc(getpid()); - - char lpFilename[PATH_MAX] = ""; - if (kp!=NULL) { - procstat_getpathname(ps, kp, lpFilename, sizeof(lpFilename)); - fallback = parent_path(parent_path({lpFilename})); - } - - free(kp); - procstat_close(ps); -#else - // FIXME: We should not hardcode this path. We can use a similar to the - // windows technique to get the path to the executable. The easiest way - // to do this is to depend on LLVMSupport and use getMainExecutable. - fallback = "/usr/local/root"; -#endif - return fallback; -} - -#ifdef ROOTPREFIX -static bool IgnorePrefix() { - static bool ignorePrefix = std::getenv("ROOTIGNOREPREFIX"); - return ignorePrefix; -} -#endif - -const std::string& GetRootSys() { -#ifdef ROOTPREFIX - if (!IgnorePrefix()) { - const static std::string rootsys = ROOTPREFIX; - return rootsys; - } -#endif - static std::string rootsys; - if (rootsys.empty()) { - if (const char* envValue = std::getenv("ROOTSYS")) { - rootsys = envValue; -#ifndef WIN32 - // We cannot use gSystem->UnixPathName. - ConvertToUnixPath(rootsys); -#endif - } - } - // FIXME: Should this also call UnixPathName for consistency? - if (rootsys.empty()) - rootsys = GetFallbackRootSys(); - return rootsys; -} - -const std::string& GetEtcDir() { -#ifdef ROOTETCDIR - if (!IgnorePrefix()) { - const static std::string rootetcdir = ROOTETCDIR; - return rootetcdir; - } -#endif - - const static std::string rootetcdir = - GetRootSys() + GetPathSeparator() + "etc" + GetPathSeparator(); - return rootetcdir; -} - static std::string str_tolower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); }); diff --git a/core/unix/src/TUnixSystem.cxx b/core/unix/src/TUnixSystem.cxx index 6ae409145d3d3..5c4ccececc32e 100644 --- a/core/unix/src/TUnixSystem.cxx +++ b/core/unix/src/TUnixSystem.cxx @@ -464,32 +464,6 @@ static const char *GetExePath() return exepath; } -#if defined(HAVE_DLADDR) && !defined(R__MACOSX) -//////////////////////////////////////////////////////////////////////////////// - -static void SetRootSys() -{ -#ifdef ROOTPREFIX - if (gSystem->Getenv("ROOTIGNOREPREFIX")) { -#endif - void *addr = (void *)SetRootSys; - Dl_info info; - if (dladdr(addr, &info) && info.dli_fname && info.dli_fname[0]) { - char respath[kMAXPATHLEN]; - if (!realpath(info.dli_fname, respath)) { - if (!gSystem->Getenv("ROOTSYS")) - ::SysError("TUnixSystem::SetRootSys", "error getting realpath of libCore, please set ROOTSYS in the shell"); - } else { - TString rs = gSystem->GetDirName(respath); - gSystem->Setenv("ROOTSYS", gSystem->GetDirName(rs.Data()).Data()); - } - } -#ifdef ROOTPREFIX - } -#endif -} -#endif - #if defined(R__MACOSX) static TString gLinkedDylibs; @@ -513,24 +487,6 @@ static void DylibAdded(const struct mach_header *mh, intptr_t /* vmaddr_slide */ TRegexp sovers = "libCore\\.[0-9]+\\.*[0-9]*\\.*[0-9]*\\.so"; TRegexp dyvers = "libCore\\.[0-9]+\\.*[0-9]*\\.*[0-9]*\\.dylib"; -#ifdef ROOTPREFIX - if (gSystem->Getenv("ROOTIGNOREPREFIX")) { -#endif - if (lib.EndsWith("libCore.dylib") || lib.EndsWith("libCore.so") || - lib.Index(sovers) != kNPOS || lib.Index(dyvers) != kNPOS) { - char respath[kMAXPATHLEN]; - if (!realpath(lib, respath)) { - if (!gSystem->Getenv("ROOTSYS")) - ::SysError("TUnixSystem::DylibAdded", "error getting realpath of libCore, please set ROOTSYS in the shell"); - } else { - TString rs = gSystem->GetDirName(respath); - gSystem->Setenv("ROOTSYS", gSystem->GetDirName(rs.Data()).Data()); - } - } -#ifdef ROOTPREFIX - } -#endif - // when libSystem.B.dylib is loaded we have finished loading all dylibs // explicitly linked against the executable. Additional dylibs // come when they are explicitly linked against loaded so's, currently @@ -616,16 +572,10 @@ Bool_t TUnixSystem::Init() UnixSignal(kSigUser2, SigHandler); #if defined(R__MACOSX) - // trap loading of all dylibs to register dylib name, - // sets also ROOTSYS if built without ROOTPREFIX + // trap loading of all dylibs to register dylib name _dyld_register_func_for_add_image(DylibAdded); -#elif defined(HAVE_DLADDR) - SetRootSys(); #endif - // This is a fallback in case TROOT::GetRootSys() can't determine ROOTSYS - gRootDir = ROOT::FoundationUtils::GetFallbackRootSys().c_str(); - return kFALSE; } diff --git a/core/winnt/src/TWinNTSystem.cxx b/core/winnt/src/TWinNTSystem.cxx index 42d8329ba1970..0e14cc5602ae4 100644 --- a/core/winnt/src/TWinNTSystem.cxx +++ b/core/winnt/src/TWinNTSystem.cxx @@ -827,9 +827,7 @@ namespace { // determine the fileopen.C file path: TString fileopen = "fileopen.C"; - TString rootmacrodir = "macros"; - sys->PrependPathName(std::getenv("ROOTSYS"), rootmacrodir); - sys->PrependPathName(rootmacrodir.Data(), fileopen); + sys->PrependPathName(gROOT->GetMacroDir().Data(), fileopen); if (regROOTwrite) { // only write to registry if fileopen.C is readable @@ -1004,40 +1002,6 @@ TWinNTSystem::TWinNTSystem() : TSystem("WinNT", "WinNT System") char *buf = new char[MAX_MODULE_NAME32 + 1]; -#ifdef ROOTPREFIX - if (gSystem->Getenv("ROOTIGNOREPREFIX")) { -#endif - // set ROOTSYS - HMODULE hModCore = ::GetModuleHandle("libCore.dll"); - if (hModCore) { - ::GetModuleFileName(hModCore, buf, MAX_MODULE_NAME32 + 1); - char *pLibName = strstr(buf, "libCore.dll"); - if (pLibName) { - --pLibName; // skip trailing \\ or / - while (--pLibName >= buf && *pLibName != '\\' && *pLibName != '/'); - *pLibName = 0; // replace trailing \\ or / with 0 - TString check_path = buf; - check_path += "\\etc"; - // look for $ROOTSYS (it should contain the "etc" subdirectory) - while (buf[0] && GetFileAttributes(check_path.Data()) == INVALID_FILE_ATTRIBUTES) { - while (--pLibName >= buf && *pLibName != '\\' && *pLibName != '/'); - *pLibName = 0; - check_path = buf; - check_path += "\\etc"; - } - if (buf[0]) { - Setenv("ROOTSYS", buf); - TString path = buf; - path += "\\bin;"; - path += Getenv("PATH"); - Setenv("PATH", path.Data()); - } - } - } -#ifdef ROOTPREFIX - } -#endif - UpdateRegistry(this, buf); delete [] buf; @@ -1104,9 +1068,6 @@ Bool_t TWinNTSystem::Init() fSigcnt = 0; - // This is a fallback in case TROOT::GetRootSys() can't determine ROOTSYS - gRootDir = ROOT::FoundationUtils::GetFallbackRootSys().c_str(); - // Increase the accuracy of Sleep() without needing to link to winmm.lib typedef UINT (WINAPI* LPTIMEBEGINPERIOD)( UINT uPeriod ); HINSTANCE hInstWinMM = LoadLibrary( "winmm.dll" ); diff --git a/main/src/rmain.cxx b/main/src/rmain.cxx index a4236e028216f..9aa2a07f44536 100644 --- a/main/src/rmain.cxx +++ b/main/src/rmain.cxx @@ -17,6 +17,7 @@ // // ////////////////////////////////////////////////////////////////////////// +#include "TROOT.h" // for ROOT::Internal::GetResourceDirs() #include "TRint.h" #include "RConfigure.h" #include "snprintf.h" @@ -40,14 +41,7 @@ void handle_notebook_option(int argc, char **argv) } if (notebook > 0) { // Build command -#ifdef ROOTBINDIR - if (std::getenv("ROOTIGNOREPREFIX")) -#endif - snprintf(arg0, sizeof(arg0), "%s/bin/%s", std::getenv("ROOTSYS"), ROOTNBBINARY); -#ifdef ROOTBINDIR - else - snprintf(arg0, sizeof(arg0), "%s/%s", ROOTBINDIR, ROOTNBBINARY); -#endif + snprintf(arg0, sizeof(arg0), "%s/%s", ROOT::Internal::GetResourceDirs().bin.Data(), ROOTNBBINARY); int numnbargs = 1 + (argc - notebook); diff --git a/roottest/CMakeLists.txt b/roottest/CMakeLists.txt index 7b290c389767d..f8c00ff70d294 100644 --- a/roottest/CMakeLists.txt +++ b/roottest/CMakeLists.txt @@ -86,11 +86,6 @@ else() message(FATAL_ERROR "-- Check for bitness: no support for ${CMAKE_SIZEOF_VOID_P}*8 bit processors.") endif() -# Setup environment. -if (gnuinstall) - set(ROOTTEST_ENVIRONMENT ROOTIGNOREPREFIX=1) -endif() - # Set some variables that customizes the behaviour of the ROOT macros set(CMAKE_ROOTTEST_DICT ON) diff --git a/roottest/root/io/namespacedict/CMakeLists.txt b/roottest/root/io/namespacedict/CMakeLists.txt index 5814242d81b44..39a43229ab736 100644 --- a/roottest/root/io/namespacedict/CMakeLists.txt +++ b/roottest/root/io/namespacedict/CMakeLists.txt @@ -1,8 +1,8 @@ if(MSVC) - set(command ${CMAKE_COMMAND} -E env "ROOTIGNOREPREFIX=1" ${CMAKE_BINARY_DIR}/bin/rootcling.exe) + set(command ${CMAKE_BINARY_DIR}/bin/rootcling.exe) else() set(command ${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}" - "ROOTIGNOREPREFIX=1" ${CMAKE_BINARY_DIR}/bin/rootcling) + ${CMAKE_BINARY_DIR}/bin/rootcling) endif() ROOTTEST_ADD_TEST(HeaderDict diff --git a/rootx/CMakeLists.txt b/rootx/CMakeLists.txt index 959281902454e..57abdb794cfb3 100644 --- a/rootx/CMakeLists.txt +++ b/rootx/CMakeLists.txt @@ -15,6 +15,10 @@ if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) target_link_libraries(root PRIVATE util procstat) endif() +if(ROOT_NEED_STDCXXFS) + target_link_libraries(root PRIVATE stdc++fs) +endif() + generateHeader(root ${CMAKE_SOURCE_DIR}/core/base/src/root-argparse.py ${CMAKE_BINARY_DIR}/ginclude/rootCommandLineOptionsHelp.h diff --git a/rootx/src/rootx.cxx b/rootx/src/rootx.cxx index a2eba1603752e..4089dd6131626 100644 --- a/rootx/src/rootx.cxx +++ b/rootx/src/rootx.cxx @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -95,26 +96,6 @@ static const char *GetExePath() return exepath.c_str(); } -static void SetRootSys() -{ - const char *exepath = GetExePath(); - if (exepath && *exepath) { - std::string epStr{exepath}; - char *ep = epStr.data(); - char *s; - if ((s = strrchr(ep, '/'))) { - *s = 0; - if ((s = strrchr(ep, '/'))) { - *s = 0; - int l2 = strlen(ep) + 10; - char *env = new char[l2]; - snprintf(env, l2, "ROOTSYS=%s", ep); - putenv(env); // NOLINT: allocated memory now used by environment variable - } - } - } -} - extern "C" { static void SigTerm(int); } @@ -163,21 +144,6 @@ int main(int argc, char **argv) char **argvv; char arg0[kMAXPATHLEN]; -#ifdef ROOTPREFIX - if (std::getenv("ROOTIGNOREPREFIX")) { -#endif - // Try to set ROOTSYS depending on pathname of the executable - SetRootSys(); - - if (!std::getenv("ROOTSYS")) { - fprintf(stderr, "%s: ROOTSYS not set. Set it before trying to run %s.\n", - argv[0], argv[0]); - return 1; - } -#ifdef ROOTPREFIX - } -#endif - // In batch mode don't show splash screen, idem for no logo mode, // in about mode show always splash screen int i; @@ -242,14 +208,10 @@ int main(int argc, char **argv) // Build argv vector argvv = new char* [argc+1]; -#ifdef ROOTBINDIR - if (std::getenv("ROOTIGNOREPREFIX")) -#endif - snprintf(arg0, sizeof(arg0), "%s/bin/%s", std::getenv("ROOTSYS"), ROOTBINARY); -#ifdef ROOTBINDIR - else - snprintf(arg0, sizeof(arg0), "%s/%s", ROOTBINDIR, ROOTBINARY); -#endif + // The root binary is in the same path by construction + namespace fs = std::filesystem; + fs::path p{GetExePath()}; + snprintf(arg0, sizeof(arg0), "%s/%s", p.parent_path().string().c_str(), ROOTBINARY); argvv[0] = arg0; for (i = 1; i < argc; i++) diff --git a/tmva/sofie/test/CMakeLists.txt b/tmva/sofie/test/CMakeLists.txt index 120b5800b2f8d..789c20c98ccaa 100644 --- a/tmva/sofie/test/CMakeLists.txt +++ b/tmva/sofie/test/CMakeLists.txt @@ -40,7 +40,7 @@ ROOTTEST_GENERATE_EXECUTABLE(emitFromONNX EmitFromONNX_all.cxx target_compile_options(emitFromONNX PRIVATE -Wno-unused-parameter -Wno-array-bounds) ROOTTEST_ADD_TEST(SofieCompileModels_ONNX - COMMAND ${CMAKE_COMMAND} -E env ROOTIGNOREPREFIX=1 ./emitFromONNX ${onnx_file} ${CMAKE_CURRENT_BINARY_DIR}/${fname} + COMMAND ./emitFromONNX ${onnx_file} ${CMAKE_CURRENT_BINARY_DIR}/${fname} FIXTURES_REQUIRED sofie-compile-models-onnx-build FIXTURES_SETUP sofie-compile-models-onnx ) @@ -75,7 +75,7 @@ target_compile_options(emitFromROOT PRIVATE -Wno-unused-parameter -Wno-array-bou # Automatic compilation of headers from root files ROOTTEST_ADD_TEST(SofieCompileModels_ROOT - COMMAND ${CMAKE_COMMAND} -E env ROOTIGNOREPREFIX=1 ./emitFromROOT + COMMAND ./emitFromROOT FIXTURES_REQUIRED sofie-compile-models-onnx-root FIXTURES_SETUP sofie-compile-models-root ) diff --git a/tree/ntuple/test/CMakeLists.txt b/tree/ntuple/test/CMakeLists.txt index 0301a5480b3bf..16414dc9346eb 100644 --- a/tree/ntuple/test/CMakeLists.txt +++ b/tree/ntuple/test/CMakeLists.txt @@ -115,10 +115,10 @@ ROOT_GENERATE_DICTIONARY(StreamerFieldDict ${CMAKE_CURRENT_SOURCE_DIR}/StreamerF DEPENDENCIES RIO) if(MSVC) - set(command ${CMAKE_COMMAND} -E env "ROOTIGNOREPREFIX=1" $) + set(command $) else() set(command ${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:$ENV{LD_LIBRARY_PATH}" - "ROOTIGNOREPREFIX=1" $) + $) endif() configure_file(StreamerFieldXML.h . COPYONLY)