Skip to content

Commit dc8eb8f

Browse files
committed
Add AOT building
1 parent a834909 commit dc8eb8f

File tree

7 files changed

+344
-123
lines changed

7 files changed

+344
-123
lines changed

cmd/build.go

Lines changed: 153 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ var (
3434
buildOrRunOpenGlVersion string
3535
buildOrRunEngineVersion string
3636
buildOrRunDocker bool
37+
buildOrRunDebug bool
38+
buildOrRunRelease bool
39+
buildOrRunProfile bool
40+
buildOrRunMode build.Mode
3741
)
3842

3943
func initCompileFlags(cmd *cobra.Command) {
@@ -43,13 +47,15 @@ func initCompileFlags(cmd *cobra.Command) {
4347
cmd.PersistentFlags().StringVar(&buildOrRunOpenGlVersion, "opengl", config.BuildOpenGlVersionDefault, "The OpenGL version specified here is only relevant for external texture plugin (i.e. video_plugin).\nIf 'none' is provided, texture won't be supported. Note: the Flutter Engine still needs a OpenGL compatible context.")
4448
cmd.PersistentFlags().StringVar(&buildOrRunEngineVersion, "engine-version", config.BuildEngineDefault, "The flutter engine version to use.")
4549
cmd.PersistentFlags().BoolVar(&buildOrRunDocker, "docker", false, "Execute the go build and packaging in a docker container. The Flutter build is always run locally")
50+
cmd.PersistentFlags().BoolVar(&buildOrRunDebug, "debug", false, "Build a debug version of the app.")
51+
cmd.PersistentFlags().BoolVar(&buildOrRunRelease, "release", false, "Enable release builds. Currently very experimental and only for linux available")
52+
cmd.PersistentFlags().BoolVar(&buildOrRunProfile, "profile", false, "Enable profile builds. Currently very experimental and only for linux available")
4653

4754
cmd.PersistentFlags().MarkHidden("branch")
4855
}
4956

5057
var (
5158
// `hover build`-only build flags
52-
buildDebug bool
5359
buildVersionNumber string
5460
buildSkipEngineDownload bool
5561
buildSkipFlutterBuildBundle bool
@@ -64,9 +70,9 @@ func init() {
6470
initCompileFlags(buildCmd)
6571

6672
buildCmd.PersistentFlags().StringVar(&buildVersionNumber, "version-number", "", "Override the version number used in build and packaging. You may use it with $(git describe --tags)")
67-
buildCmd.PersistentFlags().BoolVar(&buildDebug, "debug", false, "Build a debug version of the app.")
6873
buildCmd.PersistentFlags().BoolVar(&buildSkipEngineDownload, "skip-engine-download", false, "Skip donwloading the Flutter Engine and artifacts.")
6974
buildCmd.PersistentFlags().BoolVar(&buildSkipFlutterBuildBundle, "skip-flutter-build-bundle", false, "Skip the 'flutter build bundle' step.")
75+
7076
buildCmd.AddCommand(buildLinuxCmd)
7177
buildCmd.AddCommand(buildLinuxSnapCmd)
7278
buildCmd.AddCommand(buildLinuxDebCmd)
@@ -191,6 +197,8 @@ func subcommandBuild(targetOS string, packagingTask packaging.Task) {
191197
packagingTask.AssertSupported()
192198
}
193199

200+
initBuildParameters(targetOS, build.ReleaseMode)
201+
194202
if !buildSkipFlutterBuildBundle {
195203
cleanBuildOutputsDir(targetOS)
196204
buildFlutterBundle(targetOS)
@@ -203,9 +211,15 @@ func subcommandBuild(targetOS string, packagingTask packaging.Task) {
203211
if buildVersionNumber != "" {
204212
buildFlags = append(buildFlags, "--version-number", buildVersionNumber)
205213
}
206-
if buildDebug {
214+
if buildOrRunDebug {
207215
buildFlags = append(buildFlags, "--debug")
208216
}
217+
if buildOrRunRelease {
218+
buildFlags = append(buildFlags, "--release")
219+
}
220+
if buildOrRunProfile {
221+
buildFlags = append(buildFlags, "--profile")
222+
}
209223
dockerHoverBuild(targetOS, packagingTask, buildFlags, nil)
210224
} else {
211225
buildGoBinary(targetOS, nil)
@@ -216,7 +230,7 @@ func subcommandBuild(targetOS string, packagingTask packaging.Task) {
216230
// initBuildParameters is used to initialize all the build parameters. It sets
217231
// fallback values based on config or defaults for values that have not
218232
// explicitly been set through flags.
219-
func initBuildParameters(targetOS string) {
233+
func initBuildParameters(targetOS string, defaultbuildOrRunMode build.Mode) {
220234
if buildOrRunCachePath == "" {
221235
log.Errorf("Missing cache path, cannot continue. Please see previous warning.")
222236
os.Exit(1)
@@ -241,14 +255,43 @@ func initBuildParameters(targetOS string) {
241255
buildVersionNumber = pubspec.GetPubSpec().GetVersion()
242256
}
243257

244-
engineCachePath = enginecache.EngineCachePath(targetOS, buildOrRunCachePath)
258+
numberOfbuildOrRunModeFlagsSet := 0
259+
for _, flag := range []bool{buildOrRunDebug, buildOrRunRelease, buildOrRunProfile} {
260+
if flag {
261+
numberOfbuildOrRunModeFlagsSet++
262+
}
263+
}
264+
if numberOfbuildOrRunModeFlagsSet > 1 {
265+
log.Errorf("Only one of --debug, --release or --profile can be set at one time")
266+
os.Exit(1)
267+
}
268+
if numberOfbuildOrRunModeFlagsSet == 0 {
269+
buildOrRunMode = defaultbuildOrRunMode
270+
}
271+
272+
if buildOrRunDebug {
273+
buildOrRunMode = build.DebugMode
274+
}
275+
if buildOrRunRelease {
276+
buildOrRunMode = build.ReleaseMode
277+
}
278+
if buildOrRunProfile {
279+
buildOrRunMode = build.ProfileMode
280+
}
281+
282+
if buildOrRunMode.IsAot && targetOS != runtime.GOOS {
283+
log.Errorf("AOT builds currently only work on their host OS")
284+
os.Exit(1)
285+
}
286+
287+
engineCachePath = enginecache.EngineCachePath(targetOS, buildOrRunCachePath, buildOrRunMode)
245288
if !buildSkipEngineDownload {
246-
enginecache.ValidateOrUpdateEngine(targetOS, buildOrRunCachePath, buildOrRunEngineVersion)
289+
enginecache.ValidateOrUpdateEngine(targetOS, buildOrRunCachePath, buildOrRunEngineVersion, buildOrRunMode)
247290
}
248291
}
249292

250293
func commonFlags() []string {
251-
f := []string{}
294+
var f []string
252295
if buildOrRunFlutterTarget != config.BuildTargetDefault {
253296
f = append(f, "--target", buildOrRunFlutterTarget)
254297
}
@@ -319,53 +362,127 @@ func buildFlutterBundle(targetOS string) {
319362
}
320363

321364
checkFlutterChannel()
365+
var trackWidgetCreation string
366+
if buildOrRunMode == build.DebugMode {
367+
trackWidgetCreation = "--track-widget-creation"
368+
}
322369

323-
var flutterBuildBundleArgs = []string{
324-
"build", "bundle",
370+
cmdFlutterBuild := exec.Command(build.FlutterBin(), "build", "bundle",
325371
"--asset-dir", filepath.Join(build.OutputDirectoryPath(targetOS), "flutter_assets"),
326372
"--target", buildOrRunFlutterTarget,
327-
}
328-
if buildDebug {
329-
flutterBuildBundleArgs = append(flutterBuildBundleArgs, "--track-widget-creation")
330-
}
331-
cmdFlutterBuildBundle := exec.Command(build.FlutterBin(), flutterBuildBundleArgs...)
332-
cmdFlutterBuildBundle.Stderr = os.Stderr
333-
cmdFlutterBuildBundle.Stdout = os.Stdout
373+
trackWidgetCreation,
374+
)
375+
cmdFlutterBuild.Stderr = os.Stderr
376+
cmdFlutterBuild.Stdout = os.Stdout
334377

335-
log.Infof("Building flutter bundle")
336-
err = cmdFlutterBuildBundle.Run()
378+
log.Infof("Bundling flutter app")
379+
err = cmdFlutterBuild.Run()
337380
if err != nil {
338381
log.Errorf("Flutter build failed: %v", err)
339382
os.Exit(1)
340383
}
384+
if buildOrRunMode.IsAot {
385+
err := os.Remove(filepath.Join(build.OutputDirectoryPath(targetOS), "flutter_assets", "isolate_snapshot_data"))
386+
if err != nil {
387+
log.Errorf("Failed to remove unused isolate_snapshot_data: %v", err)
388+
os.Exit(1)
389+
}
390+
err = os.Remove(filepath.Join(build.OutputDirectoryPath(targetOS), "flutter_assets", "vm_snapshot_data"))
391+
if err != nil {
392+
log.Errorf("Failed to remove unused vm_snapshot_data: %v", err)
393+
os.Exit(1)
394+
}
395+
err = os.Remove(filepath.Join(build.OutputDirectoryPath(targetOS), "flutter_assets", "kernel_blob.bin"))
396+
if err != nil {
397+
log.Errorf("Failed to remove unused kernel_blob.bin: %v", err)
398+
os.Exit(1)
399+
}
400+
dart := filepath.Join(engineCachePath, "dart-sdk", "bin", "dart"+build.ExecutableExtension(targetOS))
401+
var genSnapshot string
402+
if targetOS == "darwin" {
403+
genSnapshot = filepath.Join(engineCachePath, "artifacts", "gen_snapshot"+build.ExecutableExtension(targetOS))
404+
} else {
405+
genSnapshot = filepath.Join(engineCachePath, "gen_snapshot"+build.ExecutableExtension(targetOS))
406+
}
407+
kernelSnapshot := filepath.Join(build.OutputDirectoryPath(targetOS), "kernel_snapshot.dill")
408+
elfSnapshot := filepath.Join(build.OutputDirectoryPath(targetOS), "libapp.so")
409+
cmdGenerateKernelSnapshot := exec.Command(
410+
dart,
411+
filepath.Join(engineCachePath, "artifacts", "frontend_server.dart.snapshot"),
412+
"--sdk-root="+filepath.Join(engineCachePath, "flutter_patched_sdk_product"),
413+
"--target=flutter",
414+
"--aot",
415+
"--tfa",
416+
"-Ddart.vm.product=true",
417+
"--packages=.packages",
418+
"--output-dill="+kernelSnapshot,
419+
buildOrRunFlutterTarget,
420+
)
421+
cmdGenerateKernelSnapshot.Stderr = os.Stderr
422+
log.Infof("Generating kernel snapshot")
423+
err = cmdGenerateKernelSnapshot.Run()
424+
if err != nil {
425+
log.Errorf("Generating kernel snapshot failed: %v", err)
426+
os.Exit(1)
427+
}
428+
generateAotSnapshotCommand := []string{
429+
genSnapshot,
430+
"--no-causal-async-stacks",
431+
"--lazy-async-stacks",
432+
"--deterministic",
433+
"--snapshot_kind=app-aot-elf",
434+
"--elf=" + elfSnapshot,
435+
}
436+
if buildOrRunMode.Name == "release" {
437+
generateAotSnapshotCommand = append(generateAotSnapshotCommand, "--strip")
438+
}
439+
generateAotSnapshotCommand = append(generateAotSnapshotCommand, kernelSnapshot)
440+
cmdGenerateAotSnapshot := exec.Command(
441+
generateAotSnapshotCommand[0],
442+
generateAotSnapshotCommand[1:]...,
443+
)
444+
cmdGenerateAotSnapshot.Stderr = os.Stderr
445+
log.Infof("Generating ELF snapshot")
446+
err = cmdGenerateAotSnapshot.Run()
447+
if err != nil {
448+
log.Errorf("Generating AOT snapshot failed: %v", err)
449+
os.Exit(1)
450+
}
451+
err = os.Remove(kernelSnapshot)
452+
if err != nil {
453+
log.Errorf("Failed to remove kernel_snapshot.dill: %v", err)
454+
os.Exit(1)
455+
}
456+
}
341457
}
342458

343459
func buildGoBinary(targetOS string, vmArguments []string) {
344460
if vmArgsFromEnv := os.Getenv("HOVER_IN_DOCKER_BUILD_VMARGS"); len(vmArgsFromEnv) > 0 {
345461
vmArguments = append(vmArguments, strings.Split(vmArgsFromEnv, ",")...)
346462
}
347-
initBuildParameters(targetOS)
348463

349464
fileutils.CopyDir(build.IntermediatesDirectoryPath(targetOS), build.OutputDirectoryPath(targetOS))
350465

351-
outputEngineFile := filepath.Join(build.OutputDirectoryPath(targetOS), build.EngineFilename(targetOS))
352-
if _, err := os.Stat(outputEngineFile); err == nil || os.IsExist(err) {
353-
err = os.RemoveAll(outputEngineFile)
466+
for _, engineFile := range build.EngineFiles(targetOS, buildOrRunMode) {
467+
outputEngineFile := filepath.Join(build.OutputDirectoryPath(targetOS), engineFile)
468+
if _, err := os.Stat(outputEngineFile); err == nil || os.IsExist(err) {
469+
err = os.RemoveAll(outputEngineFile)
470+
if err != nil {
471+
log.Errorf("Failed to remove old engine: %v", err)
472+
os.Exit(1)
473+
}
474+
}
475+
err := copy.Copy(
476+
filepath.Join(engineCachePath, engineFile),
477+
outputEngineFile,
478+
)
354479
if err != nil {
355-
log.Errorf("Failed to remove old engine: %v", err)
480+
log.Errorf("Failed to copy %s: %v", engineFile, err)
356481
os.Exit(1)
357482
}
358483
}
359-
err := copy.Copy(
360-
filepath.Join(engineCachePath, build.EngineFilename(targetOS)),
361-
outputEngineFile,
362-
)
363-
if err != nil {
364-
log.Errorf("Failed to copy %s: %v", build.EngineFilename(targetOS), err)
365-
os.Exit(1)
366-
}
367484

368-
err = copy.Copy(
485+
err := copy.Copy(
369486
filepath.Join(engineCachePath, "artifacts", "icudtl.dat"),
370487
filepath.Join(build.OutputDirectoryPath(targetOS), "icudtl.dat"),
371488
)
@@ -429,14 +546,6 @@ func buildGoBinary(targetOS string, vmArguments []string) {
429546
log.Warnf("The '--opengl=none' flag makes go-flutter incompatible with texture plugins!")
430547
}
431548

432-
if !buildDebug && targetOS == "linux" {
433-
err = exec.Command("strip", "-s", outputEngineFile).Run()
434-
if err != nil {
435-
log.Errorf("Failed to strip %s: %v", outputEngineFile, err)
436-
os.Exit(1)
437-
}
438-
}
439-
440549
buildCommandString := buildCommand(targetOS, vmArguments, build.OutputBinaryPath(config.GetConfig().GetExecutableName(pubspec.GetPubSpec().Name), targetOS))
441550
cmdGoBuild := exec.Command(buildCommandString[0], buildCommandString[1:]...)
442551
cmdGoBuild.Dir = filepath.Join(wd, build.BuildPath)
@@ -467,11 +576,14 @@ func buildEnv(targetOS string, engineCachePath string) []string {
467576
cgoLdflags = fmt.Sprintf("-F%s -Wl,-rpath,@executable_path", engineCachePath)
468577
cgoLdflags += fmt.Sprintf(" -F%s -L%s", outputDirPath, outputDirPath)
469578
cgoLdflags += " -mmacosx-version-min=10.10"
579+
cgoLdflags += fmt.Sprintf(" -framework %s", build.LibraryName(targetOS))
470580
cgoCflags = "-mmacosx-version-min=10.10"
471581
case "linux":
472582
cgoLdflags = fmt.Sprintf("-L%s -L%s", engineCachePath, outputDirPath)
583+
cgoLdflags += fmt.Sprintf(" -l%s -Wl,-rpath,$ORIGIN", build.LibraryName(targetOS))
473584
case "windows":
474585
cgoLdflags = fmt.Sprintf("-L%s -L%s", engineCachePath, outputDirPath)
586+
cgoLdflags += fmt.Sprintf(" -l%s", build.LibraryName(targetOS))
475587
default:
476588
log.Errorf("Target platform %s is not supported, cgo_ldflags not implemented.", targetOS)
477589
os.Exit(1)
@@ -513,7 +625,7 @@ func buildCommand(targetOS string, vmArguments []string, outputBinaryPath string
513625
}
514626

515627
var ldflags []string
516-
if !buildDebug {
628+
if buildOrRunMode != build.DebugMode {
517629
vmArguments = append(vmArguments, "--disable-dart-asserts")
518630
vmArguments = append(vmArguments, "--disable-observatory")
519631

cmd/bumpversion.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ var upgradeCmd = &cobra.Command{
3636
}
3737

3838
func upgrade(targetOS string) (err error) {
39-
enginecache.ValidateOrUpdateEngine(targetOS, buildOrRunCachePath, "")
39+
enginecache.ValidateOrUpdateEngine(targetOS, buildOrRunCachePath, "", build.DebugMode)
4040
return upgradeGoFlutter(targetOS)
4141
}
4242

cmd/docker.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import (
1616
)
1717

1818
func dockerHoverBuild(targetOS string, packagingTask packaging.Task, buildFlags []string, vmArguments []string) {
19-
initBuildParameters(targetOS)
2019
var err error
2120
dockerBin := build.DockerBin()
2221

cmd/run.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ var runCmd = &cobra.Command{
5252
// Can only run on host OS
5353
targetOS := runtime.GOOS
5454

55-
// forcefully enable --debug as it is not optional for 'hover run'
56-
buildDebug = true
55+
initBuildParameters(targetOS, build.DebugMode)
5756

5857
if runOmitFlutterBundle {
5958
log.Infof("Omiting flutter build bundle")
@@ -123,7 +122,7 @@ func runAndAttach(projectName string, targetOS string) {
123122
// Non-blockingly echo command stderr to terminal
124123
go io.Copy(os.Stderr, stderrApp)
125124

126-
log.Infof("Running %s in debug mode", projectName)
125+
log.Infof("Running %s in %s mode", projectName, buildOrRunMode.Name)
127126
err = cmdApp.Start()
128127
if err != nil {
129128
log.Errorf("Failed to start app '%s': %v", projectName, err)

0 commit comments

Comments
 (0)