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
4 changes: 4 additions & 0 deletions docs/REFERENCE-cmake.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ aquery must mirror.
- **Link flags**: CMake repeats compile/codegen flags (`-fvisibility=hidden`,
`-fno-common`) on the link line, where they're benign, while Bazel doesn't.
This is the common `ignore.link_flags` case.
- **Redundant `-c` in project flags**: some projects put `-c` into
`CMAKE_<LANG>_FLAGS` (e.g. `"-c -std=c11"`), which compilers tolerate. `-c`
takes no argument, so it is dropped on its own; the flag after it is still
compared and the TU is still keyed by its real source.

## Tests

Expand Down
9 changes: 7 additions & 2 deletions scripts/canonicalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
# These are universal facts (a -o names an output; -c means compile-only), never
# migration decisions, so they're stripped at canonicalization, not configured.
# Flags that consume the FOLLOWING token (drop both):
_DRIVER_PAIR_FLAGS = {"-o", "-c", "-isysroot", "--sysroot", "-arch", "-target",
_DRIVER_PAIR_FLAGS = {"-o", "-isysroot", "--sysroot", "-arch", "-target",
"-gcc-toolchain", "-x", "--serialize-diagnostics"}

# Defines the Bazel toolchain injects for reproducible builds (arrive as
Expand Down Expand Up @@ -218,9 +218,14 @@ def canonicalize_flags(
tok = raw[i]

# driver flags that consume the next token (-o out.o, -isysroot /sdk,
# -arch arm64, -c src). Pure invocation mechanics -- drop flag + arg.
# -arch arm64). Pure invocation mechanics -- drop flag + arg.
if tok in _DRIVER_PAIR_FLAGS and i + 1 < n:
i += 2; continue
# -c takes no argument, but the extractors put the source right after
# it: drop that source too.
if tok == "-c":
i += 2 if i + 1 < n and not raw[i + 1].startswith("-") else 1
continue
# bare positional driver tokens (compiler path mid-argv, .o output)
if _is_driver_token(tok):
i += 1; continue
Expand Down
7 changes: 4 additions & 3 deletions scripts/reconstruct.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ def _is_header_processing(args) -> bool:


def _source_from_compile_args(args) -> Optional[str]:
"""The compiled source is the arg to -c (or the lone source arg). Returns
None for header inputs -- not translation units."""
"""The compiled source is the token after -c (or the lone source arg).
Returns None for header inputs -- not translation units. A -c followed by a
flag is a stray, redundant -c from the project's flags, not the source."""
src = None
for i, a in enumerate(args):
if a == "-c" and i + 1 < len(args):
if a == "-c" and i + 1 < len(args) and not args[i + 1].startswith("-"):
src = args[i + 1]
break
if src is None:
Expand Down
41 changes: 41 additions & 0 deletions tests/test_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "scripts"))

from canonicalize import canonicalize_flags
from config import MigrationConfig
from diff import Severity, diff_models, summarize
from model import (Action, BuildSystem, CanonicalModel, Dependency, Target,
TargetKind, TargetRole)
from reconstruct import reconstruct

REPO = "/work/proj"

Expand Down Expand Up @@ -143,6 +145,45 @@ def test_missing_cmake_flag_is_caught():
assert "NEEDED=1" in dd.cmake_only


# A redundant -c inside the project's own flags (CMAKE_C_FLAGS="-c -std=c11";
# gcc ignores the repetition). -c takes no argument, so it must neither be read
# as naming the source nor swallow the flag that follows it.
_STRAY_C_RAW = ["-mcpu=cortex-m4", "-c", "-std=c11", "-Wall"]


def test_stray_c_does_not_swallow_next_flag():
_, _, flags = canonicalize_flags(_STRAY_C_RAW + ["-c", "src/a.c"], REPO,
is_bazel=False)
assert flags == ("-Wall", "-mcpu=cortex-m4", "-std=c11"), flags


def _stray_c_model(bazel_raw=None):
"""Two-TU target; the CMake side carries the stray -c, the Bazel side
`bazel_raw` (None = the CMake model itself)."""
raw = _STRAY_C_RAW if bazel_raw is None else bazel_raw
m = _bs(CanonicalModel(), is_bazel=bazel_raw is not None)
m.add(Target("lib", TargetKind.STATIC, role=TargetRole.PRODUCTION,
actions=[tu_from_raw(s, raw, is_bazel=bazel_raw is not None)
for s in ("src/a.c", "src/b.c")]))
return m


def test_stray_c_keeps_tus_keyed_by_source():
tus = reconstruct(_stray_c_model())["lib"].tu_map()
assert sorted(tus) == ["src/a.c", "src/b.c"], sorted(tus)


def test_stray_c_flag_is_compared():
a = _stray_c_model()
ok = _stray_c_model(["-mcpu=cortex-m4", "-std=c11", "-Wall"])
assert summarize(diff_models(a, ok))["errors"] == 0
missing = _stray_c_model(["-mcpu=cortex-m4", "-Wall"]) # no -std=c11
discs = diff_models(a, missing)
fd = [d for d in discs if d.kind == "flags_diff"]
assert fd and all("-std=c11" in d.cmake_only for d in fd), discs
assert not summarize(discs)["converged"]


def test_extra_bazel_define_is_warn_not_error():
cmake_raw = ["-DFOO=1"]
bazel_raw = ["-DFOO=1", "-DEXTRA=1"]
Expand Down