11#include "Teuchos_EnvVariables.hpp"
15#if !defined(__GNUC__) || (__GNUC__ >= 10)
23#if not(defined(WIN) && (_MSC_VER >= 1900))
28namespace Teuchos::SystemInformation {
32std::map<std::string, std::pair<std::string, std::string>>& getCommandsMap() {
33 static std::map<std::string, std::pair<std::string, std::string>> commands;
37std::set<std::string>& getEnvironmentVariablesSet() {
38 static std::set<std::string> environmentVariables;
39 return environmentVariables;
42std::set<std::string>& getEnvironmentVariablePrefixSet() {
43 static std::set<std::string> environmentVariablePrefixes;
44 return environmentVariablePrefixes;
50bool commandIsAvailable(
const std::string &command) {
52 std::string(
"command -v " + command +
" > /dev/null 2>&1").c_str());
55std::string runCommandAndCaptureOutput(
const std::string &command) {
57 std::string result =
"";
58 FILE *pipe = popen(command.c_str(),
"r");
60 return "command \"" + command +
"\"failed";
62 while (fgets(buffer,
sizeof buffer, pipe) != NULL) {
67 return "command \"" + command +
"\"failed";
74registerEnvironmentVariable(
const std::string &variableName) {
75 auto &environmentVariables = getEnvironmentVariablesSet();
77 if (
auto search = environmentVariables.find(variableName);
78 search != environmentVariables.end()) {
80 return ALREADY_PRESENT;
83 environmentVariables.insert(variableName);
88void registerAllPrefixedVariables(
const std::string &prefix) {
90#if defined(WIN) && (_MSC_VER >= 1900)
91 env = *__p__environ();
100 if (substrings.size() > 0) {
101 std::string name = substrings[0];
103 if (name.size() >= prefix.size() &&
104 name.substr(0, prefix.size()) == prefix) {
105 Teuchos::SystemInformation::registerEnvironmentVariable(name);
112registerEnvironmentVariablePrefix(
const std::string &prefix) {
113 auto &environmentVariablePrefixes = getEnvironmentVariablePrefixSet();
114 if (
auto search = environmentVariablePrefixes.find(prefix);
115 search != environmentVariablePrefixes.end()) {
117 return ALREADY_PRESENT;
120 environmentVariablePrefixes.insert(prefix);
127registerCommand(
const std::string &commandLabel,
128 const std::string &commandToRunAndCapture,
129 const std::string &commandToCheckForExistence) {
130 auto &commands = getCommandsMap();
132 std::string myCommandToRunAndCapture = commandToRunAndCapture;
133 if (myCommandToRunAndCapture.empty())
134 myCommandToRunAndCapture = commandLabel;
136 std::string myCommandToCheckForExistence = commandToCheckForExistence;
137 if (myCommandToCheckForExistence.empty())
138 myCommandToCheckForExistence = myCommandToRunAndCapture;
140 if (
auto search = commands.find(commandLabel); search != commands.end()) {
141 if ((commands[commandLabel].first == myCommandToCheckForExistence) &&
142 (commands[commandLabel].second == myCommandToRunAndCapture))
143 return ALREADY_PRESENT;
146 <<
"Teuchos::SystemInformation: Attempted to register a command (\""
147 << commandLabel <<
"\", \"" << myCommandToRunAndCapture <<
"\", \""
148 << myCommandToCheckForExistence <<
"\") "
149 <<
"that clashes with already registered command: (" << commandLabel
150 <<
"\", \"" << commands[commandLabel].first <<
"\", \""
151 << commands[commandLabel].second <<
"\")." << std::endl;
156 commands[commandLabel] = {myCommandToCheckForExistence, myCommandToRunAndCapture};
161void initializeCollection() {
163 std::string userProvidedEnvVariables =
165 "TEUCHOS_USER_ENVIRONMENT_VARIABLES",
"");
166 if (!userProvidedEnvVariables.empty()) {
168 bool isValid = (strings.size() >= 1);
171 <<
"Teuchos::SystemInformation: The value of the environment "
173 "TEUCHOS_USER_ENVIRONMENT_VARIABLES needs to be a semi-colon "
174 "seperated string. Value: "
175 << userProvidedEnvVariables << std::endl;
176 for (
int itemNo = 0; itemNo < strings.size(); ++itemNo) {
177 std::string &variableName = strings[itemNo];
178 if (registerEnvironmentVariable(variableName) == FAILURE)
182 !isValid, std::runtime_error,
183 "Teuchos::SystemInformation: Invalid environment variable "
184 "TEUCHOS_USER_ENVIRONMENT_VARIABLES");
187 std::string userProvidedCommands =
189 if (!userProvidedCommands.empty()) {
191 bool isValid = (strings.size() % 3 == 0) && (strings.size() >= 3);
193 std::cerr <<
"Teuchos::SystemInformation: The value of the environment "
194 "variable TEUCHOS_USER_COMMANDS "
195 "needs to be a semi-colon seperated string with a number of "
196 "elements that is a multiple of 3. Value: "
197 << userProvidedCommands << std::endl;
199 while (isValid && (3 * tupleNo + 2 < strings.size())) {
200 std::string &commandLabel = strings[3 * tupleNo];
201 std::string &commandToRunAndCapture = strings[3 * tupleNo + 1];
202 std::string &commandToCheckForExistence = strings[3 * tupleNo + 2];
203 if (registerCommand(commandLabel, commandToRunAndCapture,
204 commandToCheckForExistence) == FAILURE) {
210 "Teuchos::SystemInformation: Invalid "
211 "environment variable TEUCHOS_USER_COMMANDS");
214#if !defined(__GNUC__) || (__GNUC__ >= 10)
216 const std::string executable = std::filesystem::canonical(
"/proc/self/exe");
217 if (!executable.empty()) {
218 registerCommand(
"ldd",
"ldd " + executable,
"ldd");
220 }
catch (std::filesystem::filesystem_error &) {
226 registerCommand(
"lscpu");
229 registerCommand(
"sensors");
232 registerEnvironmentVariablePrefix(
"OMP");
235 registerCommand(
"ompi_info");
236 registerEnvironmentVariablePrefix(
"OMPI");
239 registerCommand(
"mpichinfo");
240 registerEnvironmentVariablePrefix(
"MPICH");
243 registerEnvironmentVariablePrefix(
"CRAY");
246 registerCommand(
"module",
"module list 2>&1",
"module");
249 registerCommand(
"nvidia-smi",
"nvidia-smi --query",
"nvidia-smi");
250 registerEnvironmentVariablePrefix(
"CUDA");
253 registerCommand(
"rocm-smi",
"rocm-smi --showallinfo",
"rocm-smi");
256 registerCommand(
"sycl-ls",
"sycl-ls --verbose",
"sycl-ls");
259 for (
auto &prefix : {
"TEUCHOS",
"KOKKOS",
"TPETRA",
"STK"})
260 registerEnvironmentVariablePrefix(prefix);
263std::map<std::string, std::string> collectSystemInformation() {
265 std::map<std::string, std::string> data;
267 const std::string DATA_NOT_AVAILABLE =
"NOT AVAILABLE";
269 auto &commands = getCommandsMap();
270 for (
auto &command : commands) {
271 const bool isAvailable = commandIsAvailable(command.second.first);
273 data[command.first] = runCommandAndCaptureOutput(command.second.second);
275 data[command.first] = DATA_NOT_AVAILABLE;
279 auto &environmentVariablePrefixes = getEnvironmentVariablePrefixSet();
280 for (
auto &prefix : environmentVariablePrefixes) {
281 registerAllPrefixedVariables(prefix);
284 auto &environmentVariables = getEnvironmentVariablesSet();
285 for (
auto &envVariable : environmentVariables) {
286 const char *varVal = std::getenv(envVariable.c_str());
287 if (varVal ==
nullptr)
288 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.