mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
The unmapped-suffix warning fired for every header-only library (the default +<*> filter matches headers), so ArduinoJson would have warned on every ESP8266 build. It now names exactly the source-like files (.CPP, .ino and case-variants of the map) the case-sensitive suffix map rejects, partial drops included, and stays quiet for headers and metadata. The ar shim batches the expanded object list by argv length (rc then q appends), keeping the command line under the Windows 32767-char limit the rspfile existed to avoid. A non-iterable dependencies value in a manifest now warns by library name instead of raising a bare TypeError.
70 lines
2.6 KiB
Python
70 lines
2.6 KiB
Python
"""Tiny cross-platform build steps invoked from the generated ninja file.
|
|
|
|
Plain script (not ``python -m``): it runs from ninja with whatever Python
|
|
started esphome and must not depend on the package being importable.
|
|
|
|
Subcommands:
|
|
ar <ar-binary> <archive> <rspfile> remove stale archive, then ``ar rc``
|
|
copy <src> <dst> copy a file
|
|
|
|
The ar rspfile carries one object path per line (the generating rule must
|
|
use ``$in_newline``, never ``$in``).
|
|
"""
|
|
|
|
from pathlib import Path
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def main() -> int:
|
|
mode = sys.argv[1]
|
|
if mode == "ar":
|
|
ar, archive, rspfile = sys.argv[2:5]
|
|
# Remove first: ``ar rc`` replaces members but never drops ones whose
|
|
# source was removed from the build, which would leak stale objects.
|
|
Path(archive).unlink(missing_ok=True)
|
|
# GNU ar treats backslashes in response files as escapes (corrupts
|
|
# Windows paths), so expand the rspfile into argv, stripping the
|
|
# simple surrounding quote ninja adds to special paths.
|
|
# After stripping the outer pair, undo ninja's POSIX escape for an
|
|
# embedded quote ('a'\''b.o' -> a'b.o)
|
|
objects = [
|
|
line[1:-1].replace("'\\''", "'")
|
|
if len(line) >= 2 and line[0] == line[-1] and line[0] in "'\""
|
|
else line
|
|
for line in Path(rspfile).read_text(encoding="utf-8").splitlines()
|
|
if line
|
|
]
|
|
if not objects:
|
|
# An empty archive would "succeed" here and fail far away at link
|
|
print(f"ar: no objects listed in {rspfile} for {archive}", file=sys.stderr)
|
|
return 1
|
|
# Batch by argv length: expanding the rspfile gives back the Windows
|
|
# 32767-char command-line limit it existed to avoid. "rc" creates,
|
|
# "q" appends the remainder.
|
|
op = "rc"
|
|
while objects:
|
|
batch = [objects.pop(0)]
|
|
batch_len = len(batch[0])
|
|
while objects and batch_len + len(objects[0]) < 25000:
|
|
batch_len += len(objects[0]) + 1
|
|
batch.append(objects.pop(0))
|
|
rc = subprocess.run(
|
|
[ar, op, archive, *batch], check=False, close_fds=False
|
|
).returncode
|
|
if rc != 0:
|
|
return rc
|
|
op = "q"
|
|
return 0
|
|
if mode == "copy":
|
|
src, dst = sys.argv[2:4]
|
|
shutil.copyfile(src, dst)
|
|
return 0
|
|
print(f"unknown build_tool mode: {mode}", file=sys.stderr)
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__": # pragma: no cover
|
|
sys.exit(main())
|