mirror of
https://github.com/esphome/esphome.git
synced 2026-10-10 21:39:06 +00:00
[core] Fix the native ESP8266 and host builds on Windows without ccache (#20468)
This commit is contained in:
@@ -1057,7 +1057,7 @@ def write_project(paths: InstalledPaths, ccache: str | None) -> bool:
|
||||
cxx = (toolchain_tool(paths.toolchain, "g++"),)
|
||||
lines = [
|
||||
*tool_lines((toolchain_tool(paths.toolchain, "gcc"),), cxx, ccache),
|
||||
*compile_rule_lines(),
|
||||
*compile_rule_lines(ccache),
|
||||
*ar_rule_lines(toolchain_tool(paths.toolchain, "ar")),
|
||||
*pch_rule_lines(),
|
||||
"rule link",
|
||||
|
||||
@@ -240,7 +240,7 @@ def write_project(compilers: HostCompilers, ccache: str | None) -> bool:
|
||||
|
||||
lines = [
|
||||
*tool_lines(compilers.cc, compilers.cxx, ccache),
|
||||
*compile_rule_lines(),
|
||||
*compile_rule_lines(ccache),
|
||||
*pch_rule_lines(),
|
||||
"rule link",
|
||||
" command = $cxx -o $out $linkflags @$out.rsp $archives $libdirflags $libflags",
|
||||
|
||||
@@ -74,33 +74,40 @@ def tool_lines(
|
||||
# path gets
|
||||
f"python = {_q(strip_win_long_path_prefix(sys.executable))}",
|
||||
f"buildtool = {_q(_BUILD_TOOL)}",
|
||||
f"ccache = {_q(ccache) if ccache else ''}",
|
||||
*([f"ccache = {_q(ccache)}"] if ccache else []),
|
||||
"",
|
||||
]
|
||||
|
||||
|
||||
def compile_rule_lines() -> list[str]:
|
||||
"""The compile rules; ``$own_includes`` is empty unless an edge sets it."""
|
||||
def compile_rule_lines(ccache: str | None) -> list[str]:
|
||||
"""The compile rules; ``$own_includes`` is empty unless an edge sets it.
|
||||
|
||||
``ccache`` is the launcher ``tool_lines`` was given; the same test here
|
||||
keeps the variable and the rules in step. It is spliced in rather than
|
||||
left as an empty variable: a leading space on the command line makes
|
||||
CreateProcess fail on Windows.
|
||||
"""
|
||||
launcher = "$ccache " if ccache else ""
|
||||
return [
|
||||
"rule c",
|
||||
" command = $ccache $cc -MMD -MF $out.d $own_includes $cflags $flags -c $in -o $out",
|
||||
f" command = {launcher}$cc -MMD -MF $out.d $own_includes $cflags $flags -c $in -o $out",
|
||||
" depfile = $out.d",
|
||||
" deps = gcc",
|
||||
" description = CC $out",
|
||||
"rule cxx",
|
||||
" command = $ccache $cxx -MMD -MF $out.d $own_includes $cxxflags $flags -c $in -o $out",
|
||||
f" command = {launcher}$cxx -MMD -MF $out.d $own_includes $cxxflags $flags -c $in -o $out",
|
||||
" depfile = $out.d",
|
||||
" deps = gcc",
|
||||
" description = CXX $out",
|
||||
"rule aspp",
|
||||
" command = $ccache $cc -MMD -MF $out.d -x assembler-with-cpp $own_includes $asflags $flags -c $in -o $out",
|
||||
f" command = {launcher}$cc -MMD -MF $out.d -x assembler-with-cpp $own_includes $asflags $flags -c $in -o $out",
|
||||
" depfile = $out.d",
|
||||
" deps = gcc",
|
||||
" description = AS $out",
|
||||
# Plain assembler, as SCons's ASCOM: no preprocessor, so no
|
||||
# depfile and no $flags (defines/includes) either
|
||||
"rule asm",
|
||||
" command = $ccache $cc -x assembler $asflags -c $in -o $out",
|
||||
f" command = {launcher}$cc -x assembler $asflags -c $in -o $out",
|
||||
" description = AS $out",
|
||||
]
|
||||
|
||||
|
||||
@@ -888,8 +888,9 @@ def test_write_project_plain_asm_rule_skips_preprocessor(tmp_path: Path) -> None
|
||||
_set_flags()
|
||||
content = _write_ninja(paths)
|
||||
assert "lowlevel.s.o: asm " in content
|
||||
assert "rule asm\n command = $cc -x assembler $asflags -c $in -o $out" in content
|
||||
assert "rule asm\n command = $ccache $cc -x assembler $asflags -c $in -o $out" in (
|
||||
content
|
||||
_write_ninja(paths, ccache="/cc/ccache")
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -308,7 +308,10 @@ def test_write_project_pch_skipped_for_a_force_include_in_the_compiler(
|
||||
def test_write_project_without_ccache(tmp_path: Path) -> None:
|
||||
_make_src(tmp_path, "main.cpp")
|
||||
_changed, ninja = _render()
|
||||
assert "ccache = \n" in ninja
|
||||
# No launcher variable, and no leading space on the commands either:
|
||||
# CreateProcess on Windows rejects a command line that starts with one
|
||||
assert "$ccache" not in ninja
|
||||
assert " command = $cxx -MMD -MF $out.d" in ninja
|
||||
|
||||
|
||||
def test_write_project_routes_user_link_flags(tmp_path: Path) -> None:
|
||||
|
||||
@@ -55,3 +55,21 @@ def test_collect_sources_skips_excluded_and_other_files(tmp_path: Path) -> None:
|
||||
tmp_path / "b.cpp",
|
||||
tmp_path / "sub" / "c.S",
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("ccache", ["/usr/bin/ccache", None])
|
||||
def test_compile_rule_lines_splice_the_launcher(ccache: str | None) -> None:
|
||||
"""Without ccache no command keeps a leading space, which CreateProcess
|
||||
on Windows rejects; with it every compile rule starts with the launcher."""
|
||||
commands = [
|
||||
line.removeprefix(" command = ")
|
||||
for line in ninja_gen.compile_rule_lines(ccache)
|
||||
if line.startswith(" command = ")
|
||||
]
|
||||
assert len(commands) == 4
|
||||
for command in commands:
|
||||
if ccache:
|
||||
assert command.startswith("$ccache $c")
|
||||
else:
|
||||
assert command.startswith("$c")
|
||||
assert "$ccache" not in command
|
||||
|
||||
Reference in New Issue
Block a user