@@ -137,6 +137,122 @@ namespace
137137 return out;
138138 }
139139
140+ static std::optional<fs::path> resolve_runnable_executable (
141+ const fs::path &buildDir,
142+ const std::string &projectName)
143+ {
144+ auto executable_name = [](const std::string &name) -> std::string
145+ {
146+ #ifdef _WIN32
147+ return name + " .exe" ;
148+ #else
149+ return name;
150+ #endif
151+ };
152+
153+ auto is_executable_candidate = [](const fs::path &p) -> bool
154+ {
155+ std::error_code ec{};
156+
157+ if (!fs::is_regular_file (p, ec) || ec)
158+ return false ;
159+
160+ #ifdef _WIN32
161+ return p.extension () == " .exe" ;
162+ #else
163+ const auto perms = fs::status (p, ec).permissions ();
164+ if (ec)
165+ return false ;
166+
167+ using pr = fs::perms;
168+ return (perms & pr::owner_exec) != pr::none ||
169+ (perms & pr::group_exec) != pr::none ||
170+ (perms & pr::others_exec) != pr::none;
171+ #endif
172+ };
173+
174+ auto looks_like_test_binary = [](const fs::path &p) -> bool
175+ {
176+ const std::string n = p.filename ().string ();
177+ return n.find (" _test" ) != std::string::npos ||
178+ n.find (" _tests" ) != std::string::npos ||
179+ n.rfind (" test_" , 0 ) == 0 ;
180+ };
181+
182+ const std::string exeFileName = executable_name (projectName);
183+
184+ // 1) Exact common locations
185+ const std::vector<fs::path> preferred = {
186+ buildDir / exeFileName,
187+ buildDir / " bin" / exeFileName,
188+ buildDir / " src" / exeFileName};
189+
190+ for (const auto &p : preferred)
191+ {
192+ if (is_executable_candidate (p))
193+ return p;
194+ }
195+
196+ // 2) Recursive scan
197+ std::vector<fs::path> exactNameCandidates;
198+ std::vector<fs::path> otherCandidates;
199+
200+ std::error_code ec{};
201+ for (auto it = fs::recursive_directory_iterator (
202+ buildDir,
203+ fs::directory_options::skip_permission_denied,
204+ ec);
205+ !ec && it != fs::recursive_directory_iterator ();
206+ ++it)
207+ {
208+ const fs::path p = it->path ();
209+
210+ if (p.string ().find (" CMakeFiles" ) != std::string::npos)
211+ continue ;
212+
213+ if (!is_executable_candidate (p))
214+ continue ;
215+
216+ if (looks_like_test_binary (p))
217+ continue ;
218+
219+ #ifdef _WIN32
220+ const std::string baseName = p.stem ().string ();
221+ #else
222+ const std::string baseName = p.filename ().string ();
223+ #endif
224+
225+ if (baseName == projectName)
226+ exactNameCandidates.push_back (p);
227+ else
228+ otherCandidates.push_back (p);
229+ }
230+
231+ auto prefer_bin_path = [](const fs::path &a, const fs::path &b) -> bool
232+ {
233+ const bool aBin = a.string ().find (" /bin/" ) != std::string::npos ||
234+ a.string ().find (" \\ bin\\ " ) != std::string::npos;
235+ const bool bBin = b.string ().find (" /bin/" ) != std::string::npos ||
236+ b.string ().find (" \\ bin\\ " ) != std::string::npos;
237+
238+ if (aBin != bBin)
239+ return aBin;
240+
241+ return a.string ().size () < b.string ().size ();
242+ };
243+
244+ if (!exactNameCandidates.empty ())
245+ {
246+ std::sort (exactNameCandidates.begin (), exactNameCandidates.end (), prefer_bin_path);
247+ return exactNameCandidates.front ();
248+ }
249+
250+ if (otherCandidates.size () == 1 )
251+ return otherCandidates.front ();
252+
253+ return std::nullopt ;
254+ }
255+
140256 void apply_manifest_auto_deps_includes (Options &opt, const fs::path &manifestFile)
141257 {
142258 const fs::path manifestDir = manifestFile.parent_path ();
@@ -797,10 +913,18 @@ namespace
797913 progress.phase_start (" Run application" );
798914
799915 const std::string exeName = projectDir.filename ().string ();
800- fs::path exePath = buildDir / exeName;
801- #ifdef _WIN32
802- exePath += " .exe" ;
803- #endif
916+ auto exePathOpt = resolve_runnable_executable (buildDir, exeName);
917+
918+ if (!exePathOpt)
919+ {
920+ error (" Built executable not found for project: " + exeName);
921+ hint (" Resolved build directory: " + buildDir.string ());
922+ hint (" No runnable application target could be resolved automatically." );
923+ hint (" If your executable uses a custom output path or custom target name, add a manifest field to specify it." );
924+ return 1 ;
925+ }
926+
927+ fs::path exePath = *exePathOpt;
804928
805929 if (!fs::exists (exePath))
806930 {
@@ -960,10 +1084,18 @@ namespace
9601084 std::cout << " \n " ;
9611085
9621086 const std::string exeName = projectDir.filename ().string ();
963- fs::path exePath = buildDir / exeName;
964- #ifdef _WIN32
965- exePath += " .exe" ;
966- #endif
1087+ auto exePathOpt = resolve_runnable_executable (buildDir, exeName);
1088+
1089+ if (!exePathOpt)
1090+ {
1091+ error (" Built executable not found for project: " + exeName);
1092+ hint (" Resolved build directory: " + buildDir.string ());
1093+ hint (" No runnable application target could be resolved automatically." );
1094+ hint (" If your executable uses a custom output path or custom target name, add a manifest field to specify it." );
1095+ return 1 ;
1096+ }
1097+
1098+ fs::path exePath = *exePathOpt;
9671099
9681100 if (exeName == " vix" )
9691101 {
@@ -1161,7 +1293,9 @@ namespace vix::commands::RunCommand
11611293 out << " --auto-deps=local Same as --auto-deps\n " ;
11621294 out << " --auto-deps=up Also search deps in parent folders (future/optional)\n " ;
11631295 out << " --san Enable ASan and UBSan\n " ;
1164- out << " --ubsan Enable UBSan only\n\n " ;
1296+ out << " --ubsan Enable UBSan only\n " ;
1297+ out << " --with-sqlite Enable SQLite support for script mode\n " ;
1298+ out << " --with-mysql Enable MySQL support for script mode\n\n " ;
11651299
11661300 out << " Documentation:\n " ;
11671301 out << " --docs Enable auto docs (sets VIX_DOCS=1)\n " ;
@@ -1200,6 +1334,8 @@ namespace vix::commands::RunCommand
12001334 out << " # Script mode (.cpp)\n " ;
12011335 out << " vix run main.cpp --cwd ./data --args --config --args config.json\n " ;
12021336 out << " vix run main.cpp --run hello 123 test\n " ;
1337+ out << " vix run main.cpp --with-sqlite\n " ;
1338+ out << " vix run main.cpp --with-mysql\n " ;
12031339 out << " vix run main.cpp -- -O2 -DNDEBUG --run hello 123\n " ;
12041340 out << " vix run main.cpp -- -lssl -lcrypto\n\n " ;
12051341
0 commit comments