/* * Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2007-2010 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2007 Sun Microsystem, Inc. All rights reserved. * Copyright (c) 2010 Sandia National Laboratories. All rights reserved. * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ * */ #include "opal_config.h" #include #include "opal/mca/installdirs/base/base.h" #include "opal/mca/installdirs/installdirs.h" #include "opal/util/os_path.h" #include "opal/util/printf.h" /* Support both ${name} and @{name} forms. The latter allows us to pass values through AC_SUBST without being munged by m4 (e.g., if we want to pass "@{libdir}" and not have it replaced by m4 to be whatever the actual value of the shell variable is. */ #define EXPAND_STRING(name) EXPAND_STRING2(name, name) #define EXPAND_STRING2(ompiname, fieldname) \ do { \ if (NULL != (start_pos = strstr(retval, "${" #fieldname "}"))) { \ tmp = retval; \ *start_pos = '\0'; \ end_pos = start_pos + strlen("${" #fieldname "}"); \ opal_asprintf(&retval, "%s%s%s", tmp, opal_install_dirs.ompiname + destdir_offset, \ end_pos); \ free(tmp); \ changed = true; \ } else if (NULL != (start_pos = strstr(retval, "@{" #fieldname "}"))) { \ tmp = retval; \ *start_pos = '\0'; \ end_pos = start_pos + strlen("@{" #fieldname "}"); \ opal_asprintf(&retval, "%s%s%s", tmp, opal_install_dirs.ompiname + destdir_offset, \ end_pos); \ free(tmp); \ changed = true; \ } \ } while (0) /* * Read the lengthy comment below to understand the value of the * is_setup parameter. */ static char *opal_install_dirs_expand_internal(const char *input, bool is_setup) { size_t len, i; bool needs_expand = false; char *retval = NULL; char *destdir = NULL; size_t destdir_offset = 0; /* This is subtle, and worth explaining. If we substitute in any ${FIELD} values, we need to prepend it with the value of the $OPAL_DESTDIR environment variable -- if it is set. We need to handle at least three cases properly (assume that configure was invoked with --prefix=/opt/openmpi and no other directory specifications, and OPAL_DESTDIR is set to /tmp/buildroot): 1. Individual directories, such as libdir. These need to be prepended with DESTDIR. I.e., return /tmp/buildroot/opt/openmpi/lib. 2. Compiler flags that have ${FIELD} values embedded in them. For example, consider if a wrapper compiler data file contains the line: preprocessor_flags=-DMYFLAG="${prefix}/share/randomthingy/" The value we should return is: -DMYFLAG="/tmp/buildroot/opt/openmpi/share/randomthingy/" 3. Compiler flags that do not have any ${FIELD} values. For example, consider if a wrapper compiler data file contains the line: preprocessor_flags=-pthread The value we should return is: -pthread Note, too, that this OPAL_DESTDIR futzing only needs to occur during opal_init(). By the time opal_init() has completed, all values should be substituted in that need substituting. Hence, we take an extra parameter (is_setup) to know whether we should do this futzing or not. */ if (is_setup) { destdir = getenv("OPAL_DESTDIR"); if (NULL != destdir && strlen(destdir) > 0) { destdir_offset = strlen(destdir); } } len = strlen(input); for (i = 0; i < len; ++i) { if ('$' == input[i] || '@' == input[i]) { needs_expand = true; break; } } retval = strdup(input); if (NULL == retval) { return NULL; } if (needs_expand) { bool changed = false; char *start_pos, *end_pos, *tmp; do { changed = false; EXPAND_STRING(prefix); EXPAND_STRING(exec_prefix); EXPAND_STRING(bindir); EXPAND_STRING(sbindir); EXPAND_STRING(libexecdir); EXPAND_STRING(datarootdir); EXPAND_STRING(datadir); EXPAND_STRING(sysconfdir); EXPAND_STRING(sharedstatedir); EXPAND_STRING(localstatedir); EXPAND_STRING(libdir); EXPAND_STRING(includedir); EXPAND_STRING(infodir); EXPAND_STRING(mandir); EXPAND_STRING2(opaldatadir, pkgdatadir); EXPAND_STRING2(opallibdir, pkglibdir); EXPAND_STRING2(opalincludedir, pkgincludedir); } while (changed); } if (NULL != destdir) { char *tmp = retval; retval = opal_os_path(false, destdir, tmp, NULL); free(tmp); } return retval; } char *opal_install_dirs_expand(const char *input) { /* We do NOT want OPAL_DESTDIR expansion in this case. */ return opal_install_dirs_expand_internal(input, false); } char *opal_install_dirs_expand_setup(const char *input) { /* We DO want OPAL_DESTDIR expansion in this case. */ return opal_install_dirs_expand_internal(input, true); }