Skip to content

Commit 8a7d604

Browse files
committed
tool: a stated program path resolves whichever executable suffix the file carries
A build program writes the path a shell gave it, and on Windows `command -v cmake` answers `C:/Program Files/CMake/bin/cmake` for a `cmake.exe`. The resolver insisted on the exact spelling and refused a program the host itself would have run -- measured in CI, where the cmake consumer reported `options::cmake = "C:/Program Files/CMake/bin/cmake" (not found)` on a runner carrying cmake, and then failed to compile because the subproject it configures never built. A stated path now follows the same suffix rule as a discovered one, which `program_in` has always applied, and a case states it on a Linux row because the rule is the same on every host.
1 parent 789a0bb commit 8a7d604

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

‎src/tool.cppm‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ inline std::string program_in(const std::filesystem::path& dir, std::string_view
7373
return {};
7474
}
7575

76+
// A STATED PATH, WITH THE SAME SUFFIX RULE AS A DISCOVERED ONE. A build program
77+
// writes the path a shell gave it, and on Windows `command -v cmake` answers
78+
// `C:/Program Files/CMake/bin/cmake` for a `cmake.exe`; process creation there
79+
// appends the suffix itself, so a resolver that insisted on the exact spelling
80+
// refused a program the host would have run (measured in CI: the cmake consumer
81+
// reported `options::cmake = "C:/Program Files/CMake/bin/cmake" (not found)` on a
82+
// runner carrying cmake). Empty when neither spelling is a file.
83+
inline std::string program_at(const std::filesystem::path& p) {
84+
if (is_file(p)) return generic(p);
85+
auto with = p;
86+
with += ".exe";
87+
if (is_file(with)) return generic(with);
88+
if (p.extension() == ".exe") {
89+
auto without = p;
90+
without.replace_extension();
91+
if (is_file(without)) return generic(without);
92+
}
93+
return {};
94+
}
95+
7696
inline std::string find_on_path(std::string_view name) {
7797
const char* path = std::getenv("PATH");
7898
if (!path) return {};
@@ -226,9 +246,9 @@ inline found resolve(const spec& s, const choice& c = {}) {
226246
record(from::choice, file, line);
227247
return out;
228248
}
229-
} else if (detail::is_file(p)) {
230-
out.program = detail::generic(p);
231-
out.root = detail::root_of(p);
249+
} else if (auto hit = detail::program_at(p); !hit.empty()) {
250+
out.program = std::move(hit);
251+
out.root = detail::root_of(out.program);
232252
record(from::choice, file, line);
233253
return out;
234254
}

‎tests/plugin-logic/build.mcpp‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,27 @@ int main(int argc, char** argv) {
479479
"the decision names the choice and the program");
480480
} },
481481

482+
{ "tool: a stated path resolves whichever executable suffix the file carries",
483+
// What a shell hands a build program on Windows: `command -v cmake`
484+
// answers a path with no `.exe`, for a `cmake.exe`. Process creation
485+
// there appends the suffix, so the resolver does too -- stated on a
486+
// Linux row, because the rule is the same on every host.
487+
t::row::linux_libcxx().file("pkg/opt/bin/cmake.exe")
488+
.xpkg_source("xim", "cmake", "pending"),
489+
[] {
490+
const auto f = tool_resolve(mcpp::plugins::tool::program(
491+
std::string(mcpp::manifest_dir()) + "/opt/bin/cmake"));
492+
std::printf("source=%s program=%s\n",
493+
std::string(mcpp::plugins::tool::name(f.source)).c_str(),
494+
f.program.c_str());
495+
return f ? 0 : 1;
496+
},
497+
[](const t::result& r, t::checker& c) {
498+
c.expect(r.has_line("source=choice", "opt/bin/cmake.exe"),
499+
"the file beside the stated path answers");
500+
c.expect(!r.has_line("mcpp:xpkg-request="), "a choice requests no payload");
501+
} },
502+
482503
{ "tool: an override answers, and the payload is not consulted",
483504
t::row::linux_libcxx().file("opt/bin/cmake")
484505
.xpkg("xim", "cmake", "{root}/opt")

0 commit comments

Comments
 (0)