diff --git a/config/opal_config_libevent.m4 b/config/opal_config_libevent.m4 index 4e16d899696..cea427df2c6 100644 --- a/config/opal_config_libevent.m4 +++ b/config/opal_config_libevent.m4 @@ -205,6 +205,7 @@ AC_DEFUN([_OPAL_CONFIG_LIBEVENT_INTERNAL], [ OPAL_VAR_SCOPE_PUSH(subconfig_happy subconfig_prefix internal_libevent_location) AS_IF([test ! -z $prefix], [subconfig_prefix="--prefix=$prefix"]) + AS_IF([test ! -z $libdir], [subconfig_prefix="--libdir=$libdir"]) # Note: To update the version of libevent shipped, update the # constant in autogen.pl. diff --git a/opal/mca/installdirs/base/installdirs_base_components.c b/opal/mca/installdirs/base/installdirs_base_components.c index 1daae990df0..f254a829987 100644 --- a/opal/mca/installdirs/base/installdirs_base_components.c +++ b/opal/mca/installdirs/base/installdirs_base_components.c @@ -21,7 +21,11 @@ #include "opal/mca/installdirs/installdirs.h" #include "opal/mca/mca.h" +#include +#include + opal_install_dirs_t opal_install_dirs = {0}; +static int opal_install_dir_warn_if_non_existent = 0; #define CONDITIONAL_COPY(target, origin, field) \ do { \ @@ -30,6 +34,23 @@ opal_install_dirs_t opal_install_dirs = {0}; } \ } while (0) +#define CHECK_AND_COMPLAIN(field) \ + do { \ + if(!directory_exists(opal_install_dirs.field)) { \ + fprintf(stderr, #field ": %s\n", opal_install_dirs.field); \ + } \ + } while (0) + +static int directory_exists(const char *path) +{ + struct stat info; + + if (0 != stat(path, &info)) { + return 0; + } + return S_ISDIR(info.st_mode); +} + static int opal_installdirs_base_open(mca_base_open_flag_t flags) { mca_base_component_list_item_t *component_item; @@ -87,26 +108,30 @@ static int opal_installdirs_base_open(mca_base_open_flag_t flags) opal_install_dirs.opalincludedir = opal_install_dirs_expand_setup( opal_install_dirs.opalincludedir); -#if 0 - fprintf(stderr, "prefix: %s\n", opal_install_dirs.prefix); - fprintf(stderr, "exec_prefix: %s\n", opal_install_dirs.exec_prefix); - fprintf(stderr, "bindir: %s\n", opal_install_dirs.bindir); - fprintf(stderr, "sbindir: %s\n", opal_install_dirs.sbindir); - fprintf(stderr, "libexecdir: %s\n", opal_install_dirs.libexecdir); - fprintf(stderr, "datarootdir: %s\n", opal_install_dirs.datarootdir); - fprintf(stderr, "datadir: %s\n", opal_install_dirs.datadir); - fprintf(stderr, "sysconfdir: %s\n", opal_install_dirs.sysconfdir); - fprintf(stderr, "sharedstatedir: %s\n", opal_install_dirs.sharedstatedir); - fprintf(stderr, "localstatedir: %s\n", opal_install_dirs.localstatedir); - fprintf(stderr, "libdir: %s\n", opal_install_dirs.libdir); - fprintf(stderr, "includedir: %s\n", opal_install_dirs.includedir); - fprintf(stderr, "infodir: %s\n", opal_install_dirs.infodir); - fprintf(stderr, "mandir: %s\n", opal_install_dirs.mandir); - fprintf(stderr, "pkgdatadir: %s\n", opal_install_dirs.pkgdatadir); - fprintf(stderr, "pkglibdir: %s\n", opal_install_dirs.pkglibdir); - fprintf(stderr, "pkgincludedir: %s\n", opal_install_dirs.pkgincludedir); -#endif + (void)mca_base_var_register("opal", "opal", "installdir", "warn", + "Print a warning is any of the OMPI necessary paths cannot be found", + MCA_BASE_VAR_TYPE_INT, NULL, 0, 0, OPAL_INFO_LVL_9, + MCA_BASE_VAR_SCOPE_READONLY, &opal_install_dir_warn_if_non_existent); + if(opal_install_dir_warn_if_non_existent) { + CHECK_AND_COMPLAIN(prefix); + CHECK_AND_COMPLAIN(exec_prefix); + CHECK_AND_COMPLAIN(bindir); + //CHECK_AND_COMPLAIN(sbindir); + //CHECK_AND_COMPLAIN(libexecdir); + CHECK_AND_COMPLAIN(datarootdir); + CHECK_AND_COMPLAIN(datadir); + CHECK_AND_COMPLAIN(sysconfdir); + //CHECK_AND_COMPLAIN(sharedstatedir); + //CHECK_AND_COMPLAIN(localstatedir); + CHECK_AND_COMPLAIN(libdir); + CHECK_AND_COMPLAIN(includedir); + //CHECK_AND_COMPLAIN(infodir); + CHECK_AND_COMPLAIN(mandir); + CHECK_AND_COMPLAIN(opaldatadir); + CHECK_AND_COMPLAIN(opallibdir); + CHECK_AND_COMPLAIN(opalincludedir); + } /* NTH: Is it ok not to close the components? If not we can add a flag to mca_base_framework_components_close to indicate not to deregister variable groups */ diff --git a/opal/mca/installdirs/config/Makefile.am b/opal/mca/installdirs/config/Makefile.am index 2ec99d31234..b0136a7c78b 100644 --- a/opal/mca/installdirs/config/Makefile.am +++ b/opal/mca/installdirs/config/Makefile.am @@ -18,4 +18,4 @@ libmca_installdirs_config_la_SOURCES = \ # This file is generated; we do not want to include it in the tarball nodist_libmca_installdirs_config_la_SOURCES = \ - install_dirs.h + ../install_dirs.h diff --git a/opal/mca/installdirs/config/configure.m4 b/opal/mca/installdirs/config/configure.m4 index bc910fdcc5d..88489e9aeca 100644 --- a/opal/mca/installdirs/config/configure.m4 +++ b/opal/mca/installdirs/config/configure.m4 @@ -24,6 +24,6 @@ AC_DEFUN([MCA_opal_installdirs_config_COMPILE_MODE], [ # ------------------------------------------------ AC_DEFUN([MCA_opal_installdirs_config_CONFIG],[ AC_CONFIG_FILES([opal/mca/installdirs/config/Makefile - opal/mca/installdirs/config/install_dirs.h]) + opal/mca/installdirs/install_dirs.h]) ]) diff --git a/opal/mca/installdirs/config/opal_installdirs_config.c b/opal/mca/installdirs/config/opal_installdirs_config.c index 201cc497f16..1f79aff88be 100644 --- a/opal/mca/installdirs/config/opal_installdirs_config.c +++ b/opal/mca/installdirs/config/opal_installdirs_config.c @@ -10,7 +10,7 @@ #include "opal_config.h" -#include "opal/mca/installdirs/config/install_dirs.h" +#include "opal/mca/installdirs/install_dirs.h" #include "opal/mca/installdirs/installdirs.h" const opal_installdirs_base_component_t mca_installdirs_config_component = { diff --git a/opal/mca/installdirs/config/install_dirs.h.in b/opal/mca/installdirs/install_dirs.h.in similarity index 100% rename from opal/mca/installdirs/config/install_dirs.h.in rename to opal/mca/installdirs/install_dirs.h.in diff --git a/opal/mca/installdirs/runtime/Makefile.am b/opal/mca/installdirs/runtime/Makefile.am new file mode 100644 index 00000000000..1ba674c606f --- /dev/null +++ b/opal/mca/installdirs/runtime/Makefile.am @@ -0,0 +1,14 @@ +# +# Copyright (c) 2025 NVIDIA Corporation. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +noinst_LTLIBRARIES = libmca_installdirs_runtime.la + +libmca_installdirs_runtime_la_SOURCES = \ + opal_installdirs_runtime.c +libmca_installdirs_runtime_la_CPPFLAGS = -DOPAL_LIB_NAME=\"@OPAL_LIB_NAME@\" diff --git a/opal/mca/installdirs/runtime/configure.m4 b/opal/mca/installdirs/runtime/configure.m4 new file mode 100644 index 00000000000..b64cd461846 --- /dev/null +++ b/opal/mca/installdirs/runtime/configure.m4 @@ -0,0 +1,45 @@ +# -*- shell-script -*- +# +# Copyright (c) 2025 NVIDIA Corporation. All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +AC_DEFUN([MCA_opal_installdirs_runtime_PRIORITY], [5]) + +AC_DEFUN([MCA_opal_installdirs_runtime_COMPILE_MODE], [ + AC_MSG_CHECKING([for MCA component $2:$3 compile mode]) + $4="static" + AC_MSG_RESULT([$$4]) +]) + +# MCA_installdirs_config_CONFIG(action-if-can-compile, +# [action-if-cant-compile]) +# ------------------------------------------------ +AC_DEFUN([MCA_opal_installdirs_runtime_CONFIG], [ + # Check if we are building a shared library or not. Disable if static + AC_MSG_CHECKING([if shared libraries are enabled]) + AS_IF([test "$enable_shared" != "yes"], + [installdirs_runtime_happy="no"], + [installdirs_runtime_happy="yes"]) + AC_MSG_RESULT([$installdirs_runtime_happy]) + + # Check if dladdr is available + AS_IF([test "$installdirs_runtime_happy" = "yes"], + [AC_CHECK_HEADERS([dlfcn.h], + [], + [installdirs_runtime_happy="no"])]) + AS_IF([test "$installdirs_runtime_happy" = "yes"], + [AC_CHECK_LIB([dl], [dladdr], + [], + [installdirs_runtime_happy="no"]) + ]) + # + AS_IF([test "$installdirs_runtime_happy" = "yes"], + [AC_CONFIG_FILES([opal/mca/installdirs/runtime/Makefile]) + $1], [$2]) +]) + diff --git a/opal/mca/installdirs/runtime/opal_installdirs_runtime.c b/opal/mca/installdirs/runtime/opal_installdirs_runtime.c new file mode 100644 index 00000000000..e5cb7cd1a35 --- /dev/null +++ b/opal/mca/installdirs/runtime/opal_installdirs_runtime.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights + * reserved. + * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "opal_config.h" + +#include +#include + +#include "opal/constants.h" +#include "opal/mca/installdirs/installdirs.h" +#include "opal/runtime/opal.h" + +static int installdirs_runtime_open(void); + +opal_installdirs_base_component_t mca_installdirs_runtime_component = { + /* First, the mca_component_t struct containing meta information + about the component itself */ + {OPAL_INSTALLDIRS_BASE_VERSION_2_0_0, + + /* Component name and version */ + "runtime", OPAL_MAJOR_VERSION, OPAL_MINOR_VERSION, OPAL_RELEASE_VERSION, + + /* Component open and close functions */ + installdirs_runtime_open, NULL}, + {/* This component is checkpointable */ + MCA_BASE_METADATA_PARAM_CHECKPOINT}, + + /* Next the opal_install_dirs_t install_dirs_data information */ + { + NULL, + }, +}; + +#include +#include "opal/util/basename.h" +#include "opal/mca/installdirs/install_dirs.h" + +/** + * We are trying to solve a particular use case here, when the entire install tree + * of Open MPI (and its dependencies) has been moved into another location. Nothing + * fancy, the entire install tree has maintained his shape but changed the prefix. + */ +static int installdirs_runtime_open(void) +{ + Dl_info info; + void* opal_fct; + char* libname = NULL; + const char* base_prefix_path = OPAL_LIBDIR; + + /* Casting from void* to fct pointer according to POSIX.1-2001 and POSIX.1-2008 */ + *(void **)&opal_fct = dlsym(RTLD_DEFAULT, "opal_init_util"); + + if( 0 == dladdr(opal_fct, &info) ) { + goto bail_out_with_no_data; + } + + /* If this build was both static and shared then this compoenent will be build and will exists + * even in the static library. We need to prevent setting a prefix for the OMPI library that + * is actually the application path. Check, if the name points to a library. + */ + libname = opal_basename(info.dli_fname); + if( strncmp(libname, "lib", 3)) { /* not a shared library */ + base_prefix_path = OPAL_BINDIR; + } else { +#if defined(OPAL_LIB_NAME) + /* Extra check using the installed name of the OPAL library */ + if( strncmp(libname+3, OPAL_LIB_NAME, strlen(OPAL_LIB_NAME)) ) { /* not a shared library */ + goto bail_out_with_no_data; + } +#endif /* defined(OPAL_LIB_NAME) */ + } + /* Remove the shared library name and it's first dirname to obtain a prefix. This + * is true in most cases, especially when the install directory was just moved + * moved around, but it is not necessarily always true. + */ + char *prefix = NULL, *dname = opal_dirname(info.dli_fname); + int dname_idx = strlen(dname), dname_token = dname_idx; + for( int i = strlen(base_prefix_path); (i > 0) && (dname_idx > 0); i-- ) { + if( dname[dname_idx] != base_prefix_path[i] ) { + dname[dname_token] = '\0'; + prefix = dname; + dname = NULL; /* the string is now attached to the component, prevent it from being freed */ + break; + } + if( dname[dname_idx] == OPAL_PATH_SEP[0] ) + dname_token = dname_idx; + dname_idx--; + } + + mca_installdirs_runtime_component.install_dirs_data.prefix = prefix; + + /* If we goto here, there is some error. Unfortunately, we can't return an error from + * this function, the MCA infrastructure is not yet completely setup, and a call to + * mca_base_component_close will break. + * So, return success but provide no meaningfull data in the component. + */ + bail_out_with_no_data: + + free(libname); + free(dname); + + return OPAL_SUCCESS; +} diff --git a/opal/mca/installdirs/runtime/owner.txt b/opal/mca/installdirs/runtime/owner.txt new file mode 100644 index 00000000000..0177f4391ab --- /dev/null +++ b/opal/mca/installdirs/runtime/owner.txt @@ -0,0 +1,7 @@ +# +# owner/status file +# owner: institution that is responsible for this package +# status: e.g. active, maintenance, unmaintained +# +owner: NVIDIA +status: active