Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
1237ee8f
Unverified
Commit
1237ee8f
authored
Jan 24, 2019
by
Jonah Williams
Committed by
GitHub
Jan 24, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add experimentalBuildEnabled flag and initial shim for build_runner (#26989)
parent
2c05d08f
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
386 additions
and
0 deletions
+386
-0
build_kernel_compiler.dart
...ter_tools/lib/src/build_runner/build_kernel_compiler.dart
+64
-0
build_runner.dart
...ages/flutter_tools/lib/src/build_runner/build_runner.dart
+153
-0
context_runner.dart
packages/flutter_tools/lib/src/context_runner.dart
+2
-0
project.dart
packages/flutter_tools/lib/src/project.dart
+3
-0
build_kernel_compiler.dart
...lutter_tools/test/build_runner/build_kernel_compiler.dart
+60
-0
build_runner_test.dart
...es/flutter_tools/test/build_runner/build_runner_test.dart
+104
-0
No files found.
packages/flutter_tools/lib/src/build_runner/build_kernel_compiler.dart
0 → 100644
View file @
1237ee8f
// Copyright 2019 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.
import
'../base/file_system.dart'
;
import
'../compile.dart'
;
import
'../globals.dart'
;
import
'build_runner.dart'
;
/// An implementation of the [KernelCompiler] which delegates to build_runner.
///
/// Only a subset of the arguments provided to the [KernelCompiler] are
/// supported here. Using the build pipeline implies a fixed multiroot
/// filesystem and requires a pubspec.
///
/// This is only safe to use if [experimentalBuildEnabled] is true.
class
BuildKernelCompiler
implements
KernelCompiler
{
const
BuildKernelCompiler
();
@override
Future
<
CompilerOutput
>
compile
({
String
mainPath
,
String
outputFilePath
,
bool
linkPlatformKernelIn
=
false
,
bool
aot
=
false
,
bool
trackWidgetCreation
,
List
<
String
>
extraFrontEndOptions
,
String
incrementalCompilerByteStorePath
,
bool
targetProductVm
=
false
,
// These arguments are currently unused.
String
sdkRoot
,
String
packagesPath
,
List
<
String
>
fileSystemRoots
,
String
fileSystemScheme
,
String
depFilePath
,
TargetModel
targetModel
,
})
async
{
if
(
fileSystemRoots
!=
null
||
fileSystemScheme
!=
null
||
depFilePath
!=
null
||
targetModel
!=
null
||
sdkRoot
!=
null
||
packagesPath
!=
null
)
{
printTrace
(
'fileSystemRoots, fileSystemScheme, depFilePath, targetModel,'
'sdkRoot, packagesPath are not supported when using the experimental '
'build* pipeline'
);
}
final
BuildRunner
buildRunner
=
buildRunnerFactory
.
create
();
try
{
final
BuildResult
buildResult
=
await
buildRunner
.
build
(
aot:
aot
,
linkPlatformKernelIn:
linkPlatformKernelIn
,
trackWidgetCreation:
trackWidgetCreation
,
mainPath:
mainPath
,
targetProductVm:
targetProductVm
,
extraFrontEndOptions:
extraFrontEndOptions
);
final
File
outputFile
=
fs
.
file
(
outputFilePath
);
if
(!
await
outputFile
.
exists
())
{
await
outputFile
.
create
();
}
await
outputFile
.
writeAsBytes
(
await
buildResult
.
dillFile
.
readAsBytes
());
return
CompilerOutput
(
outputFilePath
,
0
);
}
on
Exception
catch
(
err
)
{
printError
(
'Compilation Failed:
$err
'
);
return
const
CompilerOutput
(
null
,
1
);
}
}
}
packages/flutter_tools/lib/src/build_runner/build_runner.dart
0 → 100644
View file @
1237ee8f
// Copyright 2019 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.
import
'dart:async'
;
import
'dart:convert'
;
import
'package:meta/meta.dart'
;
import
'../artifacts.dart'
;
import
'../base/context.dart'
;
import
'../base/file_system.dart'
;
import
'../base/io.dart'
;
import
'../base/platform.dart'
;
import
'../base/process_manager.dart'
;
import
'../cache.dart'
;
import
'../dart/package_map.dart'
;
import
'../globals.dart'
;
import
'../project.dart'
;
/// The [BuildRunnerFactory] instance.
BuildRunnerFactory
get
buildRunnerFactory
=>
context
[
BuildRunnerFactory
];
/// Whether to attempt to build a flutter project using build* libraries.
///
/// This requires both an experimental opt in via the environment variable
/// 'FLUTTER_EXPERIMENTAL_BUILD' and that the project itself has a
/// dependency on the package 'flutter_build' and 'build_runner.'
FutureOr
<
bool
>
get
experimentalBuildEnabled
async
{
if
(
_experimentalBuildEnabled
!=
null
)
{
return
_experimentalBuildEnabled
;
}
final
bool
flagEnabled
=
platform
.
environment
[
'FLUTTER_EXPERIMENTAL_BUILD'
]?.
toLowerCase
()
==
'true'
;
if
(!
flagEnabled
)
{
return
_experimentalBuildEnabled
=
false
;
}
final
FlutterProject
flutterProject
=
await
FlutterProject
.
current
();
final
Map
<
String
,
Uri
>
packages
=
PackageMap
(
flutterProject
.
packagesFile
.
path
).
map
;
return
_experimentalBuildEnabled
=
packages
.
containsKey
(
'flutter_build'
)
&&
packages
.
containsKey
(
'build_runner'
);
}
bool
_experimentalBuildEnabled
;
@visibleForTesting
set
experimentalBuildEnabled
(
bool
value
)
{
_experimentalBuildEnabled
=
value
;
}
/// An injectable factory to create instances of [BuildRunner].
class
BuildRunnerFactory
{
const
BuildRunnerFactory
();
/// Creates a new [BuildRunner] instance.
BuildRunner
create
()
{
return
BuildRunner
();
}
}
/// A wrapper for a build_runner process which delegates to a generated
/// build script.
///
/// This is only enabled if [experimentalBuildEnabled] is true, and only for
/// external flutter users.
class
BuildRunner
{
/// Run a build_runner build and return the resulting .packages and dill file.
///
/// The defines of the build command are the arguments required in the
/// flutter_build kernel builder.
Future
<
BuildResult
>
build
({
@required
bool
aot
,
@required
bool
linkPlatformKernelIn
,
@required
bool
trackWidgetCreation
,
@required
bool
targetProductVm
,
@required
String
mainPath
,
@required
List
<
String
>
extraFrontEndOptions
,
})
async
{
final
FlutterProject
flutterProject
=
await
FlutterProject
.
current
();
final
String
frontendServerPath
=
artifacts
.
getArtifactPath
(
Artifact
.
frontendServerSnapshotForEngineDartSdk
);
final
String
pubExecutable
=
fs
.
path
.
join
(
Cache
.
flutterRoot
,
'bin'
,
'cache'
,
'dart-sdk'
,
'bin'
,
'pub'
);
final
String
sdkRoot
=
artifacts
.
getArtifactPath
(
Artifact
.
flutterPatchedSdkPath
);
final
String
engineDartBinaryPath
=
artifacts
.
getArtifactPath
(
Artifact
.
engineDartBinary
);
final
String
packagesPath
=
flutterProject
.
packagesFile
.
absolute
.
path
;
final
Process
process
=
await
processManager
.
start
(<
String
>[
'
$pubExecutable
'
,
'run'
,
'build_runner'
,
'build'
,
'--define'
,
'flutter_build|kernel=disabled=false'
,
'--define'
,
'flutter_build|kernel=aot=
$aot
'
,
'--define'
,
'flutter_build|kernel=linkPlatformKernelIn=
$linkPlatformKernelIn
'
,
'--define'
,
'flutter_build|kernel=trackWidgetCreation=
$trackWidgetCreation
'
,
'--define'
,
'flutter_build|kernel=targetProductVm=
$targetProductVm
'
,
'--define'
,
'flutter_build|kernel=mainPath=
$mainPath
'
,
'--define'
,
'flutter_build|kernel=packagesPath=
$packagesPath
'
,
'--define'
,
'flutter_build|kernel=sdkRoot=
$sdkRoot
'
,
'--define'
,
'flutter_build|kernel=frontendServerPath=
$frontendServerPath
'
,
'--define'
,
'flutter_build|kernel=engineDartBinaryPath=
$engineDartBinaryPath
'
,
'--define'
,
'flutter_build|kernel=extraFrontEndOptions=
${extraFrontEndOptions ?? const <String>[]}
'
,
]);
process
.
stdout
.
transform
(
utf8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
listen
(
_handleOutput
);
process
.
stderr
.
transform
(
utf8
.
decoder
)
.
transform
(
const
LineSplitter
())
.
listen
(
_handleError
);
final
int
exitCode
=
await
process
.
exitCode
;
if
(
exitCode
!=
0
)
{
throw
Exception
(
'build_runner exited with non-zero exit code:
$exitCode
'
);
}
/// We don't check for this above because it might be generated for the
/// first time by invoking the build.
final
Directory
dartTool
=
flutterProject
.
dartTool
;
final
String
projectName
=
flutterProject
.
manifest
.
appName
;
final
Directory
generatedDirectory
=
dartTool
.
absolute
.
childDirectory
(
'build'
)
.
childDirectory
(
'generated'
)
.
childDirectory
(
projectName
);
if
(!
await
generatedDirectory
.
exists
())
{
throw
Exception
(
'build_runner cannot find generated directory'
);
}
final
String
relativeMain
=
fs
.
path
.
relative
(
mainPath
,
from:
flutterProject
.
directory
.
path
);
final
File
packagesFile
=
fs
.
file
(
fs
.
path
.
join
(
generatedDirectory
.
path
,
fs
.
path
.
setExtension
(
relativeMain
,
'.packages'
))
);
final
File
dillFile
=
fs
.
file
(
fs
.
path
.
join
(
generatedDirectory
.
path
,
fs
.
path
.
setExtension
(
relativeMain
,
'.app.dill'
))
);
if
(!
await
packagesFile
.
exists
()
||
!
await
dillFile
.
exists
())
{
throw
Exception
(
'build_runner did not produce output at expected location:
${dillFile.path}
missing'
);
}
return
BuildResult
(
packagesFile
,
dillFile
);
}
void
_handleOutput
(
String
line
)
{
printTrace
(
line
);
}
void
_handleError
(
String
line
)
{
printError
(
line
);
}
}
class
BuildResult
{
const
BuildResult
(
this
.
packagesFile
,
this
.
dillFile
);
final
File
packagesFile
;
final
File
dillFile
;
}
packages/flutter_tools/lib/src/context_runner.dart
View file @
1237ee8f
...
...
@@ -21,6 +21,7 @@ import 'base/platform.dart';
import
'base/time.dart'
;
import
'base/user_messages.dart'
;
import
'base/utils.dart'
;
import
'build_runner/build_runner.dart'
;
import
'cache.dart'
;
import
'compile.dart'
;
import
'devfs.dart'
;
...
...
@@ -59,6 +60,7 @@ Future<T> runInContext<T>(
Artifacts:
()
=>
CachedArtifacts
(),
AssetBundleFactory:
()
=>
AssetBundleFactory
.
defaultInstance
,
BotDetector:
()
=>
const
BotDetector
(),
BuildRunnerFactory:
()
=>
const
BuildRunnerFactory
(),
Cache:
()
=>
Cache
(),
CocoaPods:
()
=>
CocoaPods
(),
CocoaPodsValidator:
()
=>
const
CocoaPodsValidator
(),
...
...
packages/flutter_tools/lib/src/project.dart
View file @
1237ee8f
...
...
@@ -103,6 +103,9 @@ class FlutterProject {
/// The `.flutter-plugins` file of this project.
File
get
flutterPluginsFile
=>
directory
.
childFile
(
'.flutter-plugins'
);
/// The `.dart-tool` directory of this project.
Directory
get
dartTool
=>
directory
.
childDirectory
(
'.dart_tool'
);
/// The example sub-project of this project.
FlutterProject
get
example
=>
FlutterProject
(
_exampleDirectory
(
directory
),
...
...
packages/flutter_tools/test/build_runner/build_kernel_compiler.dart
0 → 100644
View file @
1237ee8f
// Copyright 2019 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.
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/build_runner/build_kernel_compiler.dart'
;
import
'package:flutter_tools/src/build_runner/build_runner.dart'
;
import
'package:flutter_tools/src/compile.dart'
;
import
'package:mockito/mockito.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
void
main
(
)
{
group
(
BuildKernelCompiler
,
()
{
final
MockBuildRunnerFactory
mockBuildRunnerFactory
=
MockBuildRunnerFactory
();
final
MockBuildRunner
mockBuildRunner
=
MockBuildRunner
();
final
MockFileSystem
mockFileSystem
=
MockFileSystem
();
final
MockFile
packagesFile
=
MockFile
();
final
MockFile
dillFile
=
MockFile
();
final
MockFile
outputFile
=
MockFile
();
when
(
mockFileSystem
.
file
(
'main.app.dill'
)).
thenReturn
(
dillFile
);
when
(
mockFileSystem
.
file
(
'.packages'
)).
thenReturn
(
packagesFile
);
when
(
mockFileSystem
.
file
(
'output.app.dill'
)).
thenReturn
(
outputFile
);
when
(
packagesFile
.
exists
()).
thenAnswer
((
Invocation
invocation
)
async
=>
true
);
when
(
dillFile
.
exists
()).
thenAnswer
((
Invocation
invocation
)
async
=>
true
);
when
(
outputFile
.
exists
()).
thenAnswer
((
Invocation
invocation
)
async
=>
true
);
when
(
mockBuildRunnerFactory
.
create
()).
thenReturn
(
mockBuildRunner
);
when
(
dillFile
.
readAsBytes
()).
thenAnswer
((
Invocation
invocation
)
async
=>
<
int
>[
0
,
1
,
2
,
3
]);
testUsingContext
(
'delegates to build_runner'
,
()
async
{
const
BuildKernelCompiler
kernelCompiler
=
BuildKernelCompiler
();
when
(
mockBuildRunner
.
build
(
aot:
anyNamed
(
'aot'
),
extraFrontEndOptions:
anyNamed
(
'extraFrontEndOptions'
),
linkPlatformKernelIn:
anyNamed
(
'linkPlatformKernelIn'
),
mainPath:
anyNamed
(
'mainPath'
),
targetProductVm:
anyNamed
(
'targetProductVm'
),
trackWidgetCreation:
anyNamed
(
'trackWidgetCreation'
)
)).
thenAnswer
((
Invocation
invocation
)
async
{
return
BuildResult
(
fs
.
file
(
'.packages'
),
fs
.
file
(
'main.app.dill'
));
});
final
CompilerOutput
buildResult
=
await
kernelCompiler
.
compile
(
outputFilePath:
'output.app.dill'
,
);
expect
(
buildResult
.
outputFilename
,
'output.app.dill'
);
expect
(
buildResult
.
errorCount
,
0
);
verify
(
outputFile
.
writeAsBytes
(<
int
>[
0
,
1
,
2
,
3
])).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
BuildRunnerFactory:
()
=>
mockBuildRunnerFactory
,
FileSystem:
()
=>
mockFileSystem
,
});
});
}
class
MockBuildRunnerFactory
extends
Mock
implements
BuildRunnerFactory
{}
class
MockBuildRunner
extends
Mock
implements
BuildRunner
{}
class
MockFileSystem
extends
Mock
implements
FileSystem
{}
class
MockFile
extends
Mock
implements
File
{}
packages/flutter_tools/test/build_runner/build_runner_test.dart
0 → 100644
View file @
1237ee8f
// Copyright 2019 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.
import
'dart:convert'
;
import
'package:flutter_tools/src/base/file_system.dart'
;
import
'package:flutter_tools/src/base/platform.dart'
;
import
'package:flutter_tools/src/build_runner/build_runner.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:process/process.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
void
main
(
)
{
group
(
'experimentalBuildEnabled'
,
()
{
final
MockProcessManager
mockProcessManager
=
MockProcessManager
();
final
MockPlatform
mockPlatform
=
MockPlatform
();
final
MockFileSystem
mockFileSystem
=
MockFileSystem
();
setUp
(()
{
experimentalBuildEnabled
=
null
;
});
testUsingContext
(
'is enabled if environment variable is enabled and project '
'contains a dependency on flutter_build and build_runner'
,
()
async
{
final
MockDirectory
projectDirectory
=
MockDirectory
();
final
MockDirectory
exampleDirectory
=
MockDirectory
();
final
MockFile
packagesFile
=
MockFile
();
final
MockFile
pubspecFile
=
MockFile
();
final
MockFile
examplePubspecFile
=
MockFile
();
const
String
packages
=
r''
'
flutter_build:file:///Users/tester/.pub-cache/hosted/pub.dartlang.org/flutter_build/lib/
build_runner:file:///Users/tester/.pub-cache/hosted/pub.dartlang.org/build_runner/lib/
example:lib/
'''
;
when
(
mockPlatform
.
environment
).
thenReturn
(<
String
,
String
>{
'FLUTTER_EXPERIMENTAL_BUILD'
:
'true'
});
when
(
mockFileSystem
.
currentDirectory
).
thenReturn
(
projectDirectory
);
when
(
mockFileSystem
.
isFileSync
(
any
)).
thenReturn
(
false
);
when
(
projectDirectory
.
childFile
(
'pubspec.yaml'
)).
thenReturn
(
pubspecFile
);
when
(
projectDirectory
.
childFile
(
'.packages'
)).
thenReturn
(
packagesFile
);
when
(
projectDirectory
.
childDirectory
(
'example'
)).
thenReturn
(
exampleDirectory
);
when
(
exampleDirectory
.
childFile
(
'pubspec.yaml'
)).
thenReturn
(
examplePubspecFile
);
when
(
packagesFile
.
path
).
thenReturn
(
'/test/.packages'
);
when
(
pubspecFile
.
path
).
thenReturn
(
'/test/pubspec.yaml'
);
when
(
examplePubspecFile
.
path
).
thenReturn
(
'/test/example/pubspec.yaml'
);
when
(
mockFileSystem
.
file
(
'/test/.packages'
)).
thenReturn
(
packagesFile
);
when
(
packagesFile
.
readAsBytesSync
()).
thenReturn
(
utf8
.
encode
(
packages
));
expect
(
await
experimentalBuildEnabled
,
true
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
Platform:
()
=>
mockPlatform
,
FileSystem:
()
=>
mockFileSystem
,
});
testUsingContext
(
'is not enabled if environment variable is enabled and project '
'does not contain a dependency on flutter_build'
,
()
async
{
final
MockDirectory
projectDirectory
=
MockDirectory
();
final
MockDirectory
exampleDirectory
=
MockDirectory
();
final
MockFile
packagesFile
=
MockFile
();
final
MockFile
pubspecFile
=
MockFile
();
final
MockFile
examplePubspecFile
=
MockFile
();
const
String
packages
=
r''
'
build_runner:file:///Users/tester/.pub-cache/hosted/pub.dartlang.org/build_runner/lib/
example:lib/
'''
;
when
(
mockPlatform
.
environment
).
thenReturn
(<
String
,
String
>{
'FLUTTER_EXPERIMENTAL_BUILD'
:
'true'
});
when
(
mockFileSystem
.
currentDirectory
).
thenReturn
(
projectDirectory
);
when
(
mockFileSystem
.
isFileSync
(
any
)).
thenReturn
(
false
);
when
(
projectDirectory
.
childFile
(
'pubspec.yaml'
)).
thenReturn
(
pubspecFile
);
when
(
projectDirectory
.
childFile
(
'.packages'
)).
thenReturn
(
packagesFile
);
when
(
projectDirectory
.
childDirectory
(
'example'
)).
thenReturn
(
exampleDirectory
);
when
(
exampleDirectory
.
childFile
(
'pubspec.yaml'
)).
thenReturn
(
examplePubspecFile
);
when
(
packagesFile
.
path
).
thenReturn
(
'/test/.packages'
);
when
(
pubspecFile
.
path
).
thenReturn
(
'/test/pubspec.yaml'
);
when
(
examplePubspecFile
.
path
).
thenReturn
(
'/test/example/pubspec.yaml'
);
when
(
mockFileSystem
.
file
(
'/test/.packages'
)).
thenReturn
(
packagesFile
);
when
(
packagesFile
.
readAsBytesSync
()).
thenReturn
(
utf8
.
encode
(
packages
));
expect
(
await
experimentalBuildEnabled
,
false
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
Platform:
()
=>
mockPlatform
,
FileSystem:
()
=>
mockFileSystem
,
});
testUsingContext
(
'is not enabed if environment varable is not enabled'
,
()
async
{
when
(
mockPlatform
.
environment
).
thenReturn
(<
String
,
String
>{});
expect
(
await
experimentalBuildEnabled
,
false
);
},
overrides:
<
Type
,
Generator
>{
ProcessManager:
()
=>
mockProcessManager
,
Platform:
()
=>
mockPlatform
,
FileSystem:
()
=>
mockFileSystem
,
});
});
}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockPlatform
extends
Mock
implements
Platform
{}
class
MockFileSystem
extends
Mock
implements
FileSystem
{}
class
MockDirectory
extends
Mock
implements
Directory
{}
class
MockFile
extends
Mock
implements
File
{}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment