Unverified Commit 6f0cfc95 authored by stuartmorgan's avatar stuartmorgan Committed by GitHub

Surface Windows build errors in non-verbose mode (#63707)

parent 89f004e0
...@@ -257,6 +257,9 @@ abstract class ProcessUtils { ...@@ -257,6 +257,9 @@ abstract class ProcessUtils {
/// If [filter] is non-null, all lines that do not match it are removed. If /// If [filter] is non-null, all lines that do not match it are removed. If
/// [mapFunction] is present, all lines that match [filter] are also forwarded /// [mapFunction] is present, all lines that match [filter] are also forwarded
/// to [mapFunction] for further processing. /// to [mapFunction] for further processing.
///
/// If [stdoutErrorMatcher] is non-null, matching lines from stdout will be
/// treated as errors, just as if they had been logged to stderr instead.
Future<int> stream( Future<int> stream(
List<String> cmd, { List<String> cmd, {
String workingDirectory, String workingDirectory,
...@@ -264,6 +267,7 @@ abstract class ProcessUtils { ...@@ -264,6 +267,7 @@ abstract class ProcessUtils {
String prefix = '', String prefix = '',
bool trace = false, bool trace = false,
RegExp filter, RegExp filter,
RegExp stdoutErrorMatcher,
StringConverter mapFunction, StringConverter mapFunction,
Map<String, String> environment, Map<String, String> environment,
}); });
...@@ -485,6 +489,7 @@ class _DefaultProcessUtils implements ProcessUtils { ...@@ -485,6 +489,7 @@ class _DefaultProcessUtils implements ProcessUtils {
String prefix = '', String prefix = '',
bool trace = false, bool trace = false,
RegExp filter, RegExp filter,
RegExp stdoutErrorMatcher,
StringConverter mapFunction, StringConverter mapFunction,
Map<String, String> environment, Map<String, String> environment,
}) async { }) async {
...@@ -504,7 +509,9 @@ class _DefaultProcessUtils implements ProcessUtils { ...@@ -504,7 +509,9 @@ class _DefaultProcessUtils implements ProcessUtils {
} }
if (line != null) { if (line != null) {
final String message = '$prefix$line'; final String message = '$prefix$line';
if (trace) { if (stdoutErrorMatcher?.hasMatch(line) == true) {
_logger.printError(message, wrap: false);
} else if (trace) {
_logger.printTrace(message); _logger.printTrace(message);
} else { } else {
_logger.printStatus(message, wrap: false); _logger.printStatus(message, wrap: false);
......
...@@ -107,6 +107,10 @@ Future<void> _runCmakeGeneration(String cmakePath, Directory buildDir, Directory ...@@ -107,6 +107,10 @@ Future<void> _runCmakeGeneration(String cmakePath, Directory buildDir, Directory
Future<void> _runBuild(String cmakePath, Directory buildDir, String buildModeName) async { Future<void> _runBuild(String cmakePath, Directory buildDir, String buildModeName) async {
final Stopwatch sw = Stopwatch()..start(); final Stopwatch sw = Stopwatch()..start();
// MSBuild sends all output to stdout, including build errors. This surfaces
// known error patterns.
final RegExp errorMatcher = RegExp(r':\s*(?:warning|(?:fatal )?error).*?:');
int result; int result;
try { try {
result = await processUtils.stream( result = await processUtils.stream(
...@@ -126,13 +130,13 @@ Future<void> _runBuild(String cmakePath, Directory buildDir, String buildModeNam ...@@ -126,13 +130,13 @@ Future<void> _runBuild(String cmakePath, Directory buildDir, String buildModeNam
'VERBOSE_SCRIPT_LOGGING': 'true' 'VERBOSE_SCRIPT_LOGGING': 'true'
}, },
trace: true, trace: true,
stdoutErrorMatcher: errorMatcher,
); );
} on ArgumentError { } on ArgumentError {
throwToolExit("cmake not found. Run 'flutter doctor' for more information."); throwToolExit("cmake not found. Run 'flutter doctor' for more information.");
} }
if (result != 0) { if (result != 0) {
final String verboseInstructions = globals.logger.isVerbose ? '' : ' To view the stack trace, please run `flutter run -d windows -v`.'; throwToolExit('Build process failed.');
throwToolExit('Build process failed.$verboseInstructions');
} }
globals.flutterUsage.sendTiming('build', 'windows-cmake-build', Duration(milliseconds: sw.elapsedMilliseconds)); globals.flutterUsage.sendTiming('build', 'windows-cmake-build', Duration(milliseconds: sw.elapsedMilliseconds));
} }
......
...@@ -80,11 +80,13 @@ add_dependencies(flutter_wrapper_app flutter_assemble) ...@@ -80,11 +80,13 @@ add_dependencies(flutter_wrapper_app flutter_assemble)
# _phony_ is a non-existent file to force this command to run every time, # _phony_ is a non-existent file to force this command to run every time,
# since currently there's no way to get a full input/output list from the # since currently there's no way to get a full input/output list from the
# flutter tool. # flutter tool.
set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_")
set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE)
add_custom_command( add_custom_command(
OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS}
${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN}
${CPP_WRAPPER_SOURCES_APP} ${CPP_WRAPPER_SOURCES_APP}
${CMAKE_CURRENT_BINARY_DIR}/_phony_ ${PHONY_OUTPUT}
COMMAND ${CMAKE_COMMAND} -E env COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT} ${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
......
...@@ -239,6 +239,63 @@ void main() { ...@@ -239,6 +239,63 @@ void main() {
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true), FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
}); });
testUsingContext('Windows build extracts errors from stdout', () async {
final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio;
applyMocksToCommand(command);
setUpMockProjectFilesForBuild();
when(mockVisualStudio.cmakePath).thenReturn(cmakePath);
// This contains a mix of routine build output and various types of errors
// (compile error, link error, warning treated as an error) from MSBuild,
// edited down for compactness. For instance, where similar lines are
// repeated in actual output, one or two representative lines are chosen
// to be included here.
const String stdout = r'''Microsoft (R) Build Engine version 16.6.0+5ff7b0c9e for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.
Checking Build System
Generating C:/foo/windows/flutter/ephemeral/flutter_windows.dll, [etc], _phony_
Building Custom Rule C:/foo/windows/flutter/CMakeLists.txt
standard_codec.cc
Generating Code...
flutter_wrapper_plugin.vcxproj -> C:\foo\build\windows\flutter\Debug\flutter_wrapper_plugin.lib
C:\foo\windows\runner\main.cpp(18): error C2220: the following warning is treated as an error [C:\foo\build\windows\runner\test.vcxproj]
C:\foo\windows\runner\main.cpp(18): warning C4706: assignment within conditional expression [C:\foo\build\windows\runner\test.vcxproj]
main.obj : error LNK2019: unresolved external symbol "void __cdecl Bar(void)" (?Bar@@YAXXZ) referenced in function wWinMain [C:\foo\build\windows\runner\test.vcxproj]
C:\foo\build\windows\runner\Debug\test.exe : fatal error LNK1120: 1 unresolved externals [C:\foo\build\windows\runner\test.vcxproj]
Building Custom Rule C:/foo/windows/runner/CMakeLists.txt
flutter_window.cpp
main.cpp
C:\foo\windows\runner\main.cpp(17,1): error C2065: 'Baz': undeclared identifier [C:\foo\build\windows\runner\test.vcxproj]
-- Install configuration: "Debug"
-- Installing: C:/foo/build/windows/runner/Debug/data/icudtl.dat
''';
processManager = FakeProcessManager.list(<FakeCommand>[
cmakeGenerationCommand(),
buildCommand('Release',
stdout: stdout,
),
]);
await createTestCommandRunner(command).run(
const <String>['windows', '--no-pub']
);
// Just the warnings and errors should be surfaced.
expect(testLogger.errorText, r'''C:\foo\windows\runner\main.cpp(18): error C2220: the following warning is treated as an error [C:\foo\build\windows\runner\test.vcxproj]
C:\foo\windows\runner\main.cpp(18): warning C4706: assignment within conditional expression [C:\foo\build\windows\runner\test.vcxproj]
main.obj : error LNK2019: unresolved external symbol "void __cdecl Bar(void)" (?Bar@@YAXXZ) referenced in function wWinMain [C:\foo\build\windows\runner\test.vcxproj]
C:\foo\build\windows\runner\Debug\test.exe : fatal error LNK1120: 1 unresolved externals [C:\foo\build\windows\runner\test.vcxproj]
C:\foo\windows\runner\main.cpp(17,1): error C2065: 'Baz': undeclared identifier [C:\foo\build\windows\runner\test.vcxproj]
''');
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => processManager,
Platform: () => windowsPlatform,
FeatureFlags: () => TestFeatureFlags(isWindowsEnabled: true),
});
testUsingContext('Windows verbose build sets VERBOSE_SCRIPT_LOGGING', () async { testUsingContext('Windows verbose build sets VERBOSE_SCRIPT_LOGGING', () async {
final BuildWindowsCommand command = BuildWindowsCommand() final BuildWindowsCommand command = BuildWindowsCommand()
..visualStudioOverride = mockVisualStudio; ..visualStudioOverride = mockVisualStudio;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment