pvsstudio.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import atexit
  2. import multiprocessing
  3. import subprocess
  4. import sys
  5. import webbrowser
  6. from SCons.Action import Action
  7. from SCons.Builder import Builder
  8. from SCons.Script import Delete, Flatten, GetBuildFailures, Mkdir
  9. __no_browser = False
  10. def _set_browser_action(target, source, env):
  11. if env["PVSNOBROWSER"]:
  12. global __no_browser
  13. __no_browser = True
  14. def emit_pvsreport(target, source, env):
  15. target_dir = env["REPORT_DIR"]
  16. if env["PLATFORM"] == "win32":
  17. # Report generator on Windows emits to a subfolder of given output folder
  18. target_dir = target_dir.Dir("fullhtml")
  19. return [target_dir.File("index.html")], source
  20. def atexist_handler():
  21. global __no_browser
  22. if __no_browser:
  23. return
  24. for bf in GetBuildFailures():
  25. for node in Flatten(bf.node):
  26. if node.exists and node.name.endswith(".html"):
  27. # macOS
  28. if sys.platform == "darwin":
  29. subprocess.run(["open", node.abspath])
  30. else:
  31. webbrowser.open(node.abspath)
  32. break
  33. def generate(env):
  34. env.SetDefault(
  35. PVSNCORES=multiprocessing.cpu_count(),
  36. PVSOPTIONS=[
  37. "@.pvsoptions",
  38. "-j${PVSNCORES}",
  39. # "--incremental", # kinda broken on PVS side
  40. ],
  41. PVSCONVOPTIONS=[
  42. "-a",
  43. "GA:1,2,3",
  44. "-t",
  45. "fullhtml",
  46. "--indicate-warnings",
  47. ],
  48. )
  49. if env["PLATFORM"] == "win32":
  50. env.SetDefault(
  51. PVSCHECKBIN="CompilerCommandsAnalyzer.exe",
  52. PVSCONVBIN="PlogConverter.exe",
  53. )
  54. else:
  55. env.SetDefault(
  56. PVSCHECKBIN="pvs-studio-analyzer",
  57. PVSCONVBIN="plog-converter",
  58. )
  59. if not env["VERBOSE"]:
  60. env.SetDefault(
  61. PVSCHECKCOMSTR="\tPVS\t${TARGET}",
  62. PVSCONVCOMSTR="\tPVSREP\t${TARGET}",
  63. )
  64. env.Append(
  65. BUILDERS={
  66. "PVSCheck": Builder(
  67. action=Action(
  68. '${PVSCHECKBIN} analyze ${PVSOPTIONS} -f "${SOURCE}" -o "${TARGET}"',
  69. "${PVSCHECKCOMSTR}",
  70. ),
  71. suffix=".log",
  72. src_suffix=".json",
  73. ),
  74. "PVSReport": Builder(
  75. action=Action(
  76. [
  77. Delete("${TARGET.dir}"),
  78. # PlogConverter.exe and plog-converter have different behavior
  79. Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None,
  80. Action(_set_browser_action, None),
  81. '${PVSCONVBIN} ${PVSCONVOPTIONS} "${SOURCE}" -o "${REPORT_DIR}"',
  82. ],
  83. "${PVSCONVCOMSTR}",
  84. ),
  85. emitter=emit_pvsreport,
  86. src_suffix=".log",
  87. ),
  88. }
  89. )
  90. atexit.register(atexist_handler)
  91. def exists(env):
  92. return True