Skip to content

Commit f76d32e

Browse files
committed
Merge branch 'dev'
2 parents cb21fc9 + 12b79f8 commit f76d32e

10 files changed

Lines changed: 1297 additions & 26 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
*
3+
* @file DevChangeClassifier.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*
13+
* Dev mode file change classifier
14+
*
15+
*/
16+
17+
#ifndef VIX_CLI_COMMANDS_RUN_DEV_DEV_CHANGE_CLASSIFIER_HPP
18+
#define VIX_CLI_COMMANDS_RUN_DEV_DEV_CHANGE_CLASSIFIER_HPP
19+
20+
#include <filesystem>
21+
#include <string>
22+
23+
namespace vix::commands::RunCommand::dev
24+
{
25+
namespace fs = std::filesystem;
26+
27+
enum class DevChangeKind
28+
{
29+
Ignore,
30+
RebuildOnly,
31+
ReconfigureAndRebuild
32+
};
33+
34+
std::string to_string(DevChangeKind kind);
35+
36+
class DevChangeClassifier
37+
{
38+
public:
39+
DevChangeClassifier() = default;
40+
41+
DevChangeKind classify(
42+
const fs::path &projectDir,
43+
const fs::path &changedPath) const;
44+
45+
private:
46+
bool should_ignore_path(
47+
const fs::path &projectDir,
48+
const fs::path &changedPath) const;
49+
50+
bool is_source_file(const fs::path &path) const;
51+
bool is_header_file(const fs::path &path) const;
52+
bool is_config_file(const fs::path &path) const;
53+
};
54+
55+
} // namespace vix::commands::RunCommand::dev
56+
57+
#endif // VIX_CLI_COMMANDS_RUN_DEV_DEV_CHANGE_CLASSIFIER_HPP
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
*
3+
* @file DevRebuilder.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*
13+
* Dev mode project rebuilder
14+
*
15+
*/
16+
17+
#ifndef VIX_CLI_COMMANDS_RUN_DEV_DEV_REBUILDER_HPP
18+
#define VIX_CLI_COMMANDS_RUN_DEV_DEV_REBUILDER_HPP
19+
20+
#include <filesystem>
21+
#include <string>
22+
23+
#include <vix/cli/commands/run/RunDetail.hpp>
24+
25+
namespace vix::commands::RunCommand::dev
26+
{
27+
namespace fs = std::filesystem;
28+
namespace detail = vix::commands::RunCommand::detail;
29+
30+
struct DevRebuilderOptions
31+
{
32+
fs::path projectDir;
33+
fs::path buildDir;
34+
std::string targetName;
35+
36+
detail::Options runOptions;
37+
38+
bool quiet{false};
39+
};
40+
41+
struct DevRebuilderResult
42+
{
43+
bool ok{false};
44+
bool configured{false};
45+
bool built{false};
46+
47+
int exitCode{0};
48+
std::string message;
49+
std::string output;
50+
};
51+
52+
class DevRebuilder
53+
{
54+
public:
55+
explicit DevRebuilder(DevRebuilderOptions options);
56+
57+
const DevRebuilderOptions &options() const;
58+
59+
DevRebuilderResult ensure_configured() const;
60+
DevRebuilderResult rebuild() const;
61+
DevRebuilderResult reconfigure_and_rebuild() const;
62+
63+
private:
64+
DevRebuilderOptions options_;
65+
66+
bool has_cmake_cache() const;
67+
68+
std::string configure_command() const;
69+
std::string build_command() const;
70+
71+
DevRebuilderResult run_configure_command() const;
72+
DevRebuilderResult run_build_command() const;
73+
};
74+
75+
} // namespace vix::commands::RunCommand::dev
76+
77+
#endif // VIX_CLI_COMMANDS_RUN_DEV_DEV_REBUILDER_HPP
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
*
3+
* @file DevSession.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2026, Gaspard Kirira. All rights reserved.
7+
* https://github.com/vixcpp/vix
8+
* Use of this source code is governed by a MIT license
9+
* that can be found in the License file.
10+
*
11+
* Vix.cpp
12+
*
13+
* Dev mode session orchestrator
14+
*
15+
*/
16+
17+
#ifndef VIX_CLI_COMMANDS_RUN_DEV_DEV_SESSION_HPP
18+
#define VIX_CLI_COMMANDS_RUN_DEV_DEV_SESSION_HPP
19+
20+
#include <chrono>
21+
#include <filesystem>
22+
#include <map>
23+
#include <string>
24+
#include <vector>
25+
#include <optional>
26+
27+
#include <vix/cli/commands/run/RunDetail.hpp>
28+
#include <vix/cli/commands/run/dev/DevChangeClassifier.hpp>
29+
#include <vix/cli/commands/run/dev/DevRebuilder.hpp>
30+
31+
namespace vix::commands::RunCommand::dev
32+
{
33+
namespace fs = std::filesystem;
34+
namespace detail = vix::commands::RunCommand::detail;
35+
36+
struct DevSessionOptions
37+
{
38+
fs::path projectDir;
39+
fs::path buildDir;
40+
std::string targetName;
41+
42+
detail::Options runOptions;
43+
44+
std::chrono::milliseconds pollInterval{300};
45+
std::chrono::milliseconds debounceDelay{200};
46+
47+
bool quiet{false};
48+
};
49+
50+
struct DevSessionResult
51+
{
52+
int exitCode{0};
53+
std::string message;
54+
};
55+
56+
struct DevFileSnapshot
57+
{
58+
std::map<std::string, fs::file_time_type> files;
59+
60+
bool empty() const;
61+
};
62+
63+
struct DevDetectedChange
64+
{
65+
fs::path path;
66+
DevChangeKind kind{DevChangeKind::Ignore};
67+
68+
bool valid() const;
69+
};
70+
71+
class DevSession
72+
{
73+
public:
74+
explicit DevSession(DevSessionOptions options);
75+
76+
const DevSessionOptions &options() const;
77+
78+
DevSessionResult run();
79+
80+
private:
81+
DevSessionOptions options_;
82+
DevChangeClassifier classifier_;
83+
DevRebuilder rebuilder_;
84+
85+
DevFileSnapshot snapshot_project() const;
86+
87+
std::vector<DevDetectedChange> detect_changes(
88+
const DevFileSnapshot &before,
89+
const DevFileSnapshot &after) const;
90+
91+
DevChangeKind strongest_change_kind(
92+
const std::vector<DevDetectedChange> &changes) const;
93+
94+
DevDetectedChange first_relevant_change(
95+
const std::vector<DevDetectedChange> &changes) const;
96+
97+
DevDetectedChange wait_for_change(
98+
DevFileSnapshot &snapshot) const;
99+
100+
int rebuild_for_change(DevChangeKind kind) const;
101+
102+
std::optional<fs::path> executable_path() const;
103+
104+
#ifndef _WIN32
105+
int run_child_once(const fs::path &exePath);
106+
void stop_child(int pid) const;
107+
#endif
108+
109+
bool should_skip_directory(const fs::path &path) const;
110+
};
111+
112+
} // namespace vix::commands::RunCommand::dev
113+
114+
#endif // VIX_CLI_COMMANDS_RUN_DEV_DEV_SESSION_HPP

src/commands/BuildCommand.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1849,7 +1849,7 @@ namespace vix::commands::BuildCommand
18491849
}
18501850
}
18511851

1852-
if (can_use_graph_build(opt_, plan_, scan))
1852+
if (graph_executor_enabled() && can_use_graph_build(opt_, plan_, scan))
18531853
{
18541854
return run_graph_build(
18551855
graph,

src/commands/DevCommand.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <algorithm>
2020
#include <string>
2121
#include <vector>
22-
#include <iostream>
2322

2423
#include <cstdlib>
2524
#ifdef _WIN32
@@ -56,11 +55,6 @@ namespace vix::commands::DevCommand
5655

5756
forwarded.emplace_back("--dev-mode");
5857

59-
std::cerr << "[vix:dev] forwarding to run:";
60-
for (const auto &arg : forwarded)
61-
std::cerr << " " << arg;
62-
std::cerr << "\n";
63-
6458
return vix::commands::RunCommand::run(forwarded);
6559
}
6660

src/commands/RunCommand.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,12 +1600,6 @@ namespace vix::commands::RunCommand
16001600
if (opt.watch)
16011601
{
16021602
#ifndef _WIN32
1603-
std::cerr << "[vix:dev] entering project watch from resolved target:"
1604-
<< " watch=" << (opt.watch ? "1" : "0")
1605-
<< " devMode=" << (opt.devMode ? "1" : "0")
1606-
<< " projectDir=" << projectDir.string()
1607-
<< "\n";
1608-
16091603
return run_project_watch(opt, projectDir);
16101604
#else
16111605
hint("Project watch mode is not yet implemented on Windows; running once without auto-reload.");
@@ -1641,13 +1635,6 @@ namespace vix::commands::RunCommand
16411635

16421636
warn_if_env_file_missing(projectDir);
16431637

1644-
std::cerr << "[vix:dev] before project watch check:"
1645-
<< " watch=" << (opt.watch ? "1" : "0")
1646-
<< " devMode=" << (opt.devMode ? "1" : "0")
1647-
<< " singleCpp=" << (opt.singleCpp ? "1" : "0")
1648-
<< " projectDir=" << projectDir.string()
1649-
<< "\n";
1650-
16511638
if (!opt.singleCpp && opt.watch)
16521639
{
16531640
#ifndef _WIN32

src/commands/run/RunScript.cpp

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <vix/cli/errors/RawLogDetectors.hpp>
2323
#include <vix/cli/Style.hpp>
2424
#include <vix/utils/Env.hpp>
25+
#include <vix/cli/commands/run/dev/DevSession.hpp>
2526

2627
#include <algorithm>
2728
#include <cerrno>
@@ -1562,19 +1563,29 @@ namespace vix::commands::RunCommand::detail
15621563
{
15631564
#ifndef _WIN32
15641565

1565-
std::cerr << "[vix:dev] run_project_watch entered:"
1566-
<< " watch=" << (opt.watch ? "1" : "0")
1567-
<< " devMode=" << (opt.devMode ? "1" : "0")
1568-
<< " projectDir=" << projectDir.string()
1569-
<< "\n";
1570-
15711566
using Clock = std::chrono::steady_clock;
15721567
namespace fs = std::filesystem;
15731568

15741569
const bool devMode = opt.devMode;
15751570
const fs::path buildDir = projectDir / (devMode ? "build-ninja" : "build-dev");
15761571
const std::string targetName = projectDir.filename().string();
15771572

1573+
if (devMode)
1574+
{
1575+
vix::commands::RunCommand::dev::DevSession session(
1576+
vix::commands::RunCommand::dev::DevSessionOptions{
1577+
projectDir,
1578+
buildDir,
1579+
targetName,
1580+
opt,
1581+
std::chrono::milliseconds(300),
1582+
std::chrono::milliseconds(200),
1583+
opt.quiet});
1584+
1585+
const auto result = session.run();
1586+
return result.exitCode;
1587+
}
1588+
15781589
if (devMode)
15791590
{
15801591
info("Vix dev mode enabled.");

0 commit comments

Comments
 (0)