76 lines
3.3 KiB
Python
76 lines
3.3 KiB
Python
"""Prepare the known-working lwIP component layout for ESP-IDF v6.0.2."""
|
|
import filecmp
|
|
from pathlib import Path
|
|
import shutil
|
|
import sys
|
|
|
|
|
|
def replace_once(text, old, new, label):
|
|
if text.count(old) != 1:
|
|
raise RuntimeError(f"Unexpected {label}; expected ESP-IDF v6.0.2 sources")
|
|
return text.replace(old, new, 1)
|
|
|
|
|
|
def write_changed(path, data):
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
if not path.exists() or path.read_bytes() != data:
|
|
path.write_bytes(data)
|
|
|
|
|
|
def prepare(source, destination, arp):
|
|
source, destination, arp = source.resolve(), destination.resolve(), arp.resolve()
|
|
if not arp.is_file():
|
|
raise RuntimeError(f"Missing modified ARP source: {arp}")
|
|
if source == destination or source in destination.parents or destination in source.parents:
|
|
raise RuntimeError("Source and generated directories must be separate")
|
|
if any(c in arp.as_posix() for c in ('"', ';', '$')):
|
|
raise RuntimeError("ARP path contains characters that require CMake escaping")
|
|
|
|
cmake = (source / "CMakeLists.txt").read_text()
|
|
cmake = replace_once(cmake, '"lwip/src/core/ipv4/etharp.c"',
|
|
f'"{arp.as_posix()}"', "lwIP CMakeLists.txt")
|
|
cmake = replace_once(cmake,
|
|
'if(NOT ${target} STREQUAL "linux")\n set(priv_requires vfs)\nendif()',
|
|
'set(priv_requires)\n\nif(NOT ${target} STREQUAL "linux")\n list(APPEND priv_requires vfs)\nendif()',
|
|
"lwIP dependencies")
|
|
sockets_path = "lwip/src/include/lwip/sockets.h"
|
|
sockets = (source / sockets_path).read_text()
|
|
if "#ifndef SIOCATMARK" not in sockets:
|
|
line = "#define SIOCATMARK _IOR('s', 7, unsigned long) /* at oob mark? */"
|
|
sockets = replace_once(sockets, line, "#endif\n#ifndef SIOCATMARK\n" + line,
|
|
"SIOCATMARK definition")
|
|
fcntl_path = "port/linux/include/sys/fcntl.h"
|
|
fcntl = (source / fcntl_path).read_text()
|
|
if "#define F_GETFD" not in fcntl:
|
|
fcntl = fcntl.rstrip("\n") + "\n\n#ifndef F_GETFD\n#define F_GETFD 1\n#endif\n"
|
|
changed = {"CMakeLists.txt": cmake.encode(), sockets_path: sockets.encode(),
|
|
fcntl_path: fcntl.encode()}
|
|
|
|
# Validate all substitutions before writing. Do not copy or compile stock ARP.
|
|
destination.mkdir(parents=True, exist_ok=True)
|
|
for path in source.rglob("*"):
|
|
relative = path.relative_to(source)
|
|
if ".git" in relative.parts or not path.is_file():
|
|
continue
|
|
name = relative.as_posix()
|
|
if name in changed or name == "lwip/src/core/ipv4/etharp.c":
|
|
continue
|
|
target = destination / relative
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
if not target.is_file() or not filecmp.cmp(path, target, shallow=False):
|
|
shutil.copy2(path, target)
|
|
for name, data in changed.items():
|
|
write_changed(destination / name, data)
|
|
stock_arp = destination / "lwip/src/core/ipv4/etharp.c"
|
|
if stock_arp.exists():
|
|
stock_arp.unlink()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
if len(sys.argv) != 4:
|
|
raise RuntimeError("Usage: prepare.py SDK_LWIP BUILD_LWIP PATCHED_ETHARP")
|
|
prepare(*(Path(value) for value in sys.argv[1:]))
|
|
except (OSError, RuntimeError) as error:
|
|
sys.exit(str(error))
|