11#include "Teuchos_EnvVariables.hpp"
15#if !defined(__GNUC__) || (__GNUC__ >= 10)
23#if not(defined(WIN) && (_MSC_VER >= 1900))
29FILE *popen(
const char *command,
const char *mode)
30{
return _popen(command, mode); }
32int pclose(FILE *stream)
33{
return _pclose(stream);}
36namespace Teuchos::SystemInformation {
40std::map<std::string, std::pair<std::string, std::string>>& getCommandsMap() {
41 static std::map<std::string, std::pair<std::string, std::string>> commands;
45std::set<std::string>& getEnvironmentVariablesSet() {
46 static std::set<std::string> environmentVariables;
47 return environmentVariables;
50std::set<std::string>& getEnvironmentVariablePrefixSet() {
51 static std::set<std::string> environmentVariablePrefixes;
52 return environmentVariablePrefixes;
58bool commandIsAvailable(
const std::string &command) {
60 std::string(
"command -v " + command +
" > /dev/null 2>&1").c_str());
63std::string runCommandAndCaptureOutput(
const std::string &command) {
65 std::string result =
"";
66 FILE *pipe = popen(command.c_str(),
"r");
68 return "command \"" + command +
"\"failed";
70 while (fgets(buffer,
sizeof buffer, pipe) != NULL) {
75 return "command \"" + command +
"\"failed";
82registerEnvironmentVariable(
const std::string &variableName) {
83 auto &environmentVariables = getEnvironmentVariablesSet();
85 if (
auto search = environmentVariables.find(variableName);
86 search != environmentVariables.end()) {
88 return ALREADY_PRESENT;
91 environmentVariables.insert(variableName);
96void registerAllPrefixedVariables(
const std::string &prefix) {
98#if defined(WIN) && (_MSC_VER >= 1900)
99 env = *__p__environ();
103 for (; *env; ++env) {
108 if (substrings.size() > 0) {
109 std::string name = substrings[0];
111 if (name.size() >= prefix.size() &&
112 name.substr(0, prefix.size()) == prefix) {
113 Teuchos::SystemInformation::registerEnvironmentVariable(name);
120registerEnvironmentVariablePrefix(
const std::string &prefix) {
121 auto &environmentVariablePrefixes = getEnvironmentVariablePrefixSet();
122 if (
auto search = environmentVariablePrefixes.find(prefix);
123 search != environmentVariablePrefixes.end()) {
125 return ALREADY_PRESENT;
128 environmentVariablePrefixes.insert(prefix);
135registerCommand(
const std::string &commandLabel,
136 const std::string &commandToRunAndCapture,
137 const std::string &commandToCheckForExistence) {
138 auto &commands = getCommandsMap();
140 std::string myCommandToRunAndCapture = commandToRunAndCapture;
141 if (myCommandToRunAndCapture.empty())
142 myCommandToRunAndCapture = commandLabel;
144 std::string myCommandToCheckForExistence = commandToCheckForExistence;
145 if (myCommandToCheckForExistence.empty())
146 myCommandToCheckForExistence = myCommandToRunAndCapture;
148 if (
auto search = commands.find(commandLabel); search != commands.end()) {
149 if ((commands[commandLabel].first == myCommandToCheckForExistence) &&
150 (commands[commandLabel].second == myCommandToRunAndCapture))
151 return ALREADY_PRESENT;
154 <<
"Teuchos::SystemInformation: Attempted to register a command (\""
155 << commandLabel <<
"\", \"" << myCommandToRunAndCapture <<
"\", \""
156 << myCommandToCheckForExistence <<
"\") "
157 <<
"that clashes with already registered command: (" << commandLabel
158 <<
"\", \"" << commands[commandLabel].first <<
"\", \""
159 << commands[commandLabel].second <<
"\")." << std::endl;
164 commands[commandLabel] = {myCommandToCheckForExistence, myCommandToRunAndCapture};
169void initializeCollection() {
171 std::string userProvidedEnvVariables =
173 "TEUCHOS_USER_ENVIRONMENT_VARIABLES",
"");
174 if (!userProvidedEnvVariables.empty()) {
176 bool isValid = (strings.size() >= 1);
179 <<
"Teuchos::SystemInformation: The value of the environment "
181 "TEUCHOS_USER_ENVIRONMENT_VARIABLES needs to be a semi-colon "
182 "seperated string. Value: "
183 << userProvidedEnvVariables << std::endl;
184 for (
int itemNo = 0; itemNo < strings.size(); ++itemNo) {
185 std::string &variableName = strings[itemNo];
186 if (registerEnvironmentVariable(variableName) == FAILURE)
190 !isValid, std::runtime_error,
191 "Teuchos::SystemInformation: Invalid environment variable "
192 "TEUCHOS_USER_ENVIRONMENT_VARIABLES");
195 std::string userProvidedCommands =
197 if (!userProvidedCommands.empty()) {
199 bool isValid = (strings.size() % 3 == 0) && (strings.size() >= 3);
201 std::cerr <<
"Teuchos::SystemInformation: The value of the environment "
202 "variable TEUCHOS_USER_COMMANDS "
203 "needs to be a semi-colon seperated string with a number of "
204 "elements that is a multiple of 3. Value: "
205 << userProvidedCommands << std::endl;
207 while (isValid && (3 * tupleNo + 2 < strings.size())) {
208 std::string &commandLabel = strings[3 * tupleNo];
209 std::string &commandToRunAndCapture = strings[3 * tupleNo + 1];
210 std::string &commandToCheckForExistence = strings[3 * tupleNo + 2];
211 if (registerCommand(commandLabel, commandToRunAndCapture,
212 commandToCheckForExistence) == FAILURE) {
218 "Teuchos::SystemInformation: Invalid "
219 "environment variable TEUCHOS_USER_COMMANDS");
222#if !defined(__GNUC__) || (__GNUC__ >= 10)
224 const std::string executable = std::filesystem::canonical(
"/proc/self/exe").string();
225 if (!executable.empty()) {
226 registerCommand(
"ldd",
"ldd " + executable,
"ldd");
228 }
catch (std::filesystem::filesystem_error &) {
234 registerCommand(
"lscpu");
237 registerCommand(
"sensors");
240 registerEnvironmentVariablePrefix(
"OMP");
243 registerCommand(
"ompi_info");
244 registerEnvironmentVariablePrefix(
"OMPI");
247 registerCommand(
"mpichinfo");
248 registerEnvironmentVariablePrefix(
"MPICH");
251 registerEnvironmentVariablePrefix(
"CRAY");
254 registerCommand(
"module",
"module list 2>&1",
"module");
257 registerCommand(
"nvidia-smi",
"nvidia-smi --query",
"nvidia-smi");
258 registerEnvironmentVariablePrefix(
"CUDA");
261 registerCommand(
"rocm-smi",
"rocm-smi --showallinfo",
"rocm-smi");
264 registerCommand(
"sycl-ls",
"sycl-ls --verbose",
"sycl-ls");
267 for (
auto &prefix : {
"TEUCHOS",
"KOKKOS",
"TPETRA",
"STK"})
268 registerEnvironmentVariablePrefix(prefix);
271std::map<std::string, std::string> collectSystemInformation() {
273 std::map<std::string, std::string> data;
275 const std::string DATA_NOT_AVAILABLE =
"NOT AVAILABLE";
277 auto &commands = getCommandsMap();
278 for (
auto &command : commands) {
279 const bool isAvailable = commandIsAvailable(command.second.first);
281 data[command.first] = runCommandAndCaptureOutput(command.second.second);
283 data[command.first] = DATA_NOT_AVAILABLE;
287 auto &environmentVariablePrefixes = getEnvironmentVariablePrefixSet();
288 for (
auto &prefix : environmentVariablePrefixes) {
289 registerAllPrefixedVariables(prefix);
292 auto &environmentVariables = getEnvironmentVariablesSet();
293 for (
auto &envVariable : environmentVariables) {
294 const char *varVal = std::getenv(envVariable.c_str());
295 if (varVal ==
nullptr)
296 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.