Bazel to CMake: Add processing based on current file state
1. Preserve copyright year.
2. Don't overwrite files with a special blocking incantation.
3. Only add subdirectories if they have CMakeLists.txt files.
4. To facilitate (3), process directories bottom-up
Depends on https://github.com/google/iree/pull/589
Tested:
Verified it no longer overrides copyright headers
```shell
$ ./build_tools/scripts/bazel_to_cmake.py --dir iree/compiler
```
is a no-op
Verified it does not add subdirectories with no CMakeLists.txt file
```shell
$ ./build_tools/scripts/bazel_to_cmake.py --dir iree/compiler/Dialect/Flow/Conversion/HLOToFlow
```
is a no-op
Ran preview entire project and saw no new errors
```shell
$ ./build_tools/scripts/bazel_to_cmake.py --preview | grep -i error
"status_errors.h"
"status_win32_errors.h"
"status_errors.cc"
"status_win32_errors.cc"
Reason: `NameError: name 'platform_trampoline_deps' is not defined`
Reason: `NameError: name 'iree_flatbuffer_cc_library' is not defined`
Reason: `NameError: name 'PLATFORM_VULKAN_TEST_DEPS' is not defined`
Reason: `NameError: name 'PLATFORM_VULKAN_LOADER_COPTS' is not defined`
Reason: `KeyError: "No conversion found for target '//third_party/dawn:dawn_headers'"`
Reason: `NameError: name 'platform_trampoline_deps' is not defined`
Reason: `KeyError: '@llvm-project//llvm:tablegen'`
Reason: `NameError: name 'PLATFORM_VULKAN_DEPS' is not defined`
Reason: `NameError: name 'PLATFORM_VULKAN_TEST_DEPS' is not defined`
Reason: `KeyError: "No conversion found for target '@dear_imgui'"`
```
Closes https://github.com/google/iree/pull/590
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/iree/pull/590 from GMNGeoffrey:bazel-to-cmake-2-current-file-state 9bd1315a5a5bd17859f6a9bedb69548ac5d0388f
PiperOrigin-RevId: 292021380
diff --git a/build_tools/scripts/bazel_to_cmake.py b/build_tools/scripts/bazel_to_cmake.py
index 500bdbd..93eb0fe 100755
--- a/build_tools/scripts/bazel_to_cmake.py
+++ b/build_tools/scripts/bazel_to_cmake.py
@@ -34,9 +34,14 @@
from collections import OrderedDict
from itertools import repeat
import glob
+import re
repo_root = None
+EDIT_BLOCKING_PATTERN = re.compile(
+ "bazel[\s_]*to[\s_]*cmake[\s_]*:?[\s_]*do[\s_]*not[\s_]*edit",
+ flags=re.IGNORECASE)
+
def parse_arguments():
global repo_root
@@ -475,18 +480,19 @@
self.directory_path = directory_path
self.rel_build_file_path = rel_build_file_path
- def convert(self):
+ def convert(self, copyright_line):
# One `add_subdirectory(name)` per subdirectory.
- add_subdirectories = ""
+ add_subdir_commands = []
for root, dirs, file_names in os.walk(self.directory_path):
- add_subdirectories = "\n".join(
- ["add_subdirectory(%s)" % (dir,) for dir in dirs])
+ for dir in sorted(dirs):
+ if os.path.isfile(os.path.join(root, dir, "CMakeLists.txt")):
+ add_subdir_commands.append("add_subdirectory(%s)" % (dir,))
# Stop walk, only add direct subdirectories.
break
converted_file = self.template % {
- "date_year": datetime.date.today().year,
- "add_subdirectories": add_subdirectories,
+ "copyright_line": copyright_line,
+ "add_subdirectories": "\n".join(add_subdir_commands),
"body": self.body,
}
@@ -498,7 +504,7 @@
return converted_file
template = textwrap.dedent("""\
- # Copyright %(date_year)s Google LLC
+ %(copyright_line)s
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -527,7 +533,9 @@
def convert_directory_tree(root_directory_path, write_files):
print("convert_directory_tree: %s" % (root_directory_path,))
- for root, dirs, file_names in os.walk(root_directory_path):
+ # Process directories starting at leaves so we can skip add_directory on
+ # subdirs without a CMakeLists file.
+ for root, dirs, file_names in os.walk(root_directory_path, topdown=False):
convert_directory(root, write_files)
@@ -547,11 +555,29 @@
rel_cmakelists_file_path = os.path.relpath(cmakelists_file_path, repo_root)
print("Converting %s to %s" % (rel_build_file_path, rel_cmakelists_file_path))
- if write_files:
+ cmake_file_exists = os.path.isfile(cmakelists_file_path)
+ copyright_line = "# Copyright %s Google LLC" % (datetime.date.today().year,)
+ write_allowed = write_files
+ if cmake_file_exists:
+ with open(cmakelists_file_path) as f:
+ for i, line in enumerate(f):
+ if line.startswith("# Copyright"):
+ copyright_line = line.rstrip()
+ if EDIT_BLOCKING_PATTERN.search(line):
+ print(
+ " %(path)s already exists, and line %(index)d: '%(line)s' prevents edits. Falling back to preview"
+ % {
+ "path": rel_cmakelists_file_path,
+ "index": i + 1,
+ "line": line.strip()
+ })
+ write_allowed = False
+
+ if write_allowed:
# TODO(scotttodd): Attempt to merge instead of overwrite?
# Existing CMakeLists.txt may have special logic that should be preserved
- if os.path.isfile(cmakelists_file_path):
- print(" %s already exists, overwritting" % (rel_cmakelists_file_path,))
+ if cmake_file_exists:
+ print(" %s already exists, overwriting" % (rel_cmakelists_file_path,))
else:
print(" %s does not exist yet, creating" % (rel_cmakelists_file_path,))
print("")
@@ -561,9 +587,8 @@
converter = Converter(directory_path, rel_build_file_path)
try:
exec(build_file_code, GetDict(BuildFileFunctions(converter)))
- converted_text = converter.convert()
-
- if write_files:
+ converted_text = converter.convert(copyright_line)
+ if write_allowed:
with open(cmakelists_file_path, "wt") as cmakelists_file:
cmakelists_file.write(converted_text)
else: