Skip to content

Commit e3e8737

Browse files
committed
fix(errors): gate follow-up hints on handled build errors
2 parents d971fd3 + b19fe31 commit e3e8737

10 files changed

Lines changed: 157 additions & 44 deletions

File tree

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939

4040
# debug information files
4141
*.dwo
42-
build/
42+
build-*/
4343
.vscode/
4444
vix.log
4545
cmd.md

include/vix/cli/ErrorHandler.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace vix::cli
2323
class ErrorHandler
2424
{
2525
public:
26-
static void printBuildErrors(
26+
static bool printBuildErrors(
2727
const std::string &buildLog,
2828
const fs::path &sourceFile,
2929
const std::string &contextMessage = "Script build failed");
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
*
3+
* @file BuildErrorDetectors.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2025, 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+
*/
14+
#ifndef VIX_BUILD_ERROR_DETECTORS_HPP
15+
#define VIX_BUILD_ERROR_DETECTORS_HPP
16+
17+
#include <string_view>
18+
19+
namespace vix::cli::errors::build
20+
{
21+
bool handleBuildErrors(std::string_view log);
22+
}
23+
24+
#endif
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
*
3+
* @file CMakeBuildErrors.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2025, 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+
*/
14+
#ifndef VIX_CMAKE_BUILD_ERRORS_HPP
15+
#define VIX_CMAKE_BUILD_ERRORS_HPP
16+
17+
#include <string_view>
18+
19+
namespace vix::cli::errors::build
20+
{
21+
bool handleCMakeBuildError(std::string_view log);
22+
}
23+
24+
#endif

src/ErrorHandler.cpp

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@
1111
* Vix.cpp
1212
*
1313
*/
14-
#include "vix/cli/ErrorHandler.hpp"
15-
16-
#include "vix/cli/errors/ClangGccParser.hpp"
17-
#include "vix/cli/errors/CompilerError.hpp"
18-
#include "vix/cli/errors/ErrorContext.hpp"
19-
#include "vix/cli/errors/ErrorPipeline.hpp"
20-
#include "vix/cli/errors/RawLogDetectors.hpp"
21-
#include "vix/cli/errors/CodeFrame.hpp"
14+
#include <vix/cli/ErrorHandler.hpp>
15+
16+
#include <vix/cli/errors/ClangGccParser.hpp>
17+
#include <vix/cli/errors/CompilerError.hpp>
18+
#include <vix/cli/errors/ErrorContext.hpp>
19+
#include <vix/cli/errors/ErrorPipeline.hpp>
20+
#include <vix/cli/errors/RawLogDetectors.hpp>
21+
#include <vix/cli/errors/CodeFrame.hpp>
22+
#include <vix/cli/errors/build/BuildErrorDetectors.hpp>
2223
#include <vix/utils/Env.hpp>
24+
2325
#include <iostream>
2426
#include <sstream>
2527
#include <unordered_map>
@@ -194,7 +196,7 @@ namespace
194196

195197
namespace vix::cli
196198
{
197-
void ErrorHandler::printBuildErrors(
199+
bool ErrorHandler::printBuildErrors(
198200
const std::string &buildLog,
199201
const fs::path &sourceFile,
200202
const std::string &contextMessage)
@@ -212,24 +214,25 @@ namespace vix::cli
212214
<< GRAY << "compiler output:\n"
213215
<< RESET;
214216
std::cerr << cleanedLog << "\n";
215-
return;
217+
return true;
216218
}
217219

218220
if (RawLogDetectors::handleLinkerOrSanitizer(cleanedLog, sourceFile, contextMessage))
219-
return;
221+
return true;
222+
223+
if (vix::cli::errors::build::handleBuildErrors(cleanedLog))
224+
return true;
220225

221226
error(contextMessage + " (see compiler output below):");
222227
std::cerr << cleanedLog << "\n";
223-
return;
228+
return false;
224229
}
225230

226231
ErrorContext ctx{sourceFile, contextMessage, cleanedLog};
227232
ErrorPipeline pipeline;
228233

229234
if (pipeline.tryHandle(errors, ctx))
230-
{
231-
return;
232-
}
235+
return true;
233236

234237
std::unordered_map<std::string, int> counts;
235238
for (const auto &e : errors)
@@ -246,19 +249,16 @@ namespace vix::cli
246249
{
247250
std::string key = e.file + "|" + e.message;
248251
if (seen.insert(key).second)
249-
{
250252
unique.push_back(e);
251-
}
252253
}
253254

254255
if (unique.empty())
255256
{
256257
error(contextMessage + " (no unique errors found, see compiler output below):");
257258
std::cerr << buildLog << "\n";
258-
return;
259+
return false;
259260
}
260261

261-
// Generic build error header
262262
error(contextMessage + ":");
263263

264264
CodeFrameOptions cf;
@@ -273,19 +273,15 @@ namespace vix::cli
273273
const auto &err = unique[i];
274274

275275
std::cerr << "\n";
276-
277276
::printSingleError(err);
278-
279277
::printHints(err);
280278

281-
{
282-
ErrorContext frameCtx{
283-
err.file,
284-
contextMessage,
285-
cleanedLog};
279+
ErrorContext frameCtx{
280+
err.file,
281+
contextMessage,
282+
cleanedLog};
286283

287-
printCodeFrame(err, frameCtx, cf);
288-
}
284+
printCodeFrame(err, frameCtx, cf);
289285

290286
const std::string key = err.file + "|" + err.message;
291287
auto it = counts.find(key);
@@ -305,5 +301,6 @@ namespace vix::cli
305301
}
306302

307303
std::cerr << "\nSource file: " << sourceFile << "\n";
304+
return true;
308305
}
309306
} // namespace vix::cli

src/commands/BuildCommand.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -993,12 +993,12 @@ namespace vix::commands::BuildCommand
993993
out.discard();
994994

995995
const std::string log = util::read_text_file_or_empty(plan_.configureLog);
996-
vix::cli::ErrorHandler::printBuildErrors(
996+
const bool handled = vix::cli::ErrorHandler::printBuildErrors(
997997
log,
998998
plan_.projectDir / "CMakeLists.txt",
999999
"CMake configure failed");
10001000

1001-
if (!opt_.quiet)
1001+
if (!opt_.quiet && !handled)
10021002
{
10031003
util::log_hint_if(opt_.quiet, "Command:");
10041004
step(r.displayCommand);
@@ -1089,12 +1089,12 @@ namespace vix::commands::BuildCommand
10891089
out.discard();
10901090

10911091
const std::string log = util::read_text_file_or_empty(plan_.buildLog);
1092-
vix::cli::ErrorHandler::printBuildErrors(
1092+
const bool handled = vix::cli::ErrorHandler::printBuildErrors(
10931093
log,
10941094
plan_.projectDir / "CMakeLists.txt",
10951095
"Build failed");
10961096

1097-
if (!opt_.quiet)
1097+
if (!opt_.quiet && !handled)
10981098
{
10991099
util::log_hint_if(opt_.quiet, "Command:");
11001100
step(r.displayCommand);

src/commands/RunCommand.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -651,9 +651,11 @@ namespace vix::commands::RunCommand
651651

652652
if (buildExit != 0)
653653
{
654+
bool handled = false;
655+
654656
if (!log.empty())
655657
{
656-
vix::cli::ErrorHandler::printBuildErrors(
658+
handled = vix::cli::ErrorHandler::printBuildErrors(
657659
log,
658660
projectDir,
659661
"Build failed (preset '" + buildPreset + "')");
@@ -664,9 +666,12 @@ namespace vix::commands::RunCommand
664666
std::to_string(buildExit) + ").");
665667
}
666668

667-
hint("Run the same command manually:");
668-
step("cd " + projectDir.string());
669-
step("cmake --build --preset " + buildPreset);
669+
if (!handled)
670+
{
671+
hint("Run the same command manually:");
672+
step("cd " + projectDir.string());
673+
step("cmake --build --preset " + buildPreset);
674+
}
670675

671676
return buildExit != 0 ? buildExit : 2;
672677
}
@@ -965,16 +970,22 @@ namespace vix::commands::RunCommand
965970
(void)captureCode;
966971
}
967972

973+
bool handled = false;
974+
968975
if (!buildLog.empty())
969976
{
970-
vix::cli::ErrorHandler::printBuildErrors(
977+
handled = vix::cli::ErrorHandler::printBuildErrors(
971978
buildLog,
972979
buildDir,
973980
"Build failed (fallback build/)");
974981
}
975982
else
976983
{
977984
error("Build failed (fallback build/, code " + std::to_string(code) + ").");
985+
}
986+
987+
if (!handled)
988+
{
978989
hint("Check the build command manually in your terminal.");
979990
}
980991

src/commands/run/RunScript.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -565,11 +565,10 @@ namespace vix::commands::RunCommand::detail
565565

566566
if (!logContent.empty())
567567
{
568-
vix::cli::ErrorHandler::printBuildErrors(
568+
handled = vix::cli::ErrorHandler::printBuildErrors(
569569
logContent,
570570
script,
571571
"Script build failed");
572-
handled = true;
573572
}
574573
else
575574
{
@@ -923,11 +922,11 @@ namespace vix::commands::RunCommand::detail
923922
{
924923
print_script_runtime_args_hint();
925924
}
926-
vix::cli::ErrorHandler::printBuildErrors(
925+
926+
handled = vix::cli::ErrorHandler::printBuildErrors(
927927
logContent,
928928
script,
929929
"Script build failed");
930-
handled = true; // error already printed
931930
}
932931
else
933932
{
@@ -1387,7 +1386,7 @@ namespace vix::commands::RunCommand::detail
13871386
{
13881387
if (!buildLog.empty())
13891388
{
1390-
vix::cli::ErrorHandler::printBuildErrors(
1389+
(void)vix::cli::ErrorHandler::printBuildErrors(
13911390
buildLog,
13921391
buildDir,
13931392
"Build failed in dev mode (build-dev/)");
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#include <vix/cli/errors/build/BuildErrorDetectors.hpp>
2+
#include <vix/cli/errors/build/CMakeBuildErrors.hpp>
3+
4+
namespace vix::cli::errors::build
5+
{
6+
bool handleBuildErrors(std::string_view log)
7+
{
8+
if (handleCMakeBuildError(log))
9+
return true;
10+
11+
return false;
12+
}
13+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
*
3+
* @file CMakeBuildErrors.hpp
4+
* @author Gaspard Kirira
5+
*
6+
* Copyright 2025, 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+
*/
14+
#include <vix/cli/errors/build/CMakeBuildErrors.hpp>
15+
16+
#include <iostream>
17+
#include <string>
18+
19+
#include <vix/cli/Style.hpp>
20+
21+
using namespace vix::cli::style;
22+
23+
namespace vix::cli::errors::build
24+
{
25+
bool handleCMakeBuildError(std::string_view log)
26+
{
27+
const bool cacheDirMismatch =
28+
log.find("The current CMakeCache.txt directory") != std::string_view::npos;
29+
30+
const bool sourceMismatch =
31+
log.find("does not match the source") != std::string_view::npos &&
32+
log.find("used to generate cache") != std::string_view::npos;
33+
34+
if (!cacheDirMismatch && !sourceMismatch)
35+
return false;
36+
37+
error("CMake configure failed: stale build cache detected.");
38+
hint("Your build directory was generated from another project location.");
39+
hint("Remove the old build directory and reconfigure.");
40+
hint("Recommended: vix build --clean");
41+
hint("Manual fix: rm -rf build-ninja build-dev build-release");
42+
43+
return true;
44+
}
45+
}

0 commit comments

Comments
 (0)