Skip to content

Commit 4e8f40a

Browse files
committed
fix(cli): improve CMake error output
2 parents 9f52096 + 5449676 commit 4e8f40a

2 files changed

Lines changed: 127 additions & 18 deletions

File tree

src/commands/BuildCommand.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,6 @@ namespace vix::commands::BuildCommand
547547
else if (a == "--verbose" || a == "-v")
548548
{
549549
o.verbose = true;
550-
o.cmakeVerbose = true;
551550
}
552551
else if (a == "--explain")
553552
{
@@ -3262,6 +3261,12 @@ namespace vix::commands::BuildCommand
32623261
plan_.cmakeSourceDir / "CMakeLists.txt",
32633262
"CMake configure failed");
32643263

3264+
if (opt_.verbose && !log.empty())
3265+
{
3266+
std::cerr << "\nCMake output:\n";
3267+
std::cerr << log << "\n";
3268+
}
3269+
32653270
if (!opt_.quiet)
32663271
{
32673272
if (!handled)

src/errors/build/CMakeBuildErrors.cpp

Lines changed: 121 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -186,34 +186,89 @@ namespace vix::cli::errors::build
186186
return message;
187187
}
188188

189-
// Returns the single most informative line from the first CMake Error block.
190-
// Prefers the content after the first colon on the opening "CMake Error" line;
191-
// falls back to the entire block if the opening line is content-free.
192189
std::string first_cmake_error_message(std::string_view log)
193190
{
194191
const std::size_t pos = log.find("CMake Error");
195192
if (pos == std::string_view::npos)
196193
return {};
197194

198195
const std::size_t lineEnd = log.find('\n', pos);
196+
199197
const std::string firstLine =
200198
(lineEnd == std::string_view::npos)
201199
? std::string(log.substr(pos))
202200
: std::string(log.substr(pos, lineEnd - pos));
203201

204-
// Try to get the message that follows the first colon on the error line.
205-
const std::size_t colon = firstLine.find(':');
206-
if (colon != std::string::npos && colon + 1 < firstLine.size())
202+
// CMake form:
203+
// CMake Error at CMakeLists.txt:135 (message):
204+
//
205+
// Do not split at the first ':' because that belongs to file:line.
206+
// Only use same-line text after the final "):" when it exists.
207+
const std::size_t commandEnd = firstLine.find("):");
208+
if (commandEnd != std::string::npos)
207209
{
208-
std::string sameLine = trim_copy(firstLine.substr(colon + 1));
210+
const std::string sameLine =
211+
trim_copy(firstLine.substr(commandEnd + 2));
212+
209213
if (!sameLine.empty() && !is_cmake_noise_line(sameLine))
210214
return sameLine;
211215
}
212216

213-
// Fall back: collect a multi-line block, skipping noise.
217+
// CMake form:
218+
// CMake Error: some message
219+
//
220+
// This one has no file:line prefix, so splitting after "CMake Error:"
221+
// is safe.
222+
constexpr std::string_view directPrefix = "CMake Error:";
223+
if (starts_with(firstLine, directPrefix))
224+
{
225+
const std::string sameLine =
226+
trim_copy(firstLine.substr(directPrefix.size()));
227+
228+
if (!sameLine.empty() && !is_cmake_noise_line(sameLine))
229+
return sameLine;
230+
}
231+
232+
if (lineEnd == std::string_view::npos)
233+
return first_cmake_error_block(log);
234+
235+
std::istringstream stream{
236+
std::string(log.substr(lineEnd + 1))};
237+
238+
std::string message;
239+
std::string line;
240+
241+
while (std::getline(stream, line))
242+
{
243+
const std::string trimmed = trim_copy(line);
244+
245+
if (trimmed.empty())
246+
continue;
247+
248+
if (starts_with(trimmed, "CMake Error"))
249+
break;
250+
251+
if (is_cmake_noise_line(trimmed))
252+
break;
253+
254+
if (starts_with(trimmed, "-- Configuring incomplete") ||
255+
starts_with(trimmed, "-- Configuring done") ||
256+
starts_with(trimmed, "-- Generating done"))
257+
{
258+
break;
259+
}
260+
261+
if (!message.empty())
262+
message += '\n';
263+
264+
message += trimmed;
265+
}
266+
267+
if (!message.empty())
268+
return message;
269+
214270
return first_cmake_error_block(log);
215271
}
216-
217272
// -------------------------------------------------------------------------
218273
// Output helpers (preserve existing Vix CLI style)
219274
// -------------------------------------------------------------------------
@@ -244,7 +299,30 @@ namespace vix::cli::errors::build
244299
if (value.empty())
245300
return;
246301

247-
std::cerr << PAD << label << value << "\n";
302+
const std::string text(value);
303+
304+
const std::size_t firstNewline = text.find('\n');
305+
306+
if (firstNewline == std::string::npos)
307+
{
308+
std::cerr << PAD << label << text << "\n";
309+
return;
310+
}
311+
312+
std::cerr << PAD << label << "\n";
313+
314+
std::istringstream in(text);
315+
std::string line;
316+
317+
while (std::getline(in, line))
318+
{
319+
const std::string trimmed = trim_copy(line);
320+
321+
if (trimmed.empty())
322+
continue;
323+
324+
std::cerr << PAD << " " << trimmed << "\n";
325+
}
248326
}
249327

250328
void print_colored_field(std::string_view label,
@@ -254,12 +332,38 @@ namespace vix::cli::errors::build
254332
if (value.empty())
255333
return;
256334

257-
std::cerr << PAD
258-
<< label
259-
<< color
260-
<< value
261-
<< RESET
262-
<< "\n";
335+
const std::string text(value);
336+
337+
if (text.find('\n') == std::string::npos)
338+
{
339+
std::cerr << PAD
340+
<< label
341+
<< color
342+
<< text
343+
<< RESET
344+
<< "\n";
345+
return;
346+
}
347+
348+
std::cerr << PAD << label << "\n";
349+
350+
std::istringstream in(text);
351+
std::string line;
352+
353+
while (std::getline(in, line))
354+
{
355+
const std::string trimmed = trim_copy(line);
356+
357+
if (trimmed.empty())
358+
continue;
359+
360+
std::cerr << PAD
361+
<< " "
362+
<< color
363+
<< trimmed
364+
<< RESET
365+
<< "\n";
366+
}
263367
}
264368

265369
// -------------------------------------------------------------------------
@@ -1569,7 +1673,7 @@ namespace vix::cli::errors::build
15691673
"reason: ",
15701674
message.empty() ? "unclassified CMake error" : message);
15711675

1572-
print_hint("run vix build --verbose to inspect the full CMake output");
1676+
print_hint("check the CMake message above or inspect build-ninja/configure.log");
15731677
return true;
15741678
}
15751679

0 commit comments

Comments
 (0)