1 /*
2 * Copyright (c) 2006-2007 Los Alamos National Security, LLC. All rights
3 * reserved.
4 * Copyright (c) 2007-2010 Cisco Systems, Inc. All rights reserved.
5 * Copyright (c) 2007 Sun Microsystem, Inc. All rights reserved.
6 * Copyright (c) 2010 Sandia National Laboratories. All rights reserved.
7 * Copyright (c) 2018 Amazon.com, Inc. or its affiliates. All Rights reserved.
8 * $COPYRIGHT$
9 *
10 * Additional copyrights may follow
11 *
12 * $HEADER$
13 *
14 */
15
16 #include "opal_config.h"
17
18 #include <string.h>
19
20 #include "opal/util/os_path.h"
21 #include "opal/util/printf.h"
22 #include "opal/mca/installdirs/base/base.h"
23 #include "opal/mca/installdirs/installdirs.h"
24
25 /* Support both ${name} and @{name} forms. The latter allows us to
26 pass values through AC_SUBST without being munged by m4 (e.g., if
27 we want to pass "@{libdir}" and not have it replaced by m4 to be
28 whatever the actual value of the shell variable is. */
29 #define EXPAND_STRING(name) EXPAND_STRING2(name, name)
30
31 #define EXPAND_STRING2(ompiname, fieldname) \
32 do { \
33 if (NULL != (start_pos = strstr(retval, "${" #fieldname "}"))) { \
34 tmp = retval; \
35 *start_pos = '\0'; \
36 end_pos = start_pos + strlen("${" #fieldname "}"); \
37 opal_asprintf(&retval, "%s%s%s", tmp, \
38 opal_install_dirs.ompiname + destdir_offset, \
39 end_pos); \
40 free(tmp); \
41 changed = true; \
42 } else if (NULL != (start_pos = strstr(retval, "@{" #fieldname "}"))) { \
43 tmp = retval; \
44 *start_pos = '\0'; \
45 end_pos = start_pos + strlen("@{" #fieldname "}"); \
46 opal_asprintf(&retval, "%s%s%s", tmp, \
47 opal_install_dirs.ompiname + destdir_offset, \
48 end_pos); \
49 free(tmp); \
50 changed = true; \
51 } \
52 } while (0)
53
54
55 /*
56 * Read the lengthy comment below to understand the value of the
57 * is_setup parameter.
58 */
59 static char *
60 opal_install_dirs_expand_internal(const char* input, bool is_setup)
61 {
62 size_t len, i;
63 bool needs_expand = false;
64 char *retval = NULL;
65 char *destdir = NULL;
66 size_t destdir_offset = 0;
67
68 /* This is subtle, and worth explaining.
69
70 If we substitute in any ${FIELD} values, we need to prepend it
71 with the value of the $OPAL_DESTDIR environment variable -- if
72 it is set.
73
74 We need to handle at least three cases properly (assume that
75 configure was invoked with --prefix=/opt/openmpi and no other
76 directory specifications, and OPAL_DESTDIR is set to
77 /tmp/buildroot):
78
79 1. Individual directories, such as libdir. These need to be
80 prepended with DESTDIR. I.e., return
81 /tmp/buildroot/opt/openmpi/lib.
82
83 2. Compiler flags that have ${FIELD} values embedded in them.
84 For example, consider if a wrapper compiler data file
85 contains the line:
86
87 preprocessor_flags=-DMYFLAG="${prefix}/share/randomthingy/"
88
89 The value we should return is:
90
91 -DMYFLAG="/tmp/buildroot/opt/openmpi/share/randomthingy/"
92
93 3. Compiler flags that do not have any ${FIELD} values.
94 For example, consider if a wrapper compiler data file
95 contains the line:
96
97 preprocessor_flags=-pthread
98
99 The value we should return is:
100
101 -pthread
102
103 Note, too, that this OPAL_DESTDIR futzing only needs to occur
104 during opal_init(). By the time opal_init() has completed, all
105 values should be substituted in that need substituting. Hence,
106 we take an extra parameter (is_setup) to know whether we should
107 do this futzing or not. */
108 if (is_setup) {
109 destdir = getenv("OPAL_DESTDIR");
110 if (NULL != destdir && strlen(destdir) > 0) {
111 destdir_offset = strlen(destdir);
112 }
113 }
114
115 len = strlen(input);
116 for (i = 0 ; i < len ; ++i) {
117 if ('$' == input[i] || '@' == input[i]) {
118 needs_expand = true;
119 break;
120 }
121 }
122
123 retval = strdup(input);
124 if (NULL == retval) return NULL;
125
126 if (needs_expand) {
127 bool changed = false;
128 char *start_pos, *end_pos, *tmp;
129
130 do {
131 changed = false;
132 EXPAND_STRING(prefix);
133 EXPAND_STRING(exec_prefix);
134 EXPAND_STRING(bindir);
135 EXPAND_STRING(sbindir);
136 EXPAND_STRING(libexecdir);
137 EXPAND_STRING(datarootdir);
138 EXPAND_STRING(datadir);
139 EXPAND_STRING(sysconfdir);
140 EXPAND_STRING(sharedstatedir);
141 EXPAND_STRING(localstatedir);
142 EXPAND_STRING(libdir);
143 EXPAND_STRING(includedir);
144 EXPAND_STRING(infodir);
145 EXPAND_STRING(mandir);
146 EXPAND_STRING2(opaldatadir, pkgdatadir);
147 EXPAND_STRING2(opallibdir, pkglibdir);
148 EXPAND_STRING2(opalincludedir, pkgincludedir);
149 } while (changed);
150 }
151
152 if (NULL != destdir) {
153 char *tmp = retval;
154 retval = opal_os_path(false, destdir, tmp, NULL);
155 free(tmp);
156 }
157
158 return retval;
159 }
160
161
162 char *
163 opal_install_dirs_expand(const char* input)
164 {
165 /* We do NOT want OPAL_DESTDIR expansion in this case. */
166 return opal_install_dirs_expand_internal(input, false);
167 }
168
169
170 char *
171 opal_install_dirs_expand_setup(const char* input)
172 {
173 /* We DO want OPAL_DESTDIR expansion in this case. */
174 return opal_install_dirs_expand_internal(input, true);
175 }