https://mooseframework.inl.gov
Loading...
Searching...
No Matches
Capabilities.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10// Needs to be included before Capabilities.h, which
11// includes nlohmann/json_fwd.h
12#include "nlohmann/json.h"
13
14#include "Capabilities.h"
15#include "CapabilityException.h"
16#include "MooseUtils.h"
17#include "Conversion.h"
18
19#include <vector>
20
21#include "libmesh/libmesh_config.h"
22#include "petscconf.h"
23#include "petscpkg_version.h"
24
25#ifdef MOOSE_LIBTORCH_ENABLED
26#include <torch/version.h>
27#endif
28
29#if __has_include(<torch/xpu.h>)
30#include <torch/xpu.h>
31#define MOOSE_HAVE_XPU 1
32#endif
33
34#ifdef MOOSE_MFEM_ENABLED
35#include "mfem/config/config.hpp"
36#endif
37
38#ifdef LIBMESH_HAVE_NETGEN
39#include "netgen/netgen_version.hpp"
40#endif
41
42namespace Moose::internal
43{
44
46{
47 // Register the moose capabilities, just once
49}
50
53{
54 // We need a naked new here (_not_ a smart pointer or object instance) due to what seems like a
55 // bug in clang's static object destruction when using dynamic library loading.
56 static Capabilities * capability_registry = nullptr;
57 if (!capability_registry)
58 capability_registry = new Capabilities();
59 return *capability_registry;
60}
61
62std::string
64{
65 nlohmann::json root;
66 for (const auto & [name, capability] : _registry)
67 {
68 auto & entry = root[name];
69 std::visit([&entry](const auto & v) { entry["value"] = v; }, capability.getValue());
70 entry["doc"] = capability.getDoc();
71 if (const auto enumeration_ptr = capability.queryEnumeration())
72 entry["enumeration"] = *enumeration_ptr;
73 if (!capability.hasBoolValue())
74 entry["explicit"] = capability.getExplicit();
75 }
76 return root.dump(2);
77}
78
79void
80Capabilities::augment(const nlohmann::json & input, const Capabilities::AugmentPassKey)
81{
82 for (const auto & [name_json, entry] : input.items())
83 {
84 const std::string name = name_json;
85
86 const auto error = [&name](const std::string & message)
87 { throw CapabilityException("Capabilities::augment: Capability '" + name + "' " + message); };
88
89 std::string doc;
90 if (const auto it = entry.find("doc"); it != entry.end())
91 doc = *it;
92 else
93 error("missing 'doc' entry");
94
96 if (const auto it = entry.find("value"); it != entry.end())
97 {
98 if (it->is_boolean())
99 value = it->get<bool>();
100 else if (it->is_number_integer())
101 value = it->get<int>();
102 else
103 value = it->get<std::string>();
104 }
105 else
106 error("missing 'value' entry");
107
108 auto & capability = add(name, value, doc);
109
110 if (const auto it = entry.find("explicit"); it != entry.end() && it->get<bool>())
111 capability.setExplicit();
112
113 if (const auto it = entry.find("enumeration"); it != entry.end())
114 capability.setEnumeration(it->get<std::set<std::string>>());
115 }
116}
117
118bool
119Capabilities::isInstallationType(const std::string & installation_type) const
120{
121 const auto & capability = get("installation_type");
122 mooseAssert(capability.getEnumeration().count(installation_type), "Not a valid enumeration");
123 return capability.getStringValue() == installation_type;
124}
125
126void
128{
129 // helper lambdas for explicitly adding typed capabilities
130 const auto add_bool = [&](const std::string_view capability,
131 const bool value,
132 const std::string_view doc) -> Capability &
133 { return add(capability, value, doc); };
134 const auto add_int = [&](const std::string_view capability,
135 const int value,
136 const std::string_view doc) -> Capability &
137 { return add(capability, value, doc); };
138 const auto add_string = [&](const std::string_view capability,
139 const std::string_view value,
140 const std::string_view doc) -> Capability &
141 { return add(capability, std::string(value), doc); };
142
143 // helper lambdas for adding capabilities
144 const auto have = [&](const std::string & capability, const std::string & doc) -> Capability &
145 { return add_bool(capability, true, doc + " is available."); };
146 const auto missing = [&](const std::string & capability,
147 const std::string & doc,
148 const std::string & help = "") -> Capability &
149 { return add_bool(capability, false, doc + " is not available. " + help); };
150
151 const auto have_version = [&](const std::string & capability,
152 const std::string & doc,
153 const std::string & version) -> Capability &
154 { return add_string(capability, version, doc + " version " + version + " is available."); };
155 const auto petsc_missing = [&](const std::string & capability,
156 const std::string & doc) -> Capability &
157 {
158 return add_bool(
159 capability, false, doc + " is not available. Check your PETSc configure options.");
160 };
161 const auto libmesh_missing = [&](const std::string & capability,
162 const std::string & doc,
163 const std::string & config_option) -> Capability &
164 {
165 return add_bool(capability,
166 false,
167 doc + " is not available. It is controlled by the `" + config_option +
168 "` libMesh configure option.");
169 };
170
171 {
172 const auto doc = "LibTorch machine learning and parallel tensor algebra library";
173#ifdef MOOSE_LIBTORCH_ENABLED
174 add_string("libtorch", TORCH_VERSION, doc);
175#else
176 missing("libtorch",
177 doc,
178 "Check "
179 "https://mooseframework.inl.gov/moose/getting_started/installation/"
180 "install_libtorch.html for "
181 "instructions on how to configure and build moose with libTorch.");
182#endif
183 }
184
185 {
186 const auto doc = "MFEM finite element library";
187#ifdef MOOSE_MFEM_ENABLED
188 add_string("mfem", MFEM_VERSION_STRING, doc);
189#else
190 missing("mfem",
191 doc,
192 "Install mfem using the scripts/update_and_rebuild_mfem.sh script after "
193 "first running scripts/update_and_rebuild_conduit.sh. Finally, configure "
194 "moose with ./configure --with-mfem");
195#endif
196 }
197
198 {
199 const auto doc = "New Engineering Material model Library, version 2";
200#ifdef NEML2_ENABLED
201 have("neml2", doc);
202#else
203 missing("neml2",
204 doc,
205 "Install neml2 using the scripts/update_and_rebuild_neml2.sh script, then "
206 "configure moose with ./configure --with-neml2 --with-libtorch");
207#endif
208 }
209
210 {
211 const auto doc = "gperftools code performance analysis and profiling library";
212#ifdef HAVE_GPERFTOOLS
213 have("gperftools", doc);
214#else
215 missing("gperftools",
216 doc,
217 "Check https://mooseframework.inl.gov/application_development/profiling.html "
218 "for instructions on profiling MOOSE based applications.");
219#endif
220 }
221
222 {
223 const auto doc = "libPNG portable network graphics format library";
224#ifdef MOOSE_HAVE_LIBPNG
225 have("libpng", doc);
226#else
227 missing("libpng",
228 doc,
229 "Install libpng through conda or your distribution and check that it gets "
230 "detected through pkg-config, then reconfigure and rebuild MOOSE.");
231#endif
232 }
233
234 {
235 const auto doc = "NVIDIA GPU parallel computing platform";
236#ifdef PETSC_HAVE_CUDA
237 const std::string version = QUOTE(PETSC_PKG_CUDA_VERSION_MAJOR) "." QUOTE(
238 PETSC_PKG_CUDA_VERSION_MINOR) "." QUOTE(PETSC_PKG_CUDA_VERSION_SUBMINOR);
239 add_string("cuda", version, doc);
240#else
241 missing("cuda", doc, "Add the CUDA bin directory to your path and rebuild PETSc.");
242#endif
243 }
244
245 {
246 const auto doc = "AMD GPU parallel computing platform";
247#ifdef PETSC_HAVE_HIPROCM
248 const std::string version = QUOTE(PETSC_PKG_HIP_VERSION_MAJOR) "." QUOTE(
249 PETSC_PKG_HIP_VERSION_MINOR) "." QUOTE(PETSC_PKG_HIP_VERSION_SUBMINOR);
250 add_string("hip", version, doc);
251#else
252 missing("hip", doc, "Add the HIP bin directory to your path and rebuild PETSc.");
253#endif
254 }
255
256 {
257 const auto doc = "Intel GPU parallel computing platform";
258#ifdef PETSC_HAVE_SYCL
259 const std::string version = QUOTE(PETSC_PKG_SYCL_VERSION_MAJOR) "." QUOTE(
260 PETSC_PKG_SYCL_VERSION_MINOR) "." QUOTE(PETSC_PKG_SYCL_VERSION_SUBMINOR);
261 add_string("sycl", version, doc);
262#else
263 missing("sycl", doc, "Add the SYCL bin directory to your path and rebuild PETSc.");
264#endif
265 }
266
267 {
268 const auto doc = "Kokkos performance portability programming ecosystem";
269#ifdef MOOSE_KOKKOS_ENABLED
270 const std::string version = QUOTE(PETSC_PKG_KOKKOS_VERSION_MAJOR) "." QUOTE(
271 PETSC_PKG_KOKKOS_VERSION_MINOR) "." QUOTE(PETSC_PKG_KOKKOS_VERSION_SUBMINOR);
272 add_string("kokkos", version, doc);
273#else
274 missing("kokkos",
275 doc,
276 "Rebuild PETSc with Kokkos support and libMesh. Then, reconfigure MOOSE with "
277 "--with-kokkos.");
278#endif
279 }
280
281 {
282 const auto doc = "Kokkos support for PETSc";
283#ifdef PETSC_HAVE_KOKKOS
284 const std::string version = QUOTE(PETSC_PKG_KOKKOS_VERSION_MAJOR) "." QUOTE(
285 PETSC_PKG_KOKKOS_VERSION_MINOR) "." QUOTE(PETSC_PKG_KOKKOS_VERSION_SUBMINOR);
286 add_string("petsc_kokkos", version, doc);
287#else
288 missing(
289 "petsc_kokkos", doc, "Rebuild PETSc with Kokkos support, then rebuild libMesh and MOOSE.");
290#endif
291 }
292
293 {
294 const auto doc = "Intel OneAPI XPU accelerator support";
295#ifdef MOOSE_HAVE_XPU
296 if (torch::xpu::is_available())
297 have("xpu", doc);
298 else
299 missing("xpu", doc, "No usable XPU devices have been found.");
300#else
301 missing("xpu", doc, "The torch version used to build this app has no XPU support.");
302#endif
303 }
304
305 add_int(
306 "ad_size",
307 MOOSE_AD_MAX_DOFS_PER_ELEM,
308 "MOOSE was configured and built with a dual number backing store size of " +
309 Moose::stringify(MOOSE_AD_MAX_DOFS_PER_ELEM) +
310 ". Complex simulations with many variables or contact problems may require larger "
311 "values. Reconfigure MOOSE with the --with-derivative-size=<n> option in the root of the "
312 "repository.")
313 .setExplicit();
314
315 {
316 const std::string method = QUOTE(METHOD);
317 add_string("method", method, "The executable was built with METHOD=\"" + method + "\"")
318 .setExplicit()
319 .setEnumeration({"dbg", "devel", "oprof", "opt"});
320 }
321
322 {
323 const std::string version = QUOTE(LIBMESH_DETECTED_PETSC_VERSION_MAJOR) "." QUOTE(
324 LIBMESH_DETECTED_PETSC_VERSION_MINOR) "." QUOTE(LIBMESH_DETECTED_PETSC_VERSION_SUBMINOR);
325 add_string("petsc", version, "Using PETSc version " + version + ".");
326 }
327
328#ifdef LIBMESH_PETSC_USE_DEBUG
329 add_bool("petsc_debug", true, "PETSc was built with debugging options.");
330#else
331 add_bool("petsc_debug", false, "PETSc was built without debugging options.");
332#endif
333
334 {
335 const auto doc = "SuperLU direct solver";
336#ifdef LIBMESH_PETSC_HAVE_SUPERLU_DIST
337 const std::string version = QUOTE(PETSC_PKG_SUPERLU_DIST_VERSION_MAJOR) "." QUOTE(
338 PETSC_PKG_SUPERLU_DIST_VERSION_MINOR) "." QUOTE(PETSC_PKG_SUPERLU_DIST_VERSION_SUBMINOR);
339 add_string("superlu", version, doc);
340#else
341 petsc_missing("superlu", doc);
342#endif
343 }
344
345 {
346 const auto doc = "MUltifrontal Massively Parallel sparse direct Solver (MUMPS)";
347#ifdef LIBMESH_PETSC_HAVE_MUMPS
348 const std::string version = QUOTE(PETSC_PKG_MUMPS_VERSION_MAJOR) "." QUOTE(
349 PETSC_PKG_MUMPS_VERSION_MINOR) "." QUOTE(PETSC_PKG_MUMPS_VERSION_SUBMINOR);
350 add_string("mumps", version, doc);
351#else
352 petsc_missing("mumps", doc);
353#endif
354 }
355
356 {
357 const auto doc = "STRUMPACK - STRUctured Matrix PACKage solver library";
358#ifdef LIBMESH_PETSC_HAVE_STRUMPACK
359 const std::string version = QUOTE(PETSC_PKG_STRUMPACK_VERSION_MAJOR) "." QUOTE(
360 PETSC_PKG_STRUMPACK_VERSION_MINOR) "." QUOTE(PETSC_PKG_STRUMPACK_VERSION_SUBMINOR);
361 add_string("strumpack", version, doc);
362#else
363 petsc_missing("strumpack", doc);
364#endif
365 }
366
367 {
368 const auto doc = "Parmetis partitioning library";
369#if defined(LIBMESH_PETSC_HAVE_PARMETIS)
370 const std::string version = QUOTE(PETSC_PKG_PARMETIS_VERSION_MAJOR) "." QUOTE(
371 PETSC_PKG_PARMETIS_VERSION_MINOR) "." QUOTE(PETSC_PKG_PARMETIS_VERSION_SUBMINOR);
372 add_string("parmetis", version, doc);
373#elif defined(LIBMESH_HAVE_PARMETIS)
374 have("parmetis", doc);
375#else
376 petsc_missing("parmetis", doc);
377#endif
378 }
379
380 {
381 const auto doc = "Chaco graph partitioning library";
382#ifdef LIBMESH_PETSC_HAVE_CHACO
383 have("chaco", doc);
384#else
385 petsc_missing("chaco", doc);
386#endif
387 }
388
389 {
390 const auto doc = "Party matrix or graph partitioning library";
391#ifdef LIBMESH_PETSC_HAVE_PARTY
392 have("party", doc);
393#else
394 petsc_missing("party", doc);
395#endif
396 }
397
398 {
399 const auto doc = "PT-Scotch graph partitioning library";
400#ifdef LIBMESH_PETSC_HAVE_PTSCOTCH
401 const std::string version = QUOTE(PETSC_PKG_PTSCOTCH_VERSION_MAJOR) "." QUOTE(
402 PETSC_PKG_PTSCOTCH_VERSION_MINOR) "." QUOTE(PETSC_PKG_PTSCOTCH_VERSION_SUBMINOR);
403 add_string("ptscotch", version, doc);
404#else
405 petsc_missing("ptscotch", doc);
406#endif
407 }
408
409 {
410 const auto doc = "Optimized BLAS library";
411#ifdef PETSC_HAVE_OPENBLAS
412 const std::string version = QUOTE(PETSC_PKG_OPENBLAS_VERSION_MAJOR) "." QUOTE(
413 PETSC_PKG_OPENBLAS_VERSION_MINOR) "." QUOTE(PETSC_PKG_OPENBLAS_VERSION_SUBMINOR);
414 add_string("openblas", version, doc);
415#else
416 petsc_missing("openblas", doc);
417#endif
418 }
419
420 {
421 const auto doc = "Umpire resource management library";
422#ifdef PETSC_HAVE_UMPIRE
423 have("umpire", doc);
424#else
425 petsc_missing("umpire", doc);
426#endif
427 }
428
429 {
430 const auto doc = "Scalable Library for Eigenvalue Problem Computations (SLEPc)";
431#ifdef LIBMESH_HAVE_SLEPC
432 const auto version = QUOTE(LIBMESH_DETECTED_SLEPC_VERSION_MAJOR) "." QUOTE(
433 LIBMESH_DETECTED_SLEPC_VERSION_MINOR) "." QUOTE(LIBMESH_DETECTED_SLEPC_VERSION_SUBMINOR);
434 have_version("slepc", doc, version);
435#else
436 petsc_missing("slepc", doc);
437#endif
438 }
439
440 {
441 const auto doc = "Exodus mesh file format library";
442#ifdef LIBMESH_HAVE_EXODUS_API
443 const std::string version = QUOTE(LIBMESH_DETECTED_EXODUS_VERSION_MAJOR) "." QUOTE(
444 LIBMESH_DETECTED_EXODUS_VERSION_MINOR);
445 have_version("exodus", doc, version);
446#else
447 libmesh_missing("exodus", doc, "--enable-exodus");
448#endif
449 }
450
451 {
452 const auto doc = "Netgen meshing library";
453#ifdef LIBMESH_HAVE_NETGEN
454 const std::string version =
455 QUOTE(NETGEN_VERSION_MAJOR) "." QUOTE(NETGEN_VERSION_MINOR) "." QUOTE(NETGEN_VERSION_PATCH);
456 add_string("netgen", version, doc);
457#else
458 libmesh_missing("netgen", doc, "--enable-netgen");
459#endif
460 }
461
462 {
463 const auto doc = "Visualization Toolkit (VTK)";
464#ifdef LIBMESH_HAVE_VTK
465 const std::string version = QUOTE(LIBMESH_DETECTED_VTK_VERSION_MAJOR) "." QUOTE(
466 LIBMESH_DETECTED_VTK_VERSION_MINOR) "." QUOTE(LIBMESH_DETECTED_VTK_VERSION_SUBMINOR);
467 have_version("vtk", doc, version);
468#else
469 libmesh_missing("vtk", doc, "--disable-vtk and --enable-vtk-required");
470#endif
471 }
472
473 {
474 const auto doc = "libcurl - the multiprotocol file transfer library";
475#ifdef LIBMESH_HAVE_CURL
476 have("curl", doc);
477#else
478 libmesh_missing("curl", doc, "--enable-curl");
479#endif
480 }
481
482 {
483 const auto doc = "Tecplot post-processing tools API";
484#ifdef LIBMESH_HAVE_TECPLOT_API
485 have("tecplot", doc);
486#else
487 libmesh_missing("tecplot", doc, "--enable-tecplot");
488#endif
489 }
490
491 {
492 const auto doc = "NVIDIA Tools Extension Library API";
493#ifdef LIBMESH_HAVE_NVTX_API
494 have("nvtx_api", doc);
495#else
496 libmesh_missing("nvtx_api", doc, "--with-nvtx");
497#endif
498 }
499
500 {
501 const auto doc = "libMesh performance logging";
502#ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
503 have("libmesh_perflog", doc);
504#else
505 libmesh_missing("libmesh_perflog", doc, "--enable-perflog");
506#endif
507 }
508
509 {
510 const auto doc = "Boost C++ library";
511#ifdef LIBMESH_HAVE_EXTERNAL_BOOST
512 have("boost", doc);
513#else
514 libmesh_missing("boost", doc, "--with-boost");
515#endif
516 }
517
518 // libmesh stuff
519 {
520 const auto doc = "Adaptive mesh refinement";
521#ifdef LIBMESH_ENABLE_AMR
522 have("amr", doc);
523#else
524 libmesh_missing("amr", doc, "--disable-amr");
525#endif
526 }
527
528 {
529 const auto doc = "nanoflann library for Nearest Neighbor (NN) search with KD-trees";
530#ifdef LIBMESH_HAVE_NANOFLANN
531 have("nanoflann", doc);
532#else
533 libmesh_missing("nanoflann", doc, "--disable-nanoflann");
534#endif
535 }
536
537 {
538 const auto doc = "sfcurves library for space filling curves (required by geometric "
539 "partitioners such as SFCurves, Hilbert and Morton - not LGPL compatible)";
540#ifdef LIBMESH_HAVE_SFCURVES
541 have("sfcurves", doc);
542#else
543 libmesh_missing("sfcurves", doc, "--disable-sfc");
544#endif
545 }
546
547 {
548#ifdef LIBMESH_HAVE_FPARSER
549#ifdef LIBMESH_HAVE_FPARSER_JIT
550 const auto value = "jit";
551 const auto doc = "FParser enabled with just in time compilation support.";
552#else
553 const auto value = "byte_code";
554 const auto doc = "FParser enabled.";
555#endif
556 add_string("fparser", value, doc);
557#else
558 add_bool("fparser",
559 false,
560 "FParser is disabled, libMesh was likely configured with --disable-fparser.");
561#endif
562 }
563
564#ifdef LIBMESH_HAVE_DLOPEN
565 add_bool("dlopen", true, "The dlopen() system call is available to dynamically load libraries.");
566#else
567 add_bool("dlopen",
568 false,
569 "The dlopen() system call is not available. Dynamic library loading is "
570 "not supported on this system.");
571#endif
572
573 {
574 const auto doc = "LibMesh support for threaded execution";
575#ifdef LIBMESH_USING_THREADS
576 have("threads", doc);
577#else
578 libmesh_missing("threads", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
579#endif
580 }
581
582 {
583 const auto doc = "OpenMP multi-platform shared-memory parallel programming API";
584#ifdef LIBMESH_HAVE_OPENMP
585 have("openmp", doc);
586#else
587 libmesh_missing("openmp", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
588#endif
589 }
590 {
591 const auto doc = "POSIX Threads API";
592#ifdef LIBMESH_HAVE_PTHREAD
593 have("pthread", doc);
594#else
595 libmesh_missing("pthread", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
596#endif
597 }
598 {
599 const auto doc = "oneAPI Threading Building Blocks (TBB) API";
600#ifdef LIBMESH_HAVE_TBB_API
601 have("tbb", doc);
602#else
603 libmesh_missing("tbb", doc, "--with-thread-model=tbb,pthread,openmp,auto,none");
604#endif
605 }
606
607 {
608 const auto doc = "libMesh unique ID support";
609#ifdef LIBMESH_ENABLE_UNIQUE_ID
610 have("unique_id", doc);
611#else
612 libmesh_missing("unique_id", doc, "--enable-unique-id");
613#endif
614 }
615
616 {
617#ifdef LIBMESH_ENABLE_PARMESH
618 const auto value = "distributed";
619#else
620 const auto value = "replicated";
621#endif
622 add_string("mesh_mode", value, "libMesh default mesh mode")
623 .setExplicit()
624 .setEnumeration({"distributed", "replicated"});
625 }
626
627 add_int("dof_id_bytes",
628 static_cast<int>(sizeof(dof_id_type)),
629 "Degree of freedom (DOF) identifiers use " + Moose::stringify(sizeof(dof_id_type)) +
630 " bytes for storage. This is controlled by the "
631 "--with-dof-id-bytes=<1|2|4|8> libMesh configure option.")
632 .setExplicit();
633
634 {
635#ifdef LIBMESH_HAVE_STATIC_LIBS
636 const auto value = "static";
637#else
638 const auto value = "dynamic";
639#endif
640 add_string("library_mode",
641 value,
642 "The libMesh library mode. This is controlled by the --enable-static libMesh "
643 "configure option.")
644 .setExplicit()
645 .setEnumeration({"dynamic", "static"});
646 }
647
648 // compiler
649 {
650 const auto doc = "Compiler used to build the MOOSE framework.";
651#if defined(__INTEL_LLVM_COMPILER)
652 const auto value = "intel";
653#elif defined(__clang__)
654 const auto value = "clang";
655#elif defined(__GNUC__) || defined(__GNUG__)
656 const auto value = "gcc";
657#elif defined(_MSC_VER)
658 const auto value = "msvc";
659#else
660 mooseDoOnce(mooseWarning("Failed to determine compiler; setting capability compiler=unknown"));
661 const auto value = "unknown";
662#endif
663 add_string("compiler", value, doc)
664 .setExplicit()
665 .setEnumeration({"clang", "gcc", "intel", "msvc", "unknown"});
666 }
667
668 // OS related
669 {
670#ifdef __APPLE__
671 const auto value = "darwin";
672#elif __WIN32__
673 const auto value = "win32";
674#elif __linux__
675 const auto value = "linux";
676#elif __unix__
677 const auto value = "unix";
678#else
679 mooseDoOnce(mooseWarning("Failed to determine platform; setting capability platform=unknown"));
680 const auto value = "unknown";
681#endif
682 add_string("platform", value, "Operating system this executable is running on.")
683 .setExplicit()
684 .setEnumeration({"darwin", "linux", "unix", "unknown", "win32"});
685 }
686
687 // Installation type (in tree or installed)
688 {
689 // Try to find the path to the running executable
690 std::optional<std::string> executable_path;
691 {
692 Moose::ScopedThrowOnError scoped_throw_on_error;
693 try
694 {
695 executable_path = Moose::getExec();
696 }
697 catch (const MooseException &)
698 {
699 }
700 }
701
702 std::string value = "unknown";
703
704 if (executable_path)
705 {
706 // Try to follow all symlinks to get the real path
707 std::error_code ec;
708 const auto resolved_path =
709 std::filesystem::weakly_canonical(std::filesystem::path(*executable_path), ec);
710 if (ec)
711 mooseDoOnce(mooseWarning("Failed to resolve executable path '",
712 *executable_path,
713 "':\n",
714 ec.message(),
715 "\n\nSetting capability installation_type=unknown"));
716 else
717 {
718 // If the binary is in a folder "bin", we'll consider it installed.
719 // This isn't the best check, but it works with how we currently
720 // install applications in app.mk
721 value = resolved_path.parent_path().filename() == "bin" ? "relocated" : "in_tree";
722 }
723 }
724 else
725 mooseDoOnce(mooseWarning(
726 "Failed to determine executable path; setting capability installation_type=unknown"));
727
728 add_string("installation_type", value, "The installation type of the application.")
729 .setExplicit()
730 .setEnumeration({"in_tree", "relocated", "unknown"});
731
732 mooseAssert(isInstallationType(value), "Value mismatch");
733 }
734}
735
736} // namespace Moose
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
std::string help
Provides a way for users to bail out of the current solve.
Common execption to be thrown when interacting with capabilities.
An entry for a single capability.
Definition Capability.h:30
std::variant< bool, int, std::string > Value
A capability can have a bool, int, or string value.
Definition Capability.h:33
Scoped helper for setting Moose::_throw_on_error during this scope.
Definition Moose.h:298
Holds the public (to MooseApp) facing CapabilityRegistry for storing and checking capabilities.
static Capabilities & getCapabilities(const GetCapabilitiesPassKey)
Get the singleton Capabilities.
std::string dump() const
create a JSON dump of the capabilities registry
void registerMooseCapabilities()
Register the MOOSE capabilities.
void augment(const nlohmann::json &input, const AugmentPassKey)
Augment the capabilities with the given input capabilities.
bool isInstallationType(const std::string &installation_type) const
Helper for isRelocated() and isInTree()
Registry of capabilities that checks capability requirements.
RegistryType _registry
Registry storage.
Capability & add(const std::string_view name, const Moose::Capability::Value &value, const std::string_view doc)
Add a capability.
const Capability & get(const std::string &capability) const
Get a capability.
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64
std::string getExec()
Gets the full path to the running executable on Mac OS X and linux.