Files
carbon-lang/migrate_cpp/migrate_cpp.py
T
Chandler CarruthandJon Meow 05261b7fe7 Remove the LLVM bootstrap and use Hombrew installed LLVM-12. (#551)
Now that LLVM 12 has been released we no longer have any need to
bootstrap LLVM to get the desired featureset. LLVM 12 is available
widely, including in Homebrew across multiple platforms and in the
GitHub action runners.

Sadly, the Linux distribution builds of LLVM-12 are largely broken and
not as useful for us. The Homebrew Linux install was also broken
originally, but I've worked extensively with the Homebrew folks to get
the Linux install into a really good shape. It should now work reliably.

There are two primary bugs in Linux LLVM packages that need to be fixed
before we can just use them:

- https://bugs.llvm.org/show_bug.cgi?id=43604
- https://bugs.llvm.org/show_bug.cgi?id=46321

Once those are addressed and point releases with the fixes widely
available we can further simplify things.

Even with the need to use Homebrew installs, using the released LLVM has
the extra advantage of making it easy to properly support Darwin ARM and
I've added that configuration so that I can test things there.

Last but not least, this will significantly shrink our build outputs
which should allow building much more in continuous integration on
GitHub actions without exceeding the action cache size limits. I've even
added several tweaks and adjustments to the compile and build flags to
improve the build performance and reduce the build output size.

Once this is landed and stable, we can consider adding the refactoring
tooling back to our CI.

One of the biggest downsides of this path is that our CI has to download
and install the LLVM toolchain from Homebrew on each run. This is pretty
slow (takes a couple of minutes). But it is a fixed overhead -- it won't
get worse over time. Eventually, we can either look at a much fancier
action configuration to avoid this or hopefully the Debian packages will
get updated and we can move back to those.

The bootstrapping has served us long enough at this point. We can
resurrect it if we ever find a compelling reason for breaking off of the
latest LLVM release as our host toolchain.

Co-authored-by: Jon Meow <46229924+jonmeow@users.noreply.github.com>
2021-06-09 10:00:46 -07:00

107 lines
3.4 KiB
Python

"""Migrates C++ code to Carbon."""
__copyright__ = """
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
Exceptions. See /LICENSE for license information.
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
"""
import argparse
import glob
import os
import subprocess
import sys
_CPP_REFACTORING = "./cpp_refactoring/cpp_refactoring"
_H_EXTS = {".h", ".hpp"}
_CPP_EXTS = {".c", ".cc", ".cpp", ".cxx"}
class _Workflow(object):
def __init__(self):
"""Parses command-line arguments and flags."""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"dir",
type=str,
help="A directory containing C++ files to migrate to Carbon.",
)
parsed_args = parser.parse_args()
self._parsed_args = parsed_args
self._data_dir = os.path.dirname(sys.argv[0])
# Validate arguments.
if not os.path.isdir(parsed_args.dir):
sys.exit("%r must point to a directory." % parsed_args.dir)
def run(self):
"""Runs the migration workflow."""
self._gather_files()
self._clang_tidy()
self._cpp_refactoring()
self._rename_files()
self._print_header("Done!")
def _data_file(self, relative_path):
"""Returns the path to a data file."""
return os.path.join(self._data_dir, relative_path)
@staticmethod
def _print_header(header):
print("*" * 79)
print("* %-75s *" % header)
print("*" * 79)
def _gather_files(self):
"""Returns the list of C++ files to convert."""
self._print_header("Gathering C++ files...")
all_files = glob.glob(
os.path.join(self._parsed_args.dir, "**/*.*"), recursive=True
)
exts = _CPP_EXTS.union(_H_EXTS)
cpp_files = [f for f in all_files if os.path.splitext(f)[1] in exts]
if not cpp_files:
sys.exit(
"%r doesn't contain any C++ files to convert."
% self._parsed_args.dir
)
self._cpp_files = sorted(cpp_files)
print("%d files found." % len(self._cpp_files))
def _clang_tidy(self):
"""Runs clang-tidy to fix C++ files in a directory."""
self._print_header("Running clang-tidy...")
with open(self._data_file("clang_tidy.yaml")) as f:
config = f.read()
subprocess.run(
["clang-tidy", "--fix", "--config", config] + self._cpp_files
)
def _cpp_refactoring(self):
"""Runs cpp_refactoring to migrate C++ files towards Carbon syntax."""
self._print_header("Running cpp_refactoring...")
cpp_refactoring = self._data_file(_CPP_REFACTORING)
subprocess.run([cpp_refactoring] + self._cpp_files)
def _rename_files(self):
"""Renames C++ files to the destination Carbon filenames."""
api_renames = 0
impl_renames = 0
for f in self._cpp_files:
parts = os.path.splitext(f)
if parts[1] in _H_EXTS:
os.rename(f, parts[0] + ".carbon")
api_renames += 1
else:
os.rename(f, parts[0] + ".impl.carbon")
impl_renames += 1
print(
"Renaming resulted in %d API files and %d impl files."
% (api_renames, impl_renames)
)
if __name__ == "__main__":
_Workflow().run()