Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
252 changes: 87 additions & 165 deletions cmake/modules/RootConfiguration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -159,23 +159,13 @@ set(builddavix ${value${davix}})
set(davixlibdir ${DAVIX_LIBRARY_DIR})
set(davixlib ${DAVIX_LIBRARY})
set(davixincdir ${DAVIX_INCLUDE_DIR})
if(davix)
set(hasdavix define)
else()
set(hasdavix undef)
endif()

set(buildnetxng ${value${xrootd}})

set(buildcurl ${value${curl}})
set(curllibdir ${CURL_LIBRARY_DIR})
set(curllib ${CURL_LIBRARY})
set(curlincdir ${CURL_INCLUDE_DIR})
if(curl)
set(hascurl define)
else()
set(hascurl undef)
endif()

set(builddcap ${value${dcap}})
set(dcaplibdir ${DCAP_LIBRARY_DIR})
Expand Down Expand Up @@ -322,169 +312,16 @@ endif()
# set(setresuid undef)
CHECK_CXX_SOURCE_COMPILES("#include <unistd.h>
int main() { uid_t r = 0, e = 0, s = 0; if (setresuid(r, e, s) != 0) { }; return 0;}" found_setresuid)
if(found_setresuid)
set(setresuid define)
else()
set(setresuid undef)
endif()

if(mathmore)
set(hasmathmore define)
else()
set(hasmathmore undef)
endif()
if(imt)
set(useimt define)
else()
set(useimt undef)
endif()
if(CMAKE_USE_PTHREADS_INIT)
set(haspthread define)
else()
set(haspthread undef)
endif()
if(x11)
set(hasxft define)
else()
set(hasxft undef)
endif()
if(lzma)
set(haslzmacompression define)
else()
set(haslzmacompression undef)
endif()
if(lz4)
set(haslz4compression define)
else()
set(haslz4compression undef)
endif()
if(clad)
set(hasclad define)
else()
set(hasclad undef)
endif()
if(cocoa)
set(hascocoa define)
else()
set(hascocoa undef)
endif()
if(vdt)
set(hasvdt define)
else()
set(hasvdt undef)
endif()
if(ROOT_HAVE_EXPERIMENTAL_SIMD)
set(hasstdexperimentalsimd define)
else()
set(hasstdexperimentalsimd undef)
endif()
if(ROOT_EXPERIMENTAL_SIMD_PIN_AVX_ABI)
set(experimentalsimdpinavxabi define)
else()
set(experimentalsimdpinavxabi undef)
endif()
if(dataframe)
set(hasdataframe define)
else()
set(hasdataframe undef)
endif()
if(dev)
set(use_less_includes define)
else()
set(use_less_includes undef)
endif()
if(root7)
set(hasroot7 define)
else()
set(hasroot7 undef)
endif()

if(ZLIB_NG)
set(usezlibng define)
else()
set(usezlibng undef)
endif()
if(runtime_cxxmodules)
set(usecxxmodules define)
else()
set(usecxxmodules undef)
endif()
if(libcxx)
set(uselibc++ define)
else()
set(uselibc++ undef)
endif()
if(gcctoolchain)
set(setgcctoolchain define)
else()
set(setgcctoolchain undef)
endif()
if(memory_termination)
set(memory_term define)
else()
set(memory_term undef)
endif()
if(cefweb)
set(hascefweb define)
else()
set(hascefweb undef)
endif()
if(qt6web)
set(hasqt6webengine define)
else()
set(hasqt6webengine undef)
endif()
if (tmva-cpu)
set(hastmvacpu define)
else()
set(hastmvacpu undef)
endif()
if (tmva-gpu)
set(hastmvagpu define)
else()
set(hastmvagpu undef)
endif()
if (tmva-cudnn)
set(hastmvacudnn define)
else()
set(hastmvacudnn undef)
endif()
if (tmva-pymva)
set(haspymva define)
else()
set(haspymva undef)
endif()
if (uring)
set(hasuring define)
else()
set(hasuring undef)
endif()
if (geom)
set(hasgeom define)
else()
set(hasgeom undef)
endif()


CHECK_CXX_SOURCE_COMPILES("
inline __attribute__((always_inline)) bool TestBit(unsigned long f) { return f != 0; };
int main() { return TestBit(0); }" found_attribute_always_inline)
if(found_attribute_always_inline)
set(has_found_attribute_always_inline define)
else()
set(has_found_attribute_always_inline undef)
endif()

CHECK_CXX_SOURCE_COMPILES("
inline __attribute__((noinline)) bool TestBit(unsigned long f) { return f != 0; };
int main() { return TestBit(0); }" has_found_attribute_noinline)
if(has_found_attribute_noinline)
set(has_found_attribute_noinline define)
else()
set(has_found_attribute_noinline undef)
endif()

# The hardware interference size must be stable across all TUs in a ROOT build, so we need to save it in RConfigure.hxx
# The hardware interference size must be stable across all TUs in a ROOT build, so we need to save it in RConfigure.h
# Since it can vary for different compilers or tune settings, we cannot base the ABI on a value that might change,
# even be different between compiler and interpreter, or when ROOT is compiled on a different machine.
# For older CMake and when cross compiling, we simply fall back to 64
Expand Down Expand Up @@ -562,9 +399,94 @@ 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)
add_library(RConfigureDefs INTERFACE) # temporary target, do not link against it, just for bw-compatible header generation RConfigure.h
if (gnuinstall)
target_compile_definitions(RConfigureDefs INTERFACE
ROOTPREFIX="${prefix}"
ROOTBINDIR="${bindir}"
ROOTLIBDIR="${libdir}"
ROOTETCDIR="${etcdir}"
ROOTDATADIR="${datadir}"
ROOTDOCDIR="${docdir}"
ROOTMACRODIR="${macrodir}"
ROOTTUTDIR="${tutdir}"
ROOTSRCDIR="${srcdir}"
ROOTICONPATH="${iconpath}"
TTFFONTDIR="${ttffontdir}"
)
endif()

target_compile_definitions(RConfigureDefs INTERFACE
ROOT__ARCHITECTURE=${architecture}
EXTRAICONPATH=$<IF:$<BOOL:${extraiconpath}>,\"${extraiconpath}\",\"\">
ROOT__cplusplus=${__cplusplus}
$<$<BOOL:${found_setresuid}>:R__HAS_SETRESUID>
$<$<BOOL:${mathmore}>:R__HAS_MATHMORE>
$<$<BOOL:${CMAKE_USE_PTHREADS_INIT}>:R__HAS_PTHREAD>
$<$<BOOL:${x11}>:R__HAS_XFT>
$<$<BOOL:${clad}>:R__HAS_CLAD>
$<$<BOOL:${cocoa}>:R__HAS_COCOA>
$<$<BOOL:${vdt}>:R__HAS_VDT>
$<$<BOOL:${ROOT_HAVE_EXPERIMENTAL_SIMD}>:R__HAS_STD_EXPERIMENTAL_SIMD>
$<$<BOOL:${ROOT_EXPERIMENTAL_SIMD_PIN_AVX_ABI}>:R__EXPERIMENTAL_SIMD_PIN_AVX_ABI>
$<$<BOOL:${runtime_cxxmodules}>:R__USE_CXXMODULES>
$<$<BOOL:${libcxx}>:R__USE_LIBCXX>
$<$<BOOL:${found_attribute_always_inline}>:R__HAS_ATTRIBUTE_ALWAYS_INLINE>
$<$<BOOL:${has_found_attribute_noinline}>:R__HAS_ATTRIBUTE_NOINLINE>
$<$<BOOL:${imt}>:R__USE_IMT>
$<$<BOOL:${memory_termination}>:R__COMPLETE_MEM_TERMINATION>
$<$<BOOL:${cefweb}>:R__HAS_CEFWEB>
$<$<BOOL:${qt6web}>:R__HAS_QT6WEB>
$<$<BOOL:${davix}>:R__HAS_DAVIX>
$<$<BOOL:${curl}>:R__HAS_CURL>
$<$<BOOL:${dataframe}>:R__HAS_DATAFRAME>
$<$<BOOL:${root7}>:R__HAS_ROOT7>
$<$<BOOL:${dev}>:R__LESS_INCLUDES>
R__HARDWARE_INTERFERENCE_SIZE=${hardwareinterferencesize}
$<$<BOOL:${ZLIB_NG}>:R__HAS_ZLIB_NG>
$<$<BOOL:${tmva-cpu}>:R__HAS_TMVACPU>
$<$<BOOL:${tmva-gpu}>:R__HAS_TMVAGPU>
$<$<BOOL:${tmva-cudnn}>:R__HAS_CUDNN>
$<$<BOOL:${tmva-pymva}>:R__HAS_PYMVA>
$<$<BOOL:${uring}>:R__HAS_URING>
$<$<BOOL:${geom}>:R__HAS_GEOM>
)

file(GENERATE

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not quite seeing (yet?) the simplification. (The boiler plate could technically be completely removed from the original with a macro and a list of things to test/set).

There is a significant difference between configure_file and file(GENERATE which may or may not have drastic practical consequence. The timing of the file generation is different (Configure Phase vs Generation Phase) and I am concerned that the file will be touched/regenerated at each re-invocation of cmake (leading to a full rebuild each time !?).

I am also confused by configure_file is not the 'right' tool to generate a file containing configuration information. Is there a updated recommendation from KitWare?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am concerned that the file will be touched/regenerated at each re-invocation of cmake (leading to a full rebuild each time !?).

Nope, see https://cmake.org/cmake/help/latest/command/file.html.
Generated files are modified and their timestamp updated on subsequent cmake runs only if their content is changed.

I am also confused by configure_file is not the 'right' tool to generate a file containing configuration information. Is there a updated recommendation from KitWare?

Relying on global headers just for expressing "defines" is in general a bad idea: it's hard to express the dependency. The 'modern CMake' way is target compile definitions. This allows you to express dependencies. With global headers, it's harder

See
https://cmake.org/cmake/help/latest/guide/tutorial/In-Depth%20CMake%20Target%20Commands.html

The target_compile_definitions() command describes compile definitions as target properties. It is the most common mechanism for communicating build configuration information to the source code itself. As with all properties, the scope keywords apply as we have discussed.

I am not quite seeing (yet?) the simplification.

The main advantage is that now you depend on a target rather than on a global header. This allows you to better track dependencies, as well as to do better intertwining of ROOT from other libraries if you just need some compile time definitions, so you do not need to link against Core, or otherwise do global target_include_directory but then that misses dependency tracking (if global header is changed, CMake does not know that it should rebuild)
See eg #23270

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which may or may not have drastic practical consequence

a potential advantage of targets vs headers is that, rather than having to preprocess/parse a 400 lines long header file (RConfigure.h) for every compilation in ROOT, with a lot of ifdefs else branches, the compiler already gets the resolved defines via the -D flag, so the ifdef conditions are only checked once at configure time and never again. The difference will though probably be neglibible in building time.

OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/ginclude/RConfigure.h
CONTENT
"#ifndef ROOT_RConfigure
#define ROOT_RConfigure

#define $<JOIN:$<LIST:TRANSFORM,$<TARGET_PROPERTY:RConfigureDefs,INTERFACE_COMPILE_DEFINITIONS>,REPLACE,=, >,\n#define >
#endif

#ifndef ROOT_RConfigure_w
#define ROOT_RConfigure_w
#if defined(__cplusplus) && (__cplusplus != ROOT__cplusplus)
# define R__STR(x) #x
# define R__XSTR(x) R__STR(x)
# pragma message(__FILE__ \": Warning: The C++ standard in this build (\" R__XSTR(__cplusplus) \") does not match ROOT configuration (\" R__XSTR(ROOT__cplusplus) \"); this might cause unexpected issues.\")
# if defined(_MSC_VER)
# pragma message(__FILE__ \": Warning: And please make sure you are using the -Zc:__cplusplus compilation flag\")
# endif
# undef R__XSTR
# undef R__STR
#endif
#endif
"
NEWLINE_STYLE UNIX
)
install(FILES ${CMAKE_BINARY_DIR}/ginclude/RConfigure.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

# Public target interface against which to link
add_library(ROOTdefs INTERFACE)
target_compile_definitions(ROOTdefs INTERFACE
ROOT_RConfigure # so that including the mirror header RConfigure.h is imnocuous if linking against this target
)
target_link_libraries(ROOTdefs INTERFACE RConfigureDefs)


#---Configure and install various files----------------------------------------------------------------------
execute_Process(COMMAND hostname OUTPUT_VARIABLE BuildNodeInfo OUTPUT_STRIP_TRAILING_WHITESPACE )

Expand Down
68 changes: 0 additions & 68 deletions config/RConfigure.in

This file was deleted.

Loading