diff --git a/pkg/dart2native/lib/dart2native.dart b/pkg/dart2native/lib/dart2native.dart index 4e391660f19..341ba54887d 100644 --- a/pkg/dart2native/lib/dart2native.dart +++ b/pkg/dart2native/lib/dart2native.dart @@ -116,6 +116,7 @@ Future generateKernelHelper({ List extraGenKernelOptions = const [], String? nativeAssets, String? resourcesFile, + bool enableAsserts = false, bool fromDill = false, bool aot = false, bool embedSources = false, @@ -132,6 +133,7 @@ Future generateKernelHelper({ if (aot) '--aot', if (!embedSources) '--no-embed-sources', if (!linkPlatform) '--no-link-platform', + if (enableAsserts) '--enable-asserts', ...defines.map((d) => '-D$d'), if (packages != null) '--packages=$packages', if (nativeAssets != null) '--native-assets=$nativeAssets', @@ -147,6 +149,7 @@ Future generateAotSnapshotHelper( String kernelFile, String snapshotFile, String? debugFile, + bool enableAsserts, List extraGenSnapshotOptions) { return Process.run(genSnapshot, [ '--snapshot-kind=app-aot-elf', @@ -154,6 +157,7 @@ Future generateAotSnapshotHelper( if (debugFile != null) '--save-debugging-info=$debugFile', if (debugFile != null) '--dwarf-stack-traces', if (debugFile != null) '--strip', + if (enableAsserts) '--enable-asserts', ...extraGenSnapshotOptions, kernelFile ]); diff --git a/pkg/dart2native/lib/generate.dart b/pkg/dart2native/lib/generate.dart index 87d87929121..b2f86a7995d 100644 --- a/pkg/dart2native/lib/generate.dart +++ b/pkg/dart2native/lib/generate.dart @@ -71,6 +71,7 @@ Future generateNative({ String? nativeAssets, String? resourcesFile, String enableExperiment = '', + bool enableAsserts = false, bool soundNullSafety = true, bool verbose = false, String verbosity = 'all', @@ -115,6 +116,7 @@ Future generateNative({ packages: packages, defines: defines, fromDill: await isKernelFile(sourcePath), + enableAsserts: enableAsserts, enableExperiment: enableExperiment, targetOS: targetOS, extraGenKernelOptions: [ @@ -144,6 +146,7 @@ Future generateNative({ kernelFile, snapshotFile, debugPath, + enableAsserts, extraAotOptions, ); diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart index 82868d64353..b289d434a5b 100644 --- a/pkg/dartdev/lib/src/commands/compile.dart +++ b/pkg/dartdev/lib/src/commands/compile.dart @@ -410,8 +410,12 @@ class CompileNativeCommand extends CompileSubcommandCommand { help: defineOption.help, abbr: defineOption.abbr, valueHelp: defineOption.valueHelp, - ); - argParser + ) + ..addFlag( + 'enable-asserts', + negatable: false, + help: 'Enable assert statements.', + ) ..addOption( packagesOption.flag, abbr: packagesOption.abbr, @@ -510,6 +514,7 @@ Remove debugging information from the output and save it separately to the speci defines: args.multiOption(defineOption.flag), packages: args.option('packages'), enableExperiment: args.enabledExperiments.join(','), + enableAsserts: args.flag('enable-asserts'), soundNullSafety: args.flag('sound-null-safety'), debugFile: args.option('save-debugging-info'), verbose: verbose, diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart index c5d9f519358..9e9018b61f6 100644 --- a/pkg/dartdev/test/commands/compile_test.dart +++ b/pkg/dartdev/test/commands/compile_test.dart @@ -27,6 +27,7 @@ const String unsoundNullSafetyError = 'Error: the flag --no-sound-null-safety is not supported in Dart 3.'; const String unsoundNullSafetyWarning = 'Warning: the flag --no-sound-null-safety is deprecated and pending removal.'; +const String failedAssertionError = 'Failed assertion: line'; String usingTargetOSMessageForPlatform(String targetOS) => 'Specializing Platform getters for target OS $targetOS.'; final String usingTargetOSMessage = @@ -775,6 +776,37 @@ void main() { expect(result.exitCode, 0); }, skip: isRunningOnIA32); + test('Compile exe with asserts', () async { + final p = project(mainSrc: ''' +void main() { + assert(int.parse('1') == 2); +} +'''); + final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath)); + final outFile = path.canonicalize(path.join(p.dirPath, 'myexe')); + + final result = await p.run( + [ + 'compile', + 'exe', + '--enable-asserts', + '-o', + outFile, + inFile, + ], + ); + + // Only printed when -v/--verbose is used, not --verbosity. + expect(result.stdout, isNot(contains(usingTargetOSMessage))); + expect(result.stdout, isNot(contains(soundNullSafetyMessage))); + expect(result.stderr, isEmpty); + expect(result.exitCode, 0); + + final runResult = await Process.run(outFile, []); + expect(runResult.stdout, isEmpty); + expect(runResult.stderr, contains(failedAssertionError)); + }, skip: isRunningOnIA32); + test('Compile exe from kernel', () async { final p = project(mainSrc: ''' void main() {} @@ -1037,6 +1069,41 @@ void main() { expect(result.exitCode, 0); }, skip: isRunningOnIA32); + test('Compile AOT snapshot with asserts', () async { + final p = project(mainSrc: ''' +void main() { + assert(int.parse('1') == 2); +} +'''); + final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath)); + final outFile = path.canonicalize(path.join(p.dirPath, 'myaot')); + + var result = await p.run( + [ + 'compile', + 'aot-snapshot', + '--enable-asserts', + '-o', + outFile, + inFile, + ], + ); + + // Only printed when -v/--verbose is used, not --verbosity. + expect(result.stdout, isNot(contains(usingTargetOSMessage))); + expect(result.stdout, isNot(contains(soundNullSafetyMessage))); + expect(result.stderr, isEmpty); + expect(result.exitCode, 0); + + final Directory binDir = File(Platform.resolvedExecutable).parent; + result = await Process.run( + path.join(binDir.path, 'dartaotruntime'), + [outFile], + ); + expect(result.stdout, isEmpty); + expect(result.stderr, contains(failedAssertionError)); + }, skip: isRunningOnIA32); + test('Compile AOT snapshot from kernel', () async { final p = project(mainSrc: ''' void main() {} diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc index 2e2efe7c75e..8e09af2eb09 100644 --- a/runtime/vm/dart.cc +++ b/runtime/vm/dart.cc @@ -1030,9 +1030,14 @@ char* Dart::FeaturesString(IsolateGroup* isolate_group, ADD_FLAG(tsan, kTargetUsesThreadSanitizer) - // Enabling assertions affects deopt ids. - ADD_ISOLATE_GROUP_FLAG(asserts, enable_asserts, FLAG_enable_asserts); if (kind == Snapshot::kFullJIT) { + // Enabling assertions affects deopt ids. + // + // This flag is only used at compile time for AOT, so it's only relevant + // when running JIT snapshots. We can omit this flag for AOT snapshots so + // feature verification won't fail if --enable-snapshots isn't provided + // at runtime. + ADD_ISOLATE_GROUP_FLAG(asserts, enable_asserts, FLAG_enable_asserts); ADD_ISOLATE_GROUP_FLAG(use_field_guards, use_field_guards, FLAG_use_field_guards); ADD_ISOLATE_GROUP_FLAG(use_osr, use_osr, FLAG_use_osr);