Skip to content

Commit

Permalink
Make bazel_to_cmake configurable. (#12765)
Browse files Browse the repository at this point in the history
This reworks bazel_to_cmake so that it searches for a
.bazel_to_cmake.cfg.py file and uses its location as the root of the
repository.

This file is also evaluated and provides repository-specific
configuration for the tool.

There may still be some work to fully generalize but this should get us
pretty close to being able to use bazel_to_cmake in related OpenXLA
projects.

Progress on #12520 for letting us use bazel_to_cmake in out of tree
plugin repositories.
  • Loading branch information
Stella Laurenzo authored Mar 28, 2023
1 parent 9b74ec0 commit 6f24a2f
Show file tree
Hide file tree
Showing 4 changed files with 879 additions and 756 deletions.
51 changes: 51 additions & 0 deletions .bazel_to_cmake.cfg.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2020 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

import bazel_to_cmake_converter
import bazel_to_cmake_targets

DEFAULT_ROOT_DIRS = ["compiler", "runtime", "samples", "tests", "tools"]

REPO_MAP = {
# Since this is the @iree_core repo, map to empty since all internal
# targets are of the form "//compiler", not "@iree_core//compiler".
"@iree_core": "",
}


class CustomBuildFileFunctions(bazel_to_cmake_converter.BuildFileFunctions):

def iree_compiler_cc_library(self, deps=[], **kwargs):
self.cc_library(deps=deps + ["//compiler/src:defs"], **kwargs)

def iree_runtime_cc_library(self, deps=[], **kwargs):
self.cc_library(deps=deps + ["//runtime/src:runtime_defines"], **kwargs)

def iree_runtime_cc_test(self, deps=[], **kwargs):
self.cc_test(deps=deps + ["//runtime/src:runtime_defines"], **kwargs)

def iree_compiler_cc_test(self, deps=[], **kwargs):
self.cc_test(deps=deps + ["//compiler/src:defs"], **kwargs)

def iree_runtime_cc_binary(self, deps=[], **kwargs):
self.cc_binary(deps=deps + ["//runtime/src:runtime_defines"], **kwargs)

def iree_compiler_cc_binary(self, deps=[], **kwargs):
self.cc_binary(deps=deps + ["//compiler/src:defs"], **kwargs)


class CustomTargetConverter(bazel_to_cmake_targets.TargetConverter):

def _initialize(self):
self._update_target_mappings({
"//compiler/src:defs": [],
"//runtime/src:runtime_defines": [],
})

def _convert_unmatched_target(self, target: str) -> str:
"""Converts unmatched targets in a repo specific way."""
# Default rewrite: prefix with "iree::", without pruning the path.
return ["iree::" + self._convert_to_cmake_path(target)]
77 changes: 65 additions & 12 deletions build_tools/bazel_to_cmake/bazel_to_cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,55 @@
For usage, see:
python3 build_tools/bazel_to_cmake/bazel_to_cmake.py --help
Configuration
-------------
When invoked, bazel_to_cmake will traverse up from the current directory until
it finds a ".bazel_to_cmake.cfg.py" file. This file both serves as a marker
for the repository root and provides repository specific configuration.
The file is evaluated as a module and can have the following customizations:
* DEFAULT_ROOT_DIRS: A list of root directory names that should be processed
(relative to the repository root) when invoked without a --repo_root or --dir.
* REPO_MAP: Mapping of canonical Bazel repo name (i.e. "@iree_core") to what it
is known as locally (most commonly the empty string). This is used in global
target rules to make sure that they work either in the defining or referencing
repository.
* CustomBuildFileFunctions: A class that extends
`bazel_to_cmake_converter.BuildFileFunctions` and injects globals for
processing the BUILD file. All symbols that do not start with "_" are
available.
* CustomTargetConverter: A class that extends
`bazel_to_cmake_targets.TargetConverter` and customizes target mapping.
Typically, this is used for purely local targets in leaf projects (as global
targets will be encoded in the main bazel_to_cmake_targets.py file).
"""
# pylint: disable=missing-docstring

import argparse
import datetime
import importlib
import importlib.util
import os
import re
import sys
import textwrap
import types
from enum import Enum

import bazel_to_cmake_converter

repo_root = None
repo_cfg = None

EDIT_BLOCKING_PATTERN = re.compile(
r"bazel[\s_]*to[\s_]*cmake[\s_]*:?[\s_]*do[\s_]*not[\s_]*edit",
flags=re.IGNORECASE)

PRESERVE_TAG = "### BAZEL_TO_CMAKE_PRESERVES_ALL_CONTENT_BELOW_THIS_LINE ###"
REPO_CFG_FILE = ".bazel_to_cmake.cfg.py"
REPO_CFG_MODULE_NAME = "bazel_to_cmake_repo_config"


class Status(Enum):
Expand All @@ -47,8 +76,6 @@ class Status(Enum):


def parse_arguments():
global repo_root

parser = argparse.ArgumentParser(
description="Bazel to CMake conversion helper.")
parser.add_argument("--preview",
Expand Down Expand Up @@ -76,11 +103,12 @@ def parse_arguments():
group.add_argument("--dir",
help="Converts the BUILD file in the given directory",
default=None)
group.add_argument(
"--root_dir",
nargs="+",
help="Converts all BUILD files under a root directory",
default=["compiler", "iree", "runtime", "samples", "tests", "tools"])
default_root_dirs = (repo_cfg.DEFAULT_ROOT_DIRS if hasattr(
repo_cfg, "DEFAULT_ROOT_DIRS") else [])
group.add_argument("--root_dir",
nargs="+",
help="Converts all BUILD files under a root directory",
default=default_root_dirs)

args = parser.parse_args()

Expand All @@ -95,10 +123,29 @@ def parse_arguments():
def setup_environment():
"""Sets up some environment globals."""
global repo_root

# Determine the repository root (two dir-levels up).
repo_root = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
global repo_cfg

# Scan up the directory tree for a repo config file.
check_dir = os.getcwd()
while not os.path.exists(os.path.join(check_dir, REPO_CFG_FILE)):
new_check_dir = os.path.dirname(check_dir)
if not new_check_dir or new_check_dir == check_dir:
print(f"ERROR: Could not find {REPO_CFG_FILE} in a parent directory "
f"of {os.getcwd()}")
sys.exit(1)
check_dir = new_check_dir
repo_root = check_dir
log(f"Using repo root {repo_root}")

# Dynamically load the config file as a module.
orig_dont_write_bytecode = sys.dont_write_bytecode
sys.dont_write_bytecode = True # Don't generate __pycache__ dir
spec = importlib.util.spec_from_file_location(
REPO_CFG_MODULE_NAME, os.path.join(repo_root, REPO_CFG_FILE))
repo_cfg = importlib.util.module_from_spec(spec)
sys.modules[REPO_CFG_MODULE_NAME] = repo_cfg
spec.loader.exec_module(repo_cfg)
sys.dont_write_bytecode = orig_dont_write_bytecode


def repo_relpath(path):
Expand Down Expand Up @@ -212,7 +259,9 @@ def convert_directory(directory_path, write_files, allow_partial_conversion,
build_file_code = compile(build_file_contents, build_file_path, "exec")
try:
converted_build_file = bazel_to_cmake_converter.convert_build_file(
build_file_code, allow_partial_conversion=allow_partial_conversion)
build_file_code,
repo_cfg=repo_cfg,
allow_partial_conversion=allow_partial_conversion)
except (NameError, NotImplementedError) as e:
log(
f"ERROR generating {rel_dir_path}.\n"
Expand Down Expand Up @@ -267,6 +316,10 @@ def main(args):
write_files=write_files,
allow_partial_conversion=args.allow_partial_conversion,
verbosity=args.verbosity)
else:
log(f"ERROR: None of --root-dir, --dir arguments or DEFAULT_ROOT_DIRS in "
f".bazel_to_cmake.cfg.py: No conversion will be done")
sys.exit(1)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit 6f24a2f

Please sign in to comment.