Unverified Commit e1a784ae authored by stuartmorgan's avatar stuartmorgan Committed by GitHub

Wrap Windows build invocation in a batch script (#33443)

Invoking msbuild with runInShell makes handling path escaping more
error-prone, and substantially increases the chances of running into
maximum path limits. This replaces the direct call with a .bat wrapper
that calls vsvars64.bat then msbuild, and uses relative paths within the
script to keep command lengths short.

Fixes https://github.com/flutter/flutter/issues/32792
parent c56b4551
:: Copyright 2018 The Chromium Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style license that can be
:: found in the LICENSE file.
:: Calls vcvars64.bat to configure a command-line build environment, then builds
:: a project with msbuild.
@echo off
set VCVARS=%~1
set PROJECT=%~2
set CONFIG=%~3
call "%VCVARS%"
if %errorlevel% neq 0 exit /b %errorlevel%
msbuild "%PROJECT%" /p:Configuration=%CONFIG%
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file // found in the LICENSE file
import '../base/common.dart'; import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart'; import '../base/io.dart';
import '../base/logger.dart'; import '../base/logger.dart';
import '../base/process_manager.dart'; import '../base/process_manager.dart';
...@@ -28,12 +29,25 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {S ...@@ -28,12 +29,25 @@ Future<void> buildWindows(WindowsProject windowsProject, BuildInfo buildInfo, {S
throwToolExit('Unable to build: could not find vcvars64.bat'); throwToolExit('Unable to build: could not find vcvars64.bat');
} }
final String buildScript = fs.path.join(
Cache.flutterRoot,
'packages',
'flutter_tools',
'bin',
'vs_build.bat',
);
final String configuration = buildInfo.isDebug ? 'Debug' : 'Release'; final String configuration = buildInfo.isDebug ? 'Debug' : 'Release';
final String projectPath = windowsProject.vcprojFile.path;
// Run the script with a relative path to the project using the enclosing
// directory as the workingDirectory, to avoid hitting the limit on command
// lengths in batch scripts if the absolute path to the project is long.
final Process process = await processManager.start(<String>[ final Process process = await processManager.start(<String>[
vcvarsScript, '&&', 'msbuild', buildScript,
windowsProject.vcprojFile.path, vcvarsScript,
'/p:Configuration=$configuration', fs.path.basename(projectPath),
], runInShell: true); configuration,
], workingDirectory: fs.path.dirname(projectPath));
final Status status = logger.startProgress( final Status status = logger.startProgress(
'Building Windows application...', 'Building Windows application...',
timeout: null, timeout: null,
......
...@@ -25,7 +25,7 @@ void main() { ...@@ -25,7 +25,7 @@ void main() {
final MockPlatform windowsPlatform = MockPlatform() final MockPlatform windowsPlatform = MockPlatform()
..environment['PROGRAMFILES(X86)'] = r'C:\Program Files (x86)\'; ..environment['PROGRAMFILES(X86)'] = r'C:\Program Files (x86)\';
final MockPlatform notWindowsPlatform = MockPlatform(); final MockPlatform notWindowsPlatform = MockPlatform();
const String projectPath = r'windows\Runner.vcxproj'; const String projectPath = r'C:\windows\Runner.vcxproj';
// A vcvars64.bat location that will be found by the lookup method. // A vcvars64.bat location that will be found by the lookup method.
const String vcvarsPath = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat'; const String vcvarsPath = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat';
...@@ -90,12 +90,11 @@ void main() { ...@@ -90,12 +90,11 @@ void main() {
fs.file('.packages').createSync(); fs.file('.packages').createSync();
when(mockProcessManager.start(<String>[ when(mockProcessManager.start(<String>[
r'C:\packages\flutter_tools\bin\vs_build.bat',
vcvarsPath, vcvarsPath,
'&&', fs.path.basename(projectPath),
'msbuild', 'Release',
'C:\\$projectPath', ], workingDirectory: fs.path.dirname(projectPath))).thenAnswer((Invocation invocation) async {
'/p:Configuration=Release',
], runInShell: true)).thenAnswer((Invocation invocation) async {
return mockProcess; return mockProcess;
}); });
......
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