diff --git a/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart b/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart index 7c8eb0894..8d3905f2c 100644 --- a/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart +++ b/pkgs/c_compiler/lib/src/cbuilder/run_cbuilder.dart @@ -136,6 +136,11 @@ class RunCBuilder { '-o', outDir.resolve('out.o').toFilePath(), ], + // TODO(https://github.com/dart-lang/native/issues/50): The defines + // should probably be configurable. That way, the mapping from + // build_mode to defines can be defined in a project-dependent way in + // each project build.dart. + '-D${buildConfig.buildMode.name.toUpperCase()}' ], logger: logger, captureOutput: false, @@ -170,6 +175,11 @@ class RunCBuilder { final result = await runProcess( executable: compiler.uri, arguments: [ + // TODO(https://github.com/dart-lang/native/issues/50): The defines + // should probably be configurable. That way, the mapping from + // build_mode to defines can be defined in a project-dependent way in + // each project build.dart. + '/D${buildConfig.buildMode.name.toUpperCase()}', if (executable != null) ...[ ...sources.map((e) => e.toFilePath()), '/link', diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_build_failure_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_build_failure_test.dart index 9f16d38b9..d87720527 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_build_failure_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_build_failure_test.dart @@ -35,6 +35,7 @@ void main() { packageRoot: tempUri, target: Target.current, linkModePreference: LinkModePreference.dynamic, + buildMode: BuildMode.release, cCompiler: CCompilerConfig( cc: cc, envScript: envScript, diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_android_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_android_test.dart index 6ea3520be..05cecc319 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_android_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_android_test.dart @@ -117,6 +117,7 @@ Future buildLib( packageRoot: tempUri, target: target, targetAndroidNdkApi: androidNdkApi, + buildMode: BuildMode.release, linkModePreference: linkMode == LinkMode.dynamic ? LinkModePreference.dynamic : LinkModePreference.static, diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_ios_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_ios_test.dart index 2271a04d3..154f3c52d 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_ios_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_ios_test.dart @@ -60,6 +60,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: target, + buildMode: BuildMode.release, linkModePreference: linkMode == LinkMode.dynamic ? LinkModePreference.dynamic : LinkModePreference.static, diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_linux_host_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_linux_host_test.dart index 014255448..cb28ce130 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_linux_host_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_linux_host_test.dart @@ -46,6 +46,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: target, + buildMode: BuildMode.release, linkModePreference: linkMode == LinkMode.dynamic ? LinkModePreference.dynamic : LinkModePreference.static, diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_macos_host_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_macos_host_test.dart index b68e924d0..0b14671a9 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_macos_host_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_macos_host_test.dart @@ -46,6 +46,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: target, + buildMode: BuildMode.release, linkModePreference: linkMode == LinkMode.dynamic ? LinkModePreference.dynamic : LinkModePreference.static, diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_windows_host_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_windows_host_test.dart index f00feeb8d..4f85f278a 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_cross_windows_host_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_cross_windows_host_test.dart @@ -58,6 +58,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: target, + buildMode: BuildMode.release, linkModePreference: linkMode == LinkMode.dynamic ? LinkModePreference.dynamic : LinkModePreference.static, diff --git a/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart b/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart index fa80dafaf..8047fa7f1 100644 --- a/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart +++ b/pkgs/c_compiler/test/cbuilder/cbuilder_test.dart @@ -19,49 +19,55 @@ import 'package:test/test.dart'; import '../helpers.dart'; void main() { - test('Cbuilder executable', () async { - await inTempDir((tempUri) async { - final helloWorldCUri = packageUri - .resolve('test/cbuilder/testfiles/hello_world/src/hello_world.c'); - if (!await File.fromUri(helloWorldCUri).exists()) { - throw Exception('Run the test from the root directory.'); - } - const name = 'hello_world'; + for (final buildMode in BuildMode.values) { + test('Cbuilder executable $buildMode', () async { + await inTempDir((tempUri) async { + final helloWorldCUri = packageUri + .resolve('test/cbuilder/testfiles/hello_world/src/hello_world.c'); + if (!await File.fromUri(helloWorldCUri).exists()) { + throw Exception('Run the test from the root directory.'); + } + const name = 'hello_world'; - final buildConfig = BuildConfig( - outDir: tempUri, - packageRoot: tempUri, - target: Target.current, - // Ignored by executables. - linkModePreference: LinkModePreference.dynamic, - cCompiler: CCompilerConfig( - cc: cc, - envScript: envScript, - envScriptArgs: envScriptArgs, - ), - ); - final buildOutput = BuildOutput(); - final cbuilder = CBuilder.executable( - name: name, - sources: [helloWorldCUri.toFilePath()], - ); - await cbuilder.run( - buildConfig: buildConfig, - buildOutput: buildOutput, - logger: logger, - ); + final buildConfig = BuildConfig( + outDir: tempUri, + packageRoot: tempUri, + target: Target.current, + buildMode: buildMode, + // Ignored by executables. + linkModePreference: LinkModePreference.dynamic, + cCompiler: CCompilerConfig( + cc: cc, + envScript: envScript, + envScriptArgs: envScriptArgs, + ), + ); + final buildOutput = BuildOutput(); + final cbuilder = CBuilder.executable( + name: name, + sources: [helloWorldCUri.toFilePath()], + ); + await cbuilder.run( + buildConfig: buildConfig, + buildOutput: buildOutput, + logger: logger, + ); - final executableUri = - tempUri.resolve(Target.current.os.executableFileName(name)); - expect(await File.fromUri(executableUri).exists(), true); - final result = await runProcess( - executable: executableUri, - logger: logger, - ); - expect(result.exitCode, 0); - expect(result.stdout.trim(), 'Hello world.'); + final executableUri = + tempUri.resolve(Target.current.os.executableFileName(name)); + expect(await File.fromUri(executableUri).exists(), true); + final result = await runProcess( + executable: executableUri, + logger: logger, + ); + expect(result.exitCode, 0); + if (buildMode == BuildMode.debug) { + expect(result.stdout.trim(), startsWith('Running in debug mode.')); + } + expect(result.stdout.trim(), endsWith('Hello world.')); + }); }); - }); + } for (final dryRun in [true, false]) { final testSuffix = dryRun ? ' dry_run' : ''; @@ -78,6 +84,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: Target.current, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, cCompiler: CCompilerConfig( cc: cc, diff --git a/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart b/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart index ca66929ce..733ea33dc 100644 --- a/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart +++ b/pkgs/c_compiler/test/cbuilder/compiler_resolver_test.dart @@ -44,6 +44,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: Target.current, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, cCompiler: CCompilerConfig( ar: ar, @@ -67,6 +68,7 @@ void main() { outDir: tempUri, packageRoot: tempUri, target: Target.windowsX64, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, ); final resolver = CompilerResolver( diff --git a/pkgs/c_compiler/test/cbuilder/testfiles/add/src/add.c b/pkgs/c_compiler/test/cbuilder/testfiles/add/src/add.c index d4955ee5d..6a16ccab6 100644 --- a/pkgs/c_compiler/test/cbuilder/testfiles/add/src/add.c +++ b/pkgs/c_compiler/test/cbuilder/testfiles/add/src/add.c @@ -4,6 +4,10 @@ #include +#ifdef DEBUG +#include +#endif + #if _WIN32 #define FFI_EXPORT __declspec(dllexport) #else @@ -11,5 +15,8 @@ #endif FFI_EXPORT int32_t add(int32_t a, int32_t b) { - return a + b; +#ifdef DEBUG + printf("Adding %i and %i.\n", a, b); +#endif + return a + b; } diff --git a/pkgs/c_compiler/test/cbuilder/testfiles/hello_world/src/hello_world.c b/pkgs/c_compiler/test/cbuilder/testfiles/hello_world/src/hello_world.c index 56180a119..2d4205935 100644 --- a/pkgs/c_compiler/test/cbuilder/testfiles/hello_world/src/hello_world.c +++ b/pkgs/c_compiler/test/cbuilder/testfiles/hello_world/src/hello_world.c @@ -5,6 +5,9 @@ #include int main() { - printf("Hello world.\n"); - return 0; +#ifdef DEBUG + printf("Running in debug mode.\n"); +#endif + printf("Hello world.\n"); + return 0; } diff --git a/pkgs/native_assets_cli/example/native_add/src/native_add.c b/pkgs/native_assets_cli/example/native_add/src/native_add.c index cf21076d1..6a107a839 100644 --- a/pkgs/native_assets_cli/example/native_add/src/native_add.c +++ b/pkgs/native_assets_cli/example/native_add/src/native_add.c @@ -4,6 +4,13 @@ #include "native_add.h" +#ifdef DEBUG +#include +#endif + int32_t add(int32_t a, int32_t b) { - return a + b; +#ifdef DEBUG + printf("Adding %i and %i.\n", a, b); +#endif + return a + b; } diff --git a/pkgs/native_assets_cli/lib/native_assets_cli.dart b/pkgs/native_assets_cli/lib/native_assets_cli.dart index b23ff3a2c..8ee3d3064 100644 --- a/pkgs/native_assets_cli/lib/native_assets_cli.dart +++ b/pkgs/native_assets_cli/lib/native_assets_cli.dart @@ -8,6 +8,7 @@ library native_assets_cli; export 'src/model/asset.dart'; export 'src/model/build_config.dart'; +export 'src/model/build_mode.dart'; export 'src/model/build_output.dart'; export 'src/model/dependencies.dart'; export 'src/model/ios_sdk.dart'; diff --git a/pkgs/native_assets_cli/lib/src/model/build_config.dart b/pkgs/native_assets_cli/lib/src/model/build_config.dart index db2d9cb49..78383d821 100644 --- a/pkgs/native_assets_cli/lib/src/model/build_config.dart +++ b/pkgs/native_assets_cli/lib/src/model/build_config.dart @@ -11,6 +11,7 @@ import 'package:pub_semver/pub_semver.dart'; import '../utils/map.dart'; import '../utils/yaml.dart'; +import 'build_mode.dart'; import 'ios_sdk.dart'; import 'link_mode_preference.dart'; import 'metadata.dart'; @@ -65,6 +66,10 @@ class BuildConfig { bool get dryRun => _dryRun ?? false; late final bool? _dryRun; + /// The build mode that the code should be compiled in. + BuildMode get buildMode => _buildMode; + late final BuildMode _buildMode; + /// The underlying config. /// /// Can be used for easier access to values on [dependencyMetadata]. @@ -74,6 +79,7 @@ class BuildConfig { factory BuildConfig({ required Uri outDir, required Uri packageRoot, + required BuildMode buildMode, required Target target, IOSSdk? targetIOSSdk, int? targetAndroidNdkApi, @@ -85,6 +91,7 @@ class BuildConfig { final nonValidated = BuildConfig._() .._outDir = outDir .._packageRoot = packageRoot + .._buildMode = buildMode .._target = target .._targetIOSSdk = targetIOSSdk .._targetAndroidNdkApi = targetAndroidNdkApi @@ -107,6 +114,7 @@ class BuildConfig { static String checksum({ required Uri packageRoot, required Target target, + required BuildMode buildMode, IOSSdk? targetIOSSdk, int? targetAndroidNdkApi, CCompilerConfig? cCompiler, @@ -119,6 +127,7 @@ class BuildConfig { target.toString(), targetIOSSdk.toString(), targetAndroidNdkApi.toString(), + buildMode.toString(), linkModePreference.toString(), cCompiler?.ar.toString(), cCompiler?.cc.toString(), @@ -228,6 +237,12 @@ class BuildConfig { (config) => _outDir = config.path(outDirConfigKey, mustExist: true), (config) => _packageRoot = config.path(packageRootConfigKey, mustExist: true), + (config) => _buildMode = BuildMode.fromString( + config.string( + BuildMode.configKey, + validValues: BuildMode.values.map((e) => '$e'), + ), + ), (config) { _target = Target.fromString( config.string( @@ -312,6 +327,7 @@ class BuildConfig { return { outDirConfigKey: _outDir.toFilePath(), packageRootConfigKey: _packageRoot.toFilePath(), + BuildMode.configKey: _buildMode.toString(), Target.configKey: _target.toString(), if (_targetIOSSdk != null) IOSSdk.configKey: _targetIOSSdk.toString(), if (_targetAndroidNdkApi != null) @@ -337,6 +353,7 @@ class BuildConfig { } if (other._outDir != _outDir) return false; if (other._packageRoot != _packageRoot) return false; + if (other._buildMode != _buildMode) return false; if (other._target != _target) return false; if (other._targetIOSSdk != _targetIOSSdk) return false; if (other._targetAndroidNdkApi != _targetAndroidNdkApi) return false; @@ -352,6 +369,7 @@ class BuildConfig { int get hashCode => Object.hash( _outDir, _packageRoot, + _buildMode, _target, _targetIOSSdk, _targetAndroidNdkApi, diff --git a/pkgs/native_assets_cli/lib/src/model/build_mode.dart b/pkgs/native_assets_cli/lib/src/model/build_mode.dart new file mode 100644 index 000000000..8b8cd3ceb --- /dev/null +++ b/pkgs/native_assets_cli/lib/src/model/build_mode.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +class BuildMode { + final String name; + + const BuildMode._(this.name); + + static const debug = BuildMode._('debug'); + static const release = BuildMode._('release'); + + static const values = [ + debug, + release, + ]; + + factory BuildMode.fromString(String target) => + values.firstWhere((e) => e.name == target); + + /// The `package:config` key preferably used. + static const String configKey = 'build_mode'; + + @override + String toString() => name; +} diff --git a/pkgs/native_assets_cli/test/example/native_add_test.dart b/pkgs/native_assets_cli/test/example/native_add_test.dart index b650b1b72..e46f1e346 100644 --- a/pkgs/native_assets_cli/test/example/native_add_test.dart +++ b/pkgs/native_assets_cli/test/example/native_add_test.dart @@ -41,6 +41,7 @@ void main() async { '-Dout_dir=${tempUri.toFilePath()}', '-Dpackage_root=${testPackageUri.toFilePath()}', '-Dtarget=${Target.current}', + '-Dbuild_mode=debug', '-Dlink_mode_preference=dynamic', if (cc != null) '-Dcc=${cc!.toFilePath()}', if (envScript != null) diff --git a/pkgs/native_assets_cli/test/model/build_config_test.dart b/pkgs/native_assets_cli/test/model/build_config_test.dart index 2c65f4496..7259228e9 100644 --- a/pkgs/native_assets_cli/test/model/build_config_test.dart +++ b/pkgs/native_assets_cli/test/model/build_config_test.dart @@ -56,6 +56,7 @@ void main() async { ld: fakeLd, ar: fakeAr, ), + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, ); @@ -64,6 +65,7 @@ void main() async { packageRoot: tempUri, target: Target.androidArm64, targetAndroidNdkApi: 30, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, ); @@ -90,11 +92,13 @@ void main() async { packageRoot: packageRootUri, target: Target.androidArm64, targetAndroidNdkApi: 30, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, dryRun: true, ); final config = Config(fileParsed: { + 'build_mode': 'release', 'dry_run': true, 'link_mode_preference': 'prefer-static', 'out_dir': outDirUri.toFilePath(), @@ -118,6 +122,7 @@ void main() async { cc: fakeClang, ld: fakeLd, ), + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, ); @@ -133,6 +138,7 @@ void main() async { packageRoot: tempUri, target: Target.androidArm64, targetAndroidNdkApi: 30, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, dependencyMetadata: { 'bar': Metadata({ @@ -150,6 +156,7 @@ void main() async { packageRoot: tempUri, target: Target.androidArm64, targetAndroidNdkApi: 30, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, dependencyMetadata: { 'bar': Metadata({ @@ -177,6 +184,7 @@ void main() async { cc: fakeClang, ld: fakeLd, ), + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, // This map should be sorted on key for two layers. dependencyMetadata: { @@ -190,7 +198,8 @@ void main() async { }, ); final yamlString = buildConfig1.toYamlString(); - final expectedYamlString = '''c_compiler: + final expectedYamlString = '''build_mode: release +c_compiler: cc: ${fakeClang.toFilePath()} ld: ${fakeLd.toFilePath()} dependency_metadata: @@ -307,6 +316,7 @@ version: ${BuildConfig.version}'''; cc: fakeClang, ld: fakeLd, ), + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, ); config.toString(); @@ -318,6 +328,7 @@ version: ${BuildConfig.version}'''; packageRoot: tempUri, target: Target.androidArm64, targetAndroidNdkApi: 30, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, ); final configFileContents = buildConfig.toYamlString(); @@ -337,6 +348,7 @@ version: ${BuildConfig.version}'''; packageRoot: tempUri, target: Target.androidArm64, targetAndroidNdkApi: 30, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.preferStatic, dependencyMetadata: { 'bar': Metadata({ @@ -366,6 +378,7 @@ version: ${BuildConfig.version}'''; envScript: fakeVcVars, envScriptArgs: ['x64'], ), + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, ); @@ -406,16 +419,18 @@ version: ${BuildConfig.version}'''; final name1 = BuildConfig.checksum( packageRoot: nativeAddUri, target: Target.linuxX64, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, ); // Using the checksum for a build folder should be stable. - expect(name1, '02dce8b58210deaf9f278772e892d01f'); + expect(name1, '05b54381626750e570c92d255bb09390'); // Build folder different due to metadata. final name2 = BuildConfig.checksum( packageRoot: nativeAddUri, target: Target.linuxX64, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, dependencyMetadata: { 'foo': Metadata({'key': 'value'}) @@ -428,6 +443,7 @@ version: ${BuildConfig.version}'''; final name3 = BuildConfig.checksum( packageRoot: nativeAddUri, target: Target.linuxX64, + buildMode: BuildMode.release, linkModePreference: LinkModePreference.dynamic, cCompiler: CCompilerConfig( cc: fakeClangUri,