Skip to content
Open
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
2 changes: 1 addition & 1 deletion SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ instead of being a warning nobody reads.
> two sides aren't comparable.

```bash
bazel aquery 'mnemonic("CppCompile|CppLink|CppArchive", //...)' \
bazel aquery 'mnemonic("CppCompile|ObjcCompile|CppLink|CppArchive", //...)' \
[--config=<name>] [--copt=... --cxxopt=...] \
--output=jsonproto > aquery.json
python3 scripts/extract_bazel.py aquery.json <repo_root> model.bazel.json
Expand Down
3 changes: 2 additions & 1 deletion scripts/canonicalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ def _is_driver_token(tok: str) -> bool:
these, so this only affects the Bazel side."""
if tok.startswith("-"):
return False
return (tok.endswith((".sh", ".o", ".obj", ".cc", ".cpp", ".cxx", ".c", ".C"))
return (tok.endswith((".sh", ".o", ".obj", ".cc", ".cpp", ".cxx", ".c", ".C",
".m", ".mm"))
or "/" in tok and not tok.startswith("/")) # relative exec/source paths


Expand Down
16 changes: 10 additions & 6 deletions scripts/extract_bazel.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,16 @@
"""Extract a CanonicalModel from `bazel aquery --output=jsonproto`.

aquery is the Bazel-side counterpart to the CMake File API: it exposes the
actual actions the build would run -- CppCompile actions (one per TU, with the
full argv) AND CppLink/CppArchive actions (the link closure). compile commands
alone would miss the link half, so we use aquery.
actual actions the build would run -- CppCompile/ObjcCompile actions (one per
TU, with the full argv) AND CppLink/CppArchive actions (the link closure).
compile commands alone would miss the link half, so we use aquery. ObjcCompile
is Bazel's mnemonic for .m/.mm sources compiled via objc_library -- CMake's
File API has no such distinction (it reports those under CppCompile too), so
both must map to the same neutral compile bucket here or objc_library sources
silently vanish from the Bazel model.

Usage:
bazel aquery 'mnemonic("CppCompile|CppLink|CppArchive", //...)' \
bazel aquery 'mnemonic("CppCompile|ObjcCompile|CppLink|CppArchive", //...)' \
--output=jsonproto > aquery.json
python3 extract_bazel.py aquery.json <repo_root> model.bazel.json

Expand All @@ -44,7 +48,7 @@
TargetRole)
from serialize import dump_model

_COMPILE = {"CppCompile"}
_COMPILE = {"CppCompile", "ObjcCompile"}
_LINK = {"CppLink", "CppArchive"}
# Bazel Java compile. (Turbine = header/ijar compile, JavaSourceJar = packaging:
# both Bazel-specific, not real compilations -- skipped, like C++ header
Expand Down Expand Up @@ -108,7 +112,7 @@ def _label_to_name(label: str) -> str:


_HEADER_PROCESSING_MARKERS = ("-xc++-header", "-fsyntax-only")
_REAL_SOURCE_EXTS = (".cc", ".cpp", ".cxx", ".c", ".C")
_REAL_SOURCE_EXTS = (".cc", ".cpp", ".cxx", ".c", ".C", ".m", ".mm")


def _is_real_compile(args) -> bool:
Expand Down
4 changes: 2 additions & 2 deletions scripts/reconstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
from model import (Action, BuildSystem, CanonicalModel, Dependency, Target,
TargetKind, TranslationUnit)

_COMPILE_MNEMONICS = {"CppCompile"}
_COMPILE_MNEMONICS = {"CppCompile", "ObjcCompile"}
_LINK_MNEMONICS = {"CppLink", "CppArchive"}
_JAVA_COMPILE_MNEMONICS = {"JavaCompile"}

_HEADER_EXTS = (".h", ".hpp", ".hh", ".hxx", ".inc", ".inl")
_SOURCE_EXTS = (".cc", ".cpp", ".cxx", ".c", ".C")
_SOURCE_EXTS = (".cc", ".cpp", ".cxx", ".c", ".C", ".m", ".mm")
_ARCHIVE_EXTS = (".a", ".lo", ".lib")
_JAVA_EXT = ".java"

Expand Down
28 changes: 28 additions & 0 deletions tests/test_extractors.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,34 @@ def test_header_processing_actions_are_not_tus():
assert not any(s.endswith(".h") for s in srcs), srcs # header dropped


def test_bazel_objccompile_is_a_real_compile():
# objc_library sources (.m/.mm) show up under Bazel's ObjcCompile mnemonic,
# not CppCompile. CMake's File API has no such split -- it reports them as
# CppCompile too -- so ObjcCompile must land in the same TU bucket, or an
# Objective-C target's sources silently vanish from the Bazel model (they
# still compile fine; only the extractor's view of them was missing).
aquery = {
"artifacts": [{"id": 1, "pathFragmentId": 10}],
"pathFragments": [{"id": 10, "label": "cocoa_init.o", "parentId": 11},
{"id": 11, "label": "bazel-out"}],
"targets": [{"id": 100, "label": "//:glfw_cocoa"}],
"actions": [
{"mnemonic": "ObjcCompile", "targetId": 100, "outputIds": [1],
"arguments": ["clang", "-c", "src/cocoa_init.m",
"-o", "bazel-out/cocoa_init.o", "-DFOO=1"]},
],
}
with tempfile.TemporaryDirectory() as root:
aq_path = os.path.join(root, "aquery.json")
with open(aq_path, "w") as f:
json.dump(aquery, f)
b = extract_bazel.extract(aq_path, REPO)
t = _view(b, ":glfw_cocoa")
srcs = [tu.source for tu in t.tus]
assert "src/cocoa_init.m" in srcs, srcs
assert t.role.value == "production", t.role


def test_bazel_extracts_link_flags_from_cpplink():
# A CppLink action: link flags must be extracted; driver mechanics (wrapper,
# -o/output), object/archive inputs and -l libs must be dropped.
Expand Down