From 032ee975f01d8d2d74c9a96455e91e572ec79cda Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Mon, 29 Sep 2025 18:01:32 +0200 Subject: [PATCH 1/3] [rootx] Don't use full path in `root.exe` invocation If the `root` executable was in the path and could be started, the `root.exe` is in the path to because they are in the same directory. Therefore it's not necessary to start `root.exe` with the full path. --- rootx/src/rootx.cxx | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/rootx/src/rootx.cxx b/rootx/src/rootx.cxx index a2eba1603752e..2338600ec9f92 100644 --- a/rootx/src/rootx.cxx +++ b/rootx/src/rootx.cxx @@ -40,12 +40,6 @@ #include #endif // R__FBSD -#if defined(__CYGWIN__) && defined(__GNUC__) -#define ROOTBINARY "root_exe.exe" -#else -#define ROOTBINARY "root.exe" -#endif - static int gChildpid; static int GetErrno() { @@ -160,9 +154,6 @@ static void PrintUsage() int main(int argc, char **argv) { - char **argvv; - char arg0[kMAXPATHLEN]; - #ifdef ROOTPREFIX if (std::getenv("ROOTIGNOREPREFIX")) { #endif @@ -241,15 +232,9 @@ int main(int argc, char **argv) // Child is going to overlay itself with the actual ROOT module... // 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 + char arg0[] = "root.exe\0"; + + std::vector argvv(argc+1); argvv[0] = arg0; for (i = 1; i < argc; i++) @@ -257,13 +242,11 @@ int main(int argc, char **argv) argvv[i] = 0; // Execute actual ROOT module - execv(arg0, argvv); + execv("root.exe", argvv.data()); // Exec failed - fprintf(stderr, "%s: can't start ROOT -- check that %s exists!\n", - argv[0], arg0); - - delete [] argvv; + fprintf(stderr, "%s: can't start ROOT -- check that root.exe exists!\n", + argv[0]); return 1; } From 4b49caa570fbb37154bd65d29662fa71a59b41e3 Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Mon, 29 Sep 2025 18:11:15 +0200 Subject: [PATCH 2/3] [rootx] Don't set `ROOTSYS` in root executable There is no need for that, because the `root.exe` application also has a way to figure out `ROOTSYS` from the executable path if it's not set. --- rootx/src/rootx.cxx | 73 --------------------------------------------- 1 file changed, 73 deletions(-) diff --git a/rootx/src/rootx.cxx b/rootx/src/rootx.cxx index 2338600ec9f92..a0a092ac5aa12 100644 --- a/rootx/src/rootx.cxx +++ b/rootx/src/rootx.cxx @@ -51,64 +51,6 @@ static void ResetErrno() errno = 0; } -static const char *GetExePath() -{ - static std::string exepath; - if (exepath == "") { -#ifdef __APPLE__ - exepath = _dyld_get_image_name(0); -#endif -#ifdef __linux - char linkname[64]; // /proc//exe - char buf[kMAXPATHLEN]; // exe path name - pid_t pid; - - // get our pid and build the name of the link in /proc - pid = getpid(); - snprintf(linkname,64, "/proc/%i/exe", pid); - int ret = readlink(linkname, buf, kMAXPATHLEN); - if (ret > 0 && ret < kMAXPATHLEN) { - buf[ret] = 0; - exepath = buf; - } -#endif -#if defined(R__FBSD) - procstat* ps = procstat_open_sysctl(); // - kinfo_proc* kp = kinfo_getproc(getpid()); - - if (kp!=NULL) { - char path_str[PATH_MAX] = ""; - procstat_getpathname(ps, kp, path_str, sizeof(path_str)); - exepath = path_str; - } - - free(kp); - procstat_close(ps); -#endif - } - 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); } @@ -154,21 +96,6 @@ static void PrintUsage() int main(int argc, char **argv) { -#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; From f5af848c6fe6aa998efc808dc94797f7fa6e44cb Mon Sep 17 00:00:00 2001 From: Jonas Rembser Date: Mon, 29 Sep 2025 19:24:09 +0200 Subject: [PATCH 3/3] [rootx] Turn `root` executable into symbolic link to `root.exe` There is no need to two separate executables anymore, but for backwards compatibility we keep `root.exe` and then `root` is a symbolic link to it. --- CMakeLists.txt | 3 - main/CMakeLists.txt | 17 ++++ rootx/CMakeLists.txt | 29 ------- rootx/src/rootx.cxx | 179 ------------------------------------------- 4 files changed, 17 insertions(+), 211 deletions(-) delete mode 100644 rootx/CMakeLists.txt delete mode 100644 rootx/src/rootx.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index a2933ab44fc9b..f47e60a617555 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -426,9 +426,6 @@ add_subdirectory (montecarlo) if(geom) add_subdirectory (geom) endif() -if(NOT WIN32) - add_subdirectory (rootx) -endif() add_subdirectory (misc) add_subdirectory (main) add_subdirectory (bindings) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index db66a47539422..8cf57e2559612 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -16,7 +16,24 @@ if(NOT WIN32) endif() ROOT_EXECUTABLE(roots.exe roots.cxx LIBRARIES Core MathCore CMAKENOEXPORT) endif() + ROOT_EXECUTABLE(root.exe rmain.cxx LIBRARIES Core Rint) + +if(NOT MSVC) + # Create a symlink in the build tree + add_custom_command(TARGET root.exe POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink "root.exe" ${CMAKE_BINARY_DIR}/bin/root + ) + # Create symlink in the install tree + install(CODE " + execute_process(COMMAND + \"${CMAKE_COMMAND}\" -E create_symlink + root.exe + \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/root\") + ") +endif() + + if(MSVC) set(root_exports "/EXPORT:_Init_thread_abort /EXPORT:_Init_thread_epoch \ /EXPORT:_Init_thread_footer /EXPORT:_Init_thread_header /EXPORT:_tls_index \ diff --git a/rootx/CMakeLists.txt b/rootx/CMakeLists.txt deleted file mode 100644 index 959281902454e..0000000000000 --- a/rootx/CMakeLists.txt +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. -# All rights reserved. -# -# For the licensing terms see $ROOTSYS/LICENSE. -# For the list of contributors see $ROOTSYS/README/CREDITS. - -############################################################################ -# CMakeLists.txt file for building ROOT rootx package -# @author Pere Mato, CERN -############################################################################ - -ROOT_EXECUTABLE(root src/rootx.cxx) - -if (CMAKE_SYSTEM_NAME MATCHES FreeBSD) - target_link_libraries(root PRIVATE util procstat) -endif() - -generateHeader(root - ${CMAKE_SOURCE_DIR}/core/base/src/root-argparse.py - ${CMAKE_BINARY_DIR}/ginclude/rootCommandLineOptionsHelp.h -) - -target_include_directories(root PRIVATE - ${CMAKE_SOURCE_DIR}/core/foundation/inc - ${CMAKE_SOURCE_DIR}/core/base/inc - ${CMAKE_SOURCE_DIR}/core/clib/inc # for snprintf.h - ${CMAKE_SOURCE_DIR}/core/meta/inc # for TGenericClassInfo.h - ${CMAKE_BINARY_DIR}/ginclude # for RConfigure.h and rootCommandLineOptionsHelp.h -) diff --git a/rootx/src/rootx.cxx b/rootx/src/rootx.cxx deleted file mode 100644 index a0a092ac5aa12..0000000000000 --- a/rootx/src/rootx.cxx +++ /dev/null @@ -1,179 +0,0 @@ -// @(#)root/rootx:$Id$ -// Author: Fons Rademakers 19/02/98 - -////////////////////////////////////////////////////////////////////////// -// // -// Rootx // -// // -// Rootx is a small front-end program that starts the main ROOT module. // -// This program is called "root" in the $ROOTSYS/bin directory and the // -// real ROOT executable is now called "root.exe" (formerly "root"). // -// // -////////////////////////////////////////////////////////////////////////// - -#include "RConfigure.h" -#include "Rtypes.h" -#include "snprintf.h" -#include "rootCommandLineOptionsHelp.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __APPLE__ -#include -#include -#endif - -#ifdef R__FBSD -#include -#include -#include -#include -#include -#endif // R__FBSD - -static int gChildpid; -static int GetErrno() -{ - return errno; -} - -static void ResetErrno() -{ - errno = 0; -} - -extern "C" { - static void SigTerm(int); -} - -static void SigTerm(int sig) -{ - // When we get terminated, terminate child, too. - kill(gChildpid, sig); -} - -static void WaitChild() -{ - // Wait till child (i.e. ROOT) is finished. - - int status; - - do { - while (waitpid(gChildpid, &status, WUNTRACED) < 0) { - if (GetErrno() != EINTR) - break; - ResetErrno(); - } - - if (WIFEXITED(status)) - exit(WEXITSTATUS(status)); - - if (WIFSIGNALED(status)) - exit(WTERMSIG(status)); - - if (WIFSTOPPED(status)) { // child got ctlr-Z - raise(SIGTSTP); // stop also parent - kill(gChildpid, SIGCONT); // if parent wakes up, wake up child - } - } while (WIFSTOPPED(status)); - - exit(0); -} - -static void PrintUsage() -{ - fprintf(stderr, kCommandLineOptionsHelp); -} - -int main(int argc, char **argv) -{ - // In batch mode don't show splash screen, idem for no logo mode, - // in about mode show always splash screen - int i; - for (i = 1; i < argc; i++) { - if (!strcmp(argv[i], "-?") || !strncmp(argv[i], "-h", 2) || - !strncmp(argv[i], "--help", 6)) { - PrintUsage(); - return 0; - } - } - - // Ignore SIGINT and SIGQUIT. Install handler for SIGUSR1. - - struct sigaction ignore, actTerm, - saveintr, savequit, saveterm; - -#if defined(__sun) && !defined(__i386) && !defined(__SVR4) - ignore.sa_handler = (void (*)())SIG_IGN; -#elif defined(__sun) && defined(__SVR4) - ignore.sa_handler = (void (*)(int))SIG_IGN; -#else - ignore.sa_handler = SIG_IGN; -#endif - sigemptyset(&ignore.sa_mask); - ignore.sa_flags = 0; - - actTerm = ignore; -#if defined(__sun) && !defined(__i386) && !defined(__SVR4) - actTerm.sa_handler = (void (*)())SigTerm; -#elif defined(__sun) && defined(__SVR4) - actTerm.sa_handler = SigTerm; -#elif (defined(__sgi) && !defined(__KCC)) || defined(__Lynx__) -# if defined(IRIX64) || (__GNUG__>=3) - actTerm.sa_handler = SigTerm; -# else - actTerm.sa_handler = (void (*)(...))SigTerm; -# endif -#else - actTerm.sa_handler = SigTerm; -#endif - sigaction(SIGINT, &ignore, &saveintr); - sigaction(SIGQUIT, &ignore, &savequit); - sigaction(SIGTERM, &actTerm, &saveterm); - - // Create child... - - if ((gChildpid = fork()) < 0) { - fprintf(stderr, "%s: error forking child\n", argv[0]); - return 1; - } else if (gChildpid > 0) { - WaitChild(); - } - - // Continue with child... - - // Restore original signal actions - sigaction(SIGINT, &saveintr, 0); - sigaction(SIGQUIT, &savequit, 0); - sigaction(SIGTERM, &saveterm, 0); - - // Child is going to overlay itself with the actual ROOT module... - - // Build argv vector - char arg0[] = "root.exe\0"; - - std::vector argvv(argc+1); - argvv[0] = arg0; - - for (i = 1; i < argc; i++) - argvv[i] = argv[i]; - argvv[i] = 0; - - // Execute actual ROOT module - execv("root.exe", argvv.data()); - - // Exec failed - fprintf(stderr, "%s: can't start ROOT -- check that root.exe exists!\n", - argv[0]); - - return 1; -}