Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,50 @@ if you want to build things after the bazelfiication to checkt that everything s

`ninja2bazel` supports remapping of paths/files and manually generated targets.

### Post-treatments

Generated `BUILD.bazel` files can be rewritten immediately after generation with
one or more `--post-treatment` scripts. Each script receives the path to the
generated file and can update it in place.

```
python3 parser.py -p "." path/to/build.ninja path/to/src \
--post-treatment contrib/posttreatments/add_crc32_arm_crc_copts.py
```

There is a complete AST-based example in `contrib/posttreatments/`.
That folder also contains a second example that injects a `genrule` to render
`pregenerated/flow/include/flow/ProtocolVersion.h` from
`flow/ProtocolVersion.h.cmake` and `flow/ProtocolVersions.cmake`.

### Remapping paths/files

Initially this was developped to deal with symlinks to other folders outside of the what was currently bazelified, for instance your are trying to bazelify your C++ code that is in `cpp` but you have already bazelified your protobuf that is in `proto` and you have a symlink from `cpp/proto` to `../proto`, using `--remap cpp/proto=proto` would allow to use targets that would be defined in the proto folder.

More recently this feature was extended to remap files as well, in this case you don't specify the full path where you want it remap but just the prefix to remap to; for instance if you have a file that is generated during the build you can remap it to a pre-exiting file that you have placed somewhere else, you would use `--remap flow/config.h=bazel/build` will remap the file flow/config.h to bazel/build assuming that there is a file called `flow/config.h` there.
The tool will take care of setting the `include` value properly to make things work.

### CMake configure_file pregenerated files

Pass `--configure_files_list path/to/configure_files.txt` to teach `ninja2bazel`
how CMake-created files under the work directory are generated. The file should
contain `configure_file(...)` lines copied from CMake, for example:

```
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ProtocolVersion.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/include/flow/ProtocolVersion.h)
```

When a pregenerated include matches one of those outputs, `ninja2bazel` emits a
`genrule` that renders it from the template. Template placeholders using
`@VAR@` or `${VAR}` are resolved by scanning CMake files for `set(VAR ...)`; the
conversion fails if any placeholder cannot be found.

You can also provide values directly on the command line:

```
--configure_var=var1=val1 --configure_var=var2=val2
```

### Manually generated targets
Sometime the build generates files but they are not generated by `ninja` a counter example for that are files generated by `cmake` because it won't work for them because usually the CMake build don't include them in the dependencies they are more often than not just included headers. In that case it's better to use the pregenerated support for that but for instance `RocksDB` build generates a file and add it as dependency to other targets but don't generate the command to get the generate the file itself. In this case you want to use `-m foo/bar.h=bazel/build/bar.h`.
Beware that in order for this to work today you need to use a different prefix, this will need to be changed in the future to be more flexible.
51 changes: 50 additions & 1 deletion bazel.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,16 @@
CompilationFlags = Dict[str, Union[str, Set[str]]]
BASIC_C_STD_RE = re.compile(r"^-std=(?:c|gnu)[0-9A-Za-z]+$")
BASIC_CXX_STD_RE = re.compile(r"^-std=(?:c\+\+|gnu\+\+)[0-9A-Za-z]+$")
RULES_CC_BZL = "@rules_cc//cc:defs.bzl"
RULES_CC_SYMBOLS = (
"cc_binary",
"cc_import",
"cc_library",
"cc_shared_library",
"cc_test",
)
RULES_PYTHON_LOAD = 'load("@rules_python//python:defs.bzl", "py_binary")'
RULES_SHELL_LOAD = 'load("@rules_shell//shell:sh_binary.bzl", "sh_binary")'


def _normalize_flag(flag: str) -> str:
Expand All @@ -50,6 +60,28 @@ def _split_language_opts(
return conlyopts, cxxopts, copts


def _format_rules_cc_load(symbols: Iterable[str]) -> str:
ordered_symbols = [symbol for symbol in RULES_CC_SYMBOLS if symbol in symbols]
quoted_symbols = ", ".join([f'"{symbol}"' for symbol in ordered_symbols])
return f'load("{RULES_CC_BZL}", {quoted_symbols})'


def _merge_rules_cc_loads(loads: Iterable[str]) -> List[str]:
symbols: Set[str] = set()
other_loads: List[str] = []
prefix = f'load("{RULES_CC_BZL}", '
for load in loads:
if load.startswith(prefix):
for symbol in RULES_CC_SYMBOLS:
if f'"{symbol}"' in load:
symbols.add(symbol)
else:
other_loads.append(load)
if symbols:
other_loads.append(_format_rules_cc_load(symbols))
return other_loads


def _getPrefix(
d: Union["BaseBazelTarget", "BazelCCImport"], location: str, defaultPrefix: str
) -> str:
Expand Down Expand Up @@ -229,7 +261,12 @@ def __repr__(self) -> str:
return f"cc_import {self.name}"

def getGlobalImport(self) -> str:
return ""
if self.alias is not None:
return ""
symbols = {"cc_import"}
if not self.skipWrapping:
symbols.add("cc_library")
return _format_rules_cc_load(symbols)

def getAllHeaders(self, deps_only=False):
# cc_import have headers but we don't include them in the upper target
Expand Down Expand Up @@ -534,6 +571,7 @@ def genBazelBuildContent(self) -> Dict[str, str]:

for k, v in topContent.items():
topStanza = list(filter(lambda x: x != "", v))
topStanza = _merge_rules_cc_loads(topStanza)
if len(topStanza) > 0:
# Force empty line

Expand Down Expand Up @@ -737,6 +775,11 @@ def __repr__(self) -> str:
base += deps
return base

def getGlobalImport(self) -> str:
if self.type in RULES_CC_SYMBOLS:
return _format_rules_cc_load({self.type})
return ""

def asBazel(
self, commonFlags: CompilationFlags, defaultPrefix: str = None
) -> BazelTargetStrings:
Expand Down Expand Up @@ -1164,6 +1207,9 @@ def asBazel(
def addSrc(self, target: BaseBazelTarget):
self.srcs.add(target)

def getGlobalImport(self) -> str:
return RULES_PYTHON_LOAD


class ShBinaryBazelTarget(BaseBazelTarget):
def __init__(self, name: str, location: str):
Expand All @@ -1190,6 +1236,9 @@ def asBazel(
def addSrc(self, target: BaseBazelTarget):
self.srcs.add(target)

def getGlobalImport(self) -> str:
return RULES_SHELL_LOAD


bazelcache: Dict[str, Any] = {}

Expand Down
Loading
Loading