11#include "Teuchos_EnvVariables.hpp"
21#if not(defined(WIN) && (_MSC_VER >= 1900))
27FILE *popen(
const char *command,
const char *mode)
28{
return _popen(command, mode); }
30int pclose(FILE *stream)
31{
return _pclose(stream);}
34namespace Teuchos::SystemInformation {
38std::map<std::string, std::pair<std::string, std::string>>& getCommandsMap() {
39 static std::map<std::string, std::pair<std::string, std::string>> commands;
43std::set<std::string>& getEnvironmentVariablesSet() {
44 static std::set<std::string> environmentVariables;
45 return environmentVariables;
48std::set<std::string>& getEnvironmentVariablePrefixSet() {
49 static std::set<std::string> environmentVariablePrefixes;
50 return environmentVariablePrefixes;
56bool commandIsAvailable(
const std::string &command) {
58 std::string(
"command -v " + command +
" > /dev/null 2>&1").c_str());
61std::string runCommandAndCaptureOutput(
const std::string &command) {
63 std::string result =
"";
64 FILE *pipe = popen(command.c_str(),
"r");
66 return "command \"" + command +
"\"failed";
68 while (fgets(buffer,
sizeof buffer, pipe) != NULL) {
73 return "command \"" + command +
"\"failed";
80registerEnvironmentVariable(
const std::string &variableName) {
81 auto &environmentVariables = getEnvironmentVariablesSet();
83 if (
auto search = environmentVariables.find(variableName);
84 search != environmentVariables.end()) {
86 return ALREADY_PRESENT;
89 environmentVariables.insert(variableName);
94void registerAllPrefixedVariables(
const std::string &prefix) {
96#if defined(WIN) && (_MSC_VER >= 1900)
97 env = *__p__environ();
101 for (; *env; ++env) {
106 if (substrings.size() > 0) {
107 std::string name = substrings[0];
109 if (name.size() >= prefix.size() &&
110 name.substr(0, prefix.size()) == prefix) {
111 Teuchos::SystemInformation::registerEnvironmentVariable(name);
118registerEnvironmentVariablePrefix(
const std::string &prefix) {
119 auto &environmentVariablePrefixes = getEnvironmentVariablePrefixSet();
120 if (
auto search = environmentVariablePrefixes.find(prefix);
121 search != environmentVariablePrefixes.end()) {
123 return ALREADY_PRESENT;
126 environmentVariablePrefixes.insert(prefix);
133registerCommand(
const std::string &commandLabel,
134 const std::string &commandToRunAndCapture,
135 const std::string &commandToCheckForExistence) {
136 auto &commands = getCommandsMap();
138 std::string myCommandToRunAndCapture = commandToRunAndCapture;
139 if (myCommandToRunAndCapture.empty())
140 myCommandToRunAndCapture = commandLabel;
142 std::string myCommandToCheckForExistence = commandToCheckForExistence;
143 if (myCommandToCheckForExistence.empty())
144 myCommandToCheckForExistence = myCommandToRunAndCapture;
146 if (
auto search = commands.find(commandLabel); search != commands.end()) {
147 if ((commands[commandLabel].first == myCommandToCheckForExistence) &&
148 (commands[commandLabel].second == myCommandToRunAndCapture))
149 return ALREADY_PRESENT;
152 <<
"Teuchos::SystemInformation: Attempted to register a command (\""
153 << commandLabel <<
"\", \"" << myCommandToRunAndCapture <<
"\", \""
154 << myCommandToCheckForExistence <<
"\") "
155 <<
"that clashes with already registered command: (" << commandLabel
156 <<
"\", \"" << commands[commandLabel].first <<
"\", \""
157 << commands[commandLabel].second <<
"\")." << std::endl;
162 commands[commandLabel] = {myCommandToCheckForExistence, myCommandToRunAndCapture};
167void initializeCollection() {
169 std::string userProvidedEnvVariables =
171 "TEUCHOS_USER_ENVIRONMENT_VARIABLES",
"");
172 if (!userProvidedEnvVariables.empty()) {
174 bool isValid = (strings.size() >= 1);
177 <<
"Teuchos::SystemInformation: The value of the environment "
179 "TEUCHOS_USER_ENVIRONMENT_VARIABLES needs to be a semi-colon "
180 "seperated string. Value: "
181 << userProvidedEnvVariables << std::endl;
182 for (
int itemNo = 0; itemNo < strings.size(); ++itemNo) {
183 std::string &variableName = strings[itemNo];
184 if (registerEnvironmentVariable(variableName) == FAILURE)
188 !isValid, std::runtime_error,
189 "Teuchos::SystemInformation: Invalid environment variable "
190 "TEUCHOS_USER_ENVIRONMENT_VARIABLES");
193 std::string userProvidedCommands =
195 if (!userProvidedCommands.empty()) {
197 bool isValid = (strings.size() % 3 == 0) && (strings.size() >= 3);
199 std::cerr <<
"Teuchos::SystemInformation: The value of the environment "
200 "variable TEUCHOS_USER_COMMANDS "
201 "needs to be a semi-colon seperated string with a number of "
202 "elements that is a multiple of 3. Value: "
203 << userProvidedCommands << std::endl;
205 while (isValid && (3 * tupleNo + 2 < strings.size())) {
206 std::string &commandLabel = strings[3 * tupleNo];
207 std::string &commandToRunAndCapture = strings[3 * tupleNo + 1];
208 std::string &commandToCheckForExistence = strings[3 * tupleNo + 2];
209 if (registerCommand(commandLabel, commandToRunAndCapture,
210 commandToCheckForExistence) == FAILURE) {
216 "Teuchos::SystemInformation: Invalid "
217 "environment variable TEUCHOS_USER_COMMANDS");
221 const std::string executable = std::filesystem::canonical(
"/proc/self/exe").string();
222 if (!executable.empty()) {
223 registerCommand(
"ldd",
"ldd " + executable,
"ldd");
224 registerCommand(
"stat",
"stat --printf %s " + executable,
"stat");
226 }
catch (std::filesystem::filesystem_error &) {
231 registerCommand(
"lscpu");
234 registerCommand(
"sensors");
237 registerEnvironmentVariablePrefix(
"OMP");
240 registerCommand(
"ompi_info");
241 registerEnvironmentVariablePrefix(
"OMPI");
244 registerCommand(
"mpichinfo");
245 registerEnvironmentVariablePrefix(
"MPICH");
248 registerEnvironmentVariablePrefix(
"CRAY");
251 registerCommand(
"module",
"module list 2>&1",
"module");
254 registerCommand(
"nvidia-smi",
"nvidia-smi --query",
"nvidia-smi");
255 registerEnvironmentVariablePrefix(
"CUDA");
258 registerCommand(
"rocm-smi",
"rocm-smi --showallinfo",
"rocm-smi");
261 registerCommand(
"sycl-ls",
"sycl-ls --verbose",
"sycl-ls");
264 for (
auto &prefix : {
"TEUCHOS",
"KOKKOS",
"TPETRA",
"STK",
"MUELU",
"IFPACK2"})
265 registerEnvironmentVariablePrefix(prefix);
268std::map<std::string, std::string> collectSystemInformation() {
270 std::map<std::string, std::string> data;
272 const std::string DATA_NOT_AVAILABLE =
"NOT AVAILABLE";
274 auto &commands = getCommandsMap();
275 for (
auto &command : commands) {
276 const bool isAvailable = commandIsAvailable(command.second.first);
278 data[command.first] = runCommandAndCaptureOutput(command.second.second);
280 data[command.first] = DATA_NOT_AVAILABLE;
284 auto &environmentVariablePrefixes = getEnvironmentVariablePrefixSet();
285 for (
auto &prefix : environmentVariablePrefixes) {
286 registerAllPrefixedVariables(prefix);
289 auto &environmentVariables = getEnvironmentVariablesSet();
290 for (
auto &envVariable : environmentVariables) {
291 const char *varVal = std::getenv(envVariable.c_str());
292 if (varVal ==
nullptr)
293 data[envVariable] =
"NOT SET";
A std::string utilities class for Teuchos.
Standard test and throw macros.
Smart reference counting pointer class for automatic garbage collection.
static Array< std::string > splitString(const std::string_view s, const char sep=',')
Split an input std::string using a seperator char sep.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.