diff --git a/cmake/modules/RootConfiguration.cmake b/cmake/modules/RootConfiguration.cmake index 1fd7e8a496185..489281df231fd 100644 --- a/cmake/modules/RootConfiguration.cmake +++ b/cmake/modules/RootConfiguration.cmake @@ -548,6 +548,19 @@ endif() string(REGEX MATCH "__cplusplus[=| ]([0-9]+)" __cplusplus "${__cplusplus_PPout}") set(__cplusplus ${CMAKE_MATCH_1}L) +# To mark the build tree. Important for automatic resolution of relative paths, +# for example to the include directory. Use custom target to ensure re-creation +# when someone deletes the marker. +set(build_tree_marker "${localruntimedir}/root-build-tree-marker") +add_custom_command( + OUTPUT "${build_tree_marker}" + COMMAND ${CMAKE_COMMAND} -E touch "${build_tree_marker}" + COMMENT "Ensuring that \"${build_tree_marker}\" exists" +) +add_custom_target(ensure_build_tree_marker ALL + DEPENDS "${build_tree_marker}" +) + configure_file(${PROJECT_SOURCE_DIR}/config/RConfigure.in ginclude/RConfigure.h NEWLINE_STYLE UNIX) install(FILES ${CMAKE_BINARY_DIR}/ginclude/RConfigure.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) diff --git a/config/RConfigure.in b/config/RConfigure.in index d8fa08521d0c9..09931572afe88 100644 --- a/config/RConfigure.in +++ b/config/RConfigure.in @@ -9,7 +9,6 @@ #define ROOTPREFIX "@prefix@" #define ROOTBINDIR "@bindir@" #define ROOTLIBDIR "@libdir@" -#define ROOTINCDIR "@incdir@" #define ROOTETCDIR "@etcdir@" #define ROOTDATADIR "@datadir@" #define ROOTDOCDIR "@docdir@" diff --git a/core/base/CMakeLists.txt b/core/base/CMakeLists.txt index 97fffc3e9b6bb..26177a4d446cc 100644 --- a/core/base/CMakeLists.txt +++ b/core/base/CMakeLists.txt @@ -236,9 +236,21 @@ if(core_soversion) else() set(full_core_filename "${core_prefix}Core${core_suffix}") 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_includedir_is_absolute 1) +else() + set(install_includedir_is_absolute 0) +endif() +file(TO_NATIVE_PATH "${CMAKE_INSTALL_INCLUDEDIR}" install_includedir_native) + target_compile_options(Core PRIVATE -DLIB_CORE_NAME=${full_core_filename} - -DCMAKE_INSTALL_INCLUDEDIR=${CMAKE_INSTALL_INCLUDEDIR} + -DINSTALL_INCLUDEDIR=${install_includedir_native} + -DINSTALL_INCLUDEDIR_IS_ABSOLUTE=${install_includedir_is_absolute} ) +add_dependencies(Core ensure_build_tree_marker) if(PCRE2_FOUND) target_link_libraries(Core PRIVATE PCRE2::PCRE2) diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index af0068d8c1bff..f557c4d440977 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -1993,9 +1993,7 @@ void TROOT::InitSystem() if (gSystem->Init()) fprintf(stderr, "Fatal in : can't init operating system layer\n"); - TString rootincludedir = _R_QUOTEVAL_(CMAKE_INSTALL_INCLUDEDIR); - gSystem->PrependPathName(GetRootSys(), rootincludedir); - gSystem->SetIncludePath(("-I" + rootincludedir).Data()); + gSystem->SetIncludePath(("-I" + GetIncludeDir()).Data()); if (!gSystem->HomeDirectory()) { fprintf(stderr, "Fatal in : HOME directory not set\n"); @@ -3098,11 +3096,29 @@ const TString& TROOT::GetSharedLibDir() { //////////////////////////////////////////////////////////////////////////////// /// Get the include directory in the installation. Static utility function. -const TString& TROOT::GetIncludeDir() { - // Avoid returning a reference to a temporary because of the conversion - // between std::string and TString. - const static TString includedir = ROOT::FoundationUtils::GetIncludeDir(); - return includedir; +const TString &TROOT::GetIncludeDir() +{ + static TString rootincdir; + + if (!rootincdir.IsNull()) + return rootincdir; + + const std::string &sep = ROOT::FoundationUtils::GetPathSeparator(); + + // Check if we are in the build tree using the build tree marker file + const bool isBuildTree = std::filesystem::exists((GetSharedLibDir() + sep + "root-build-tree-marker").Data()); + + if (isBuildTree) { + rootincdir = GetRootSys() + sep + "include"; + } else { +#if INSTALL_INCLUDEDIR_IS_ABSOLUTE + rootincdir = _R_QUOTEVAL_(INSTALL_INCLUDEDIR); +#else + rootincdir = GetRootSys() + sep + _R_QUOTEVAL_(INSTALL_INCLUDEDIR); +#endif + } + + return rootincdir; } //////////////////////////////////////////////////////////////////////////////// diff --git a/core/foundation/res/ROOT/FoundationUtils.hxx b/core/foundation/res/ROOT/FoundationUtils.hxx index ce224f1067130..c4ba65cfe093c 100644 --- a/core/foundation/res/ROOT/FoundationUtils.hxx +++ b/core/foundation/res/ROOT/FoundationUtils.hxx @@ -67,10 +67,6 @@ namespace FoundationUtils { /// const std::string& GetRootSys(); - ///\ returns the include directory in the installation. - /// - const std::string& GetIncludeDir(); - ///\returns the sysconfig directory in the installation. const std::string& GetEtcDir(); diff --git a/core/foundation/src/FoundationUtils.cxx b/core/foundation/src/FoundationUtils.cxx index 702c00377c8c2..b1b73b2d47fe6 100644 --- a/core/foundation/src/FoundationUtils.cxx +++ b/core/foundation/src/FoundationUtils.cxx @@ -167,8 +167,10 @@ const std::string& GetRootSys() { 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? @@ -177,22 +179,6 @@ const std::string& GetRootSys() { return rootsys; } - -const std::string& GetIncludeDir() { -#ifdef ROOTINCDIR - if (!IgnorePrefix()) { - const static std::string rootincdir = ROOTINCDIR; - return rootincdir; - } -#endif - static std::string rootincdir; - if (rootincdir.empty()) { - const std::string& sep = GetPathSeparator(); - rootincdir = GetRootSys() + sep + "include" + sep; - } - return rootincdir; -} - const std::string& GetEtcDir() { #ifdef ROOTETCDIR if (!IgnorePrefix()) {