llvm_symlinks_test.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/usr/bin/env python3
  2. """Checks various LLVM tool symlinks behave as expected."""
  3. __copyright__ = """
  4. Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  5. Exceptions. See /LICENSE for license information.
  6. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. """
  8. from pathlib import Path
  9. import subprocess
  10. import os
  11. import platform
  12. import sys
  13. import unittest
  14. class LLVMSymlinksTest(unittest.TestCase):
  15. def setUp(self) -> None:
  16. # The install root is adjacent to the test script
  17. self.install_root = Path(sys.argv[0]).parent / "prefix_root"
  18. self.tmpdir = Path(os.environ["TEST_TMPDIR"])
  19. self.test_o_file = self.tmpdir / "test.o"
  20. self.test_o_file.touch()
  21. def get_link_cmd(self, clang: Path) -> list[str | Path]:
  22. return [
  23. clang,
  24. # Verbose printing to help with debugging.
  25. "-v",
  26. # Print out the link command rather than running it.
  27. "-###",
  28. # Give the link command an output.
  29. "-o",
  30. self.tmpdir / "test",
  31. # A test input file. This won't be read though.
  32. self.test_o_file,
  33. ]
  34. def unsupported(self, stderr: str) -> None:
  35. self.fail(f"Unsupported platform '{platform.uname()}':\n{stderr}")
  36. # Note that we can't test `clang` vs. `clang++` portably. The only commands
  37. # with useful differences are _link_ commands, and those need to build
  38. # runtime libraries on demand, which requires the host to be able to compile
  39. # and link for the target. Instead, we test linking with the default target
  40. # (the host), as that is the one that should reliably work if we're
  41. # developing Carbon, and encode all the different platform results in the
  42. # test expectations.
  43. def test_clang(self) -> None:
  44. bin = self.install_root / "lib/carbon/llvm/bin/clang"
  45. # Most errors are caught by ensuring the command succeeds.
  46. run = subprocess.run(
  47. self.get_link_cmd(bin), check=True, capture_output=True, text=True
  48. )
  49. # Also ensure that it correctly didn't imply a C++ link.
  50. if platform.system() == "Linux":
  51. self.assertNotRegex(run.stderr, r'"-lstdc\+\+"')
  52. elif platform.system() == "Darwin":
  53. self.assertNotRegex(run.stderr, r'"-lc\+\+"')
  54. else:
  55. self.unsupported(run.stderr)
  56. # Note that we can't test `clang` vs. `clang++` portably. See the comment on
  57. # `test_clang` for details.
  58. def test_clangplusplus(self) -> None:
  59. bin = self.install_root / "lib/carbon/llvm/bin/clang++"
  60. run = subprocess.run(
  61. self.get_link_cmd(bin), check=True, capture_output=True, text=True
  62. )
  63. # Ensure that this binary _does_ imply a C++ link.
  64. if platform.system() == "Linux":
  65. self.assertRegex(run.stderr, r'"-lstdc\+\+"')
  66. elif platform.system() == "Darwin":
  67. self.assertRegex(run.stderr, r'"-lc\+\+"')
  68. else:
  69. self.unsupported(run.stderr)
  70. def test_clang_cl(self) -> None:
  71. bin = self.install_root / "lib/carbon/llvm/bin/clang-cl"
  72. run = subprocess.run(
  73. # Use the `cl.exe`-specific help flag to test the mode.
  74. [bin, "/?"],
  75. check=True,
  76. capture_output=True,
  77. text=True,
  78. )
  79. # This should print the help string, including `cl.exe` specifics.
  80. self.assertRegex(run.stdout, r"CL.EXE COMPATIBILITY OPTIONS:")
  81. def test_clang_cpp(self) -> None:
  82. # Note that this is a test of the C-preprocessor mode, not C++ mode.
  83. # Create a test file that we'll preprocess.
  84. text_file = self.tmpdir / "test.txt"
  85. with open(text_file, "w") as f:
  86. f.write("TEST\n")
  87. # Run the preprocessor using a CPP-specific command line reading from
  88. # the test file and writing to stdout. We define a macro that we'll
  89. # check is expanded.
  90. bin = self.install_root / "lib/carbon/llvm/bin/clang-cpp"
  91. try:
  92. run = subprocess.run(
  93. [bin, "-D", "TEST=SUCCESS", text_file, "-"],
  94. check=True,
  95. capture_output=True,
  96. text=True,
  97. )
  98. except subprocess.CalledProcessError as err:
  99. print(err.stderr, file=sys.stderr)
  100. raise
  101. self.assertEqual(run.stderr, "")
  102. self.assertRegex(run.stdout, r"(^|\n)SUCCESS\n")
  103. if __name__ == "__main__":
  104. unittest.main()