builtin-check.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include "builtin.h"
  3. #include "color.h"
  4. #include "util/debug.h"
  5. #include "util/header.h"
  6. #include <tools/config.h>
  7. #include <stdbool.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <subcmd/parse-options.h>
  11. static const char * const check_subcommands[] = { "feature", NULL };
  12. static struct option check_options[] = {
  13. OPT_BOOLEAN('q', "quiet", &quiet, "do not show any warnings or messages"),
  14. OPT_END()
  15. };
  16. static struct option check_feature_options[] = { OPT_PARENT(check_options) };
  17. static const char *check_usage[] = { NULL, NULL };
  18. static const char *check_feature_usage[] = {
  19. "perf check feature <feature_list>",
  20. NULL
  21. };
  22. struct feature_status supported_features[] = {
  23. FEATURE_STATUS("aio", HAVE_AIO_SUPPORT),
  24. FEATURE_STATUS("bpf", HAVE_LIBBPF_SUPPORT),
  25. FEATURE_STATUS("bpf_skeletons", HAVE_BPF_SKEL),
  26. FEATURE_STATUS("debuginfod", HAVE_DEBUGINFOD_SUPPORT),
  27. FEATURE_STATUS("dwarf", HAVE_DWARF_SUPPORT),
  28. FEATURE_STATUS("dwarf_getlocations", HAVE_DWARF_GETLOCATIONS_SUPPORT),
  29. FEATURE_STATUS("dwarf-unwind", HAVE_DWARF_UNWIND_SUPPORT),
  30. FEATURE_STATUS("auxtrace", HAVE_AUXTRACE_SUPPORT),
  31. FEATURE_STATUS("libaudit", HAVE_LIBAUDIT_SUPPORT),
  32. FEATURE_STATUS("libbfd", HAVE_LIBBFD_SUPPORT),
  33. FEATURE_STATUS("libcapstone", HAVE_LIBCAPSTONE_SUPPORT),
  34. FEATURE_STATUS("libcrypto", HAVE_LIBCRYPTO_SUPPORT),
  35. FEATURE_STATUS("libdw-dwarf-unwind", HAVE_DWARF_SUPPORT),
  36. FEATURE_STATUS("libelf", HAVE_LIBELF_SUPPORT),
  37. FEATURE_STATUS("libnuma", HAVE_LIBNUMA_SUPPORT),
  38. FEATURE_STATUS("libopencsd", HAVE_CSTRACE_SUPPORT),
  39. FEATURE_STATUS("libperl", HAVE_LIBPERL_SUPPORT),
  40. FEATURE_STATUS("libpfm4", HAVE_LIBPFM),
  41. FEATURE_STATUS("libpython", HAVE_LIBPYTHON_SUPPORT),
  42. FEATURE_STATUS("libslang", HAVE_SLANG_SUPPORT),
  43. FEATURE_STATUS("libtraceevent", HAVE_LIBTRACEEVENT),
  44. FEATURE_STATUS("libunwind", HAVE_LIBUNWIND_SUPPORT),
  45. FEATURE_STATUS("lzma", HAVE_LZMA_SUPPORT),
  46. FEATURE_STATUS("numa_num_possible_cpus", HAVE_LIBNUMA_SUPPORT),
  47. FEATURE_STATUS("syscall_table", HAVE_SYSCALL_TABLE_SUPPORT),
  48. FEATURE_STATUS("zlib", HAVE_ZLIB_SUPPORT),
  49. FEATURE_STATUS("zstd", HAVE_ZSTD_SUPPORT),
  50. /* this should remain at end, to know the array end */
  51. FEATURE_STATUS(NULL, _)
  52. };
  53. static void on_off_print(const char *status)
  54. {
  55. printf("[ ");
  56. if (!strcmp(status, "OFF"))
  57. color_fprintf(stdout, PERF_COLOR_RED, "%-3s", status);
  58. else
  59. color_fprintf(stdout, PERF_COLOR_GREEN, "%-3s", status);
  60. printf(" ]");
  61. }
  62. /* Helper function to print status of a feature along with name/macro */
  63. static void status_print(const char *name, const char *macro,
  64. const char *status)
  65. {
  66. printf("%22s: ", name);
  67. on_off_print(status);
  68. printf(" # %s\n", macro);
  69. }
  70. #define STATUS(feature) \
  71. do { \
  72. if (feature.is_builtin) \
  73. status_print(feature.name, feature.macro, "on"); \
  74. else \
  75. status_print(feature.name, feature.macro, "OFF"); \
  76. } while (0)
  77. /**
  78. * check whether "feature" is built-in with perf
  79. *
  80. * returns:
  81. * 0: NOT built-in or Feature not known
  82. * 1: Built-in
  83. */
  84. static int has_support(const char *feature)
  85. {
  86. for (int i = 0; supported_features[i].name; ++i) {
  87. if ((strcasecmp(feature, supported_features[i].name) == 0) ||
  88. (strcasecmp(feature, supported_features[i].macro) == 0)) {
  89. if (!quiet)
  90. STATUS(supported_features[i]);
  91. return supported_features[i].is_builtin;
  92. }
  93. }
  94. if (!quiet)
  95. pr_err("Unknown feature '%s', please use 'perf version --build-options' to see which ones are available.\n", feature);
  96. return 0;
  97. }
  98. /**
  99. * Usage: 'perf check feature <feature_list>'
  100. *
  101. * <feature_list> can be a single feature name/macro, or a comma-separated list
  102. * of feature names/macros
  103. * eg. argument can be "libtraceevent" or "libtraceevent,bpf" etc
  104. *
  105. * In case of a comma-separated list, feature_enabled will be 1, only if
  106. * all features passed in the string are supported
  107. *
  108. * Note that argv will get modified
  109. */
  110. static int subcommand_feature(int argc, const char **argv)
  111. {
  112. char *feature_list;
  113. char *feature_name;
  114. int feature_enabled;
  115. argc = parse_options(argc, argv, check_feature_options,
  116. check_feature_usage, 0);
  117. if (!argc)
  118. usage_with_options(check_feature_usage, check_feature_options);
  119. if (argc > 1) {
  120. pr_err("Too many arguments passed to 'perf check feature'\n");
  121. return -1;
  122. }
  123. feature_enabled = 1;
  124. /* feature_list is a non-const copy of 'argv[0]' */
  125. feature_list = strdup(argv[0]);
  126. if (!feature_list) {
  127. pr_err("ERROR: failed to allocate memory for feature list\n");
  128. return -1;
  129. }
  130. feature_name = strtok(feature_list, ",");
  131. while (feature_name) {
  132. feature_enabled &= has_support(feature_name);
  133. feature_name = strtok(NULL, ",");
  134. }
  135. free(feature_list);
  136. return !feature_enabled;
  137. }
  138. int cmd_check(int argc, const char **argv)
  139. {
  140. argc = parse_options_subcommand(argc, argv, check_options,
  141. check_subcommands, check_usage, 0);
  142. if (!argc)
  143. usage_with_options(check_usage, check_options);
  144. if (strcmp(argv[0], "feature") == 0)
  145. return subcommand_feature(argc, argv);
  146. /* If no subcommand matched above, print usage help */
  147. pr_err("Unknown subcommand: %s\n", argv[0]);
  148. usage_with_options(check_usage, check_options);
  149. /* free usage string allocated by parse_options_subcommand */
  150. free((void *)check_usage[0]);
  151. return 0;
  152. }