Skip to content

Commit 4a3bbf4

Browse files
committed
fix(run): reuse last build preset instead of defaulting to dev-ninja
1 parent 191ac92 commit 4a3bbf4

3 files changed

Lines changed: 128 additions & 17 deletions

File tree

include/vix/cli/commands/run/RunDetail.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,10 @@ namespace vix::commands::RunCommand::detail
148148
apply_log_color_env(opt);
149149
}
150150

151+
std::string choose_configure_preset_smart(const std::filesystem::path &projectDir,
152+
const std::string &userPreset);
153+
154+
std::filesystem::path resolve_build_dir_smart(const std::filesystem::path &projectDir,
155+
const std::string &configurePreset);
156+
151157
} // namespace vix::commands::RunCommand::detail

src/commands/RunCommand.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -176,18 +176,22 @@ namespace vix::commands::RunCommand
176176

177177
if (has_presets(projectDir))
178178
{
179+
const std::string configurePreset =
180+
choose_configure_preset_smart(projectDir, opt.preset);
181+
182+
const std::string runPreset =
183+
choose_run_preset(projectDir, configurePreset, opt.runPreset);
184+
185+
const fs::path buildDir = resolve_build_dir_smart(projectDir, configurePreset);
186+
const bool alreadyConfigured = has_cmake_cache(buildDir);
187+
179188
RunProgress progress(/*totalSteps=*/2);
180189

181190
// 1) Configure (only if needed)
182191
{
183-
progress.phase_start("Configure project (preset: " + opt.preset + ")");
192+
progress.phase_start("Configure project (preset: " + configurePreset + ")");
184193

185-
bool needConfigure = true;
186-
if (auto binDir = detail::preset_binary_dir(projectDir, opt.preset))
187-
{
188-
if (detail::has_cmake_cache(*binDir))
189-
needConfigure = false;
190-
}
194+
bool needConfigure = !alreadyConfigured;
191195

192196
if (!needConfigure)
193197
{
@@ -198,34 +202,31 @@ namespace vix::commands::RunCommand
198202
std::ostringstream oss;
199203
#ifdef _WIN32
200204
oss << "cmd /C \"cd /D " << quote(projectDir.string())
201-
<< " && cmake --preset " << quote(opt.preset) << "\"";
205+
<< " && cmake --preset " << quote(configurePreset) << "\"";
202206
#else
203207
oss << "cd " << quote(projectDir.string())
204-
<< " && cmake --log-level=WARNING --preset " << quote(opt.preset);
208+
<< " && cmake --log-level=WARNING --preset " << quote(configurePreset);
205209
#endif
206210
const std::string cmd = oss.str();
207211

208212
const int code = run_cmd_live_filtered(
209213
cmd,
210-
"Configuring project (preset \"" + opt.preset + "\")");
214+
"Configuring project (preset \"" + configurePreset + "\")");
211215

212216
if (code != 0)
213217
{
214-
error("CMake configure failed with preset '" + opt.preset + "'.");
218+
error("CMake configure failed with preset '" + configurePreset + "'.");
215219
hint("Run the same command manually to inspect the error:");
216220
step("cd " + projectDir.string());
217-
step("cmake --preset " + opt.preset);
221+
step("cmake --preset " + configurePreset);
218222
return code != 0 ? code : 2;
219223
}
220224

221225
progress.phase_done("Configure project", "completed");
222226
}
223227
}
224228

225-
// 2) run preset
226-
const std::string runPreset =
227-
choose_run_preset(projectDir, opt.preset, opt.runPreset);
228-
229+
// 2) Build & run preset
229230
{
230231
progress.phase_start("Build & run (preset: " + runPreset + ")");
231232
const std::string mode = opt.watch ? "dev" : "run";
@@ -489,7 +490,7 @@ namespace vix::commands::RunCommand
489490
{
490491
std::ostream &out = std::cout;
491492

492-
out << "Usage:\n";
493+
out << "Usageddd:\n";
493494
out << " vix run [name|file.cpp|manifest.vix] [options] [-- compiler/linker flags]\n\n";
494495

495496
out << "Description:\n";

src/commands/run/RunFlow.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#ifndef _WIN32
1717
#include <sys/wait.h>
18+
#include <chrono>
1819
#endif
1920

2021
using namespace vix::cli::style;
@@ -507,6 +508,28 @@ namespace vix::commands::RunCommand::detail
507508
#endif
508509
}
509510

511+
fs::path resolve_build_dir_smart(const fs::path &projectDir,
512+
const std::string &configurePreset)
513+
{
514+
fs::path buildDir = projectDir / "build";
515+
516+
if (auto binDir = preset_binary_dir(projectDir, configurePreset))
517+
return *binDir;
518+
519+
fs::path p = projectDir / ("build-" + configurePreset);
520+
if (fs::exists(p))
521+
return p;
522+
523+
if (configurePreset.rfind("dev-", 0) == 0)
524+
{
525+
fs::path p2 = projectDir / ("build-" + configurePreset.substr(4));
526+
if (fs::exists(p2))
527+
return p2;
528+
}
529+
530+
return buildDir;
531+
}
532+
510533
static std::vector<std::string> list_presets(const fs::path &dir, const std::string &kind)
511534
{
512535
#ifdef _WIN32
@@ -577,6 +600,87 @@ namespace vix::commands::RunCommand::detail
577600
return fs::exists(buildDir / "CMakeCache.txt", ec);
578601
}
579602

603+
#ifndef _WIN32
604+
static std::optional<std::chrono::file_clock::time_point>
605+
mtime_if_exists(const fs::path &p)
606+
{
607+
std::error_code ec;
608+
if (!fs::exists(p, ec) || ec)
609+
return std::nullopt;
610+
auto t = fs::last_write_time(p, ec);
611+
if (ec)
612+
return std::nullopt;
613+
return t;
614+
}
615+
616+
std::string choose_configure_preset_smart(const fs::path &projectDir,
617+
const std::string &userPreset)
618+
{
619+
620+
// Respect user choice always
621+
if (!userPreset.empty())
622+
return userPreset;
623+
624+
auto cfgs = list_presets(projectDir, "configure");
625+
if (cfgs.empty())
626+
return "dev-ninja";
627+
628+
struct Candidate
629+
{
630+
std::string preset;
631+
fs::path buildDir;
632+
std::chrono::file_clock::time_point stamp{};
633+
};
634+
635+
std::optional<Candidate> best;
636+
637+
for (const auto &preset : cfgs)
638+
{
639+
// IMPORTANT: do NOT rely on parsing binaryDir from presets json
640+
const fs::path buildDir = resolve_build_dir_smart(projectDir, preset);
641+
642+
if (!has_cmake_cache(buildDir))
643+
continue;
644+
645+
auto t = mtime_if_exists(buildDir / "CMakeCache.txt");
646+
if (!t)
647+
continue;
648+
649+
Candidate c{preset, buildDir, *t};
650+
651+
if (!best || c.stamp > best->stamp)
652+
best = c;
653+
}
654+
655+
if (std::getenv("VIX_DEBUG_PRESET"))
656+
{
657+
info("Preset candidates:");
658+
for (const auto &preset : cfgs)
659+
{
660+
const auto buildDir = resolve_build_dir_smart(projectDir, preset);
661+
step("" + preset + " -> " + buildDir.string() +
662+
(has_cmake_cache(buildDir) ? " [cache]" : " [no-cache]"));
663+
}
664+
}
665+
666+
// If we found an existing configured preset, prefer it.
667+
if (best)
668+
return best->preset;
669+
670+
// Otherwise keep a stable default:
671+
if (std::find(cfgs.begin(), cfgs.end(), "dev-ninja") != cfgs.end())
672+
return "dev-ninja";
673+
674+
return cfgs.front();
675+
}
676+
677+
#else
678+
std::string choose_configure_preset_smart(const fs::path &, const std::string &userPreset)
679+
{
680+
return userPreset.empty() ? std::string("dev-ninja") : userPreset;
681+
}
682+
#endif
683+
580684
std::optional<fs::path> choose_project_dir(const Options &opt, const fs::path &cwd)
581685
{
582686
auto exists_cml = [](const fs::path &p)

0 commit comments

Comments
 (0)